4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
21 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
22 * Use is subject to license terms.
24 * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
27 * Portions of this source code were derived from Berkeley
28 * 4.3 BSD under license from the Regents of the University of
32 * Copyright (c) 2016 by Delphix. All rights reserved.
34 #pragma ident "%Z%%M% %I% %E% SMI"
38 extern int gettimeofday(struct timeval
*);
40 #include <sys/types.h>
49 #include <sys/types.h>
55 #include <rpc/nettype.h>
56 #include <rpc/rpcb_prot.h>
57 #include <rpc/rpcb_clnt.h>
58 #include <sys/systeminfo.h>
59 #include <sys/select.h>
69 #define YPPROG ((ulong_t)109999)
71 #define YPBINDPROG ((ulong_t)109998)
74 #define INTER_TRY 12 /* Seconds between tries */
75 #define PORTMAP_TIME 30 /* Seconds before decide its down */
76 #define TIMEOUT INTER_TRY*4 /* Total time for timeout */
77 #define CUR_PAR 4 /* Total parallal yppushes */
78 #define MIN_GRACE 25 /* select timeout and minimum grace */
79 #define GRACE_PERIOD 800 /* Total seconds we'll wait for */
80 /* responses from ypxfrs, yes */
81 /* virginia yp map transfers */
82 /* can take a long time, we */
83 /* only worry if the slave */
88 static char *domain
= NULL
;
89 static char *host
= NULL
;
90 static char my_name
[YPMAXPEER
+1];
91 static char default_domain_name
[YPMAXDOMAIN
];
92 static char domain_alias
[MAXNAMLEN
]; /* nickname for domain - */
93 /* used in sysv filesystems */
94 static char map_alias
[MAXNAMLEN
]; /* nickname for map - */
95 /* used in sysv filesystems */
96 static char *map
= NULL
;
97 static bool verbose
= FALSE
;
98 static bool onehost
= FALSE
;
99 static bool oldxfr
= FALSE
;
100 static bool callback_timeout
= FALSE
; /* set when a callback times out */
101 int grace_period
= GRACE_PERIOD
;
102 int curpar
= CUR_PAR
; /* should be set by other stuff */
103 static char ypmapname
[1024]; /* Used to check for map's existence */
105 static struct timeval intertry
= {
106 INTER_TRY
, /* Seconds */
109 static struct timeval timeout
= {
110 TIMEOUT
, /* Seconds */
113 static SVCXPRT
*transport4
;
114 static SVCXPRT
*transport6
;
116 struct server
*pnext
;
117 struct dom_binding domb
;
118 char svc_name
[YPMAXPEER
+1];
119 unsigned long xactid
;
120 unsigned short state
;
121 unsigned long status
;
125 #define n_conf dom_binding->ypbind_nconf
126 #define svc_addr dom_binding->ypbind_svcaddr
127 static struct server
*server_list
= NULL
;
128 static struct server
*active_list
= NULL
;
130 /* State values for server.state field */
133 #define SSTAT_CALLED 1
134 #define SSTAT_RESPONDED 2
135 #define SSTAT_PROGNOTREG 3
137 #define SSTAT_RSCRC 5
138 #define SSTAT_SYSTEM 6
140 static char err_usage
[] =
141 "Usage:\n\typpush [-p <par>] [-d <domainname>] [-h <hostname>] [-v] map\n";
142 static char err_bad_args
[] =
143 "The %s argument is bad.\n";
144 static char err_cant_get_kname
[] =
145 "Can't get %s from system call.\n";
146 static char err_null_kname
[] =
147 "The %s hasn't been set on this machine.\n";
148 static char err_bad_domainname
[] = "domainname";
149 static char err_cant_bind
[] =
150 "Can't find a yp server for domain %s. Reason: %s.\n";
151 static char err_cant_build_serverlist
[] =
152 "Can't build server list from map \"ypservers\". Reason: %s.\n";
153 static char err_cant_find_host
[] =
154 "Can't find host %s in map \"ypservers\".\n";
156 * State_duple table. All messages should take 1 arg - the node name.
162 static struct state_duple state_duples
[] = {
163 {SSTAT_INIT
, "Internal error trying to talk to %s."},
164 {SSTAT_CALLED
, "%s has been called."},
165 {SSTAT_RESPONDED
, "%s (v1 ypserv) sent an old-style request."},
166 {SSTAT_PROGNOTREG
, "nis server not registered at %s."},
167 {SSTAT_RPC
, "RPC error to %s: "},
168 {SSTAT_RSCRC
, "Local resource allocation failure - can't talk to %s."},
169 {SSTAT_SYSTEM
, "System error talking to %s: "},
173 * Status_duple table. No messages should require any args.
175 struct status_duple
{
179 static struct status_duple status_duples
[] = {
180 {YPPUSH_SUCC
, "Map successfully transferred."},
182 "Transfer not done: master's version isn't newer."},
183 {YPPUSH_NOMAP
, "Failed - ypxfr there can't find a server for map."},
184 {YPPUSH_NODOM
, "Failed - domain isn't supported."},
185 {YPPUSH_RSRC
, "Failed - local resource allocation failure."},
186 {YPPUSH_RPC
, "Failed - ypxfr had an RPC failure"},
187 {YPPUSH_MADDR
, "Failed - ypxfr couldn't get the map master's address."},
188 {YPPUSH_YPERR
, "Failed - nis server or map format error."},
189 {YPPUSH_BADARGS
, "Failed - args to ypxfr were bad."},
190 {YPPUSH_DBM
, "Failed - dbm operation on map failed."},
191 {YPPUSH_FILE
, "Failed - file I/O operation on map failed"},
192 {YPPUSH_SKEW
, "Failed - map version skew during transfer."},
194 "Map successfully transferred, but ypxfr \
195 couldn't send \"Clear map\" to ypserv "},
197 "Failed - no local order number in map - use -f flag to ypxfr."},
198 {YPPUSH_XFRERR
, "Failed - ypxfr internal error."},
199 {YPPUSH_REFUSED
, "Failed - Transfer request refused."},
201 "Failed - System V domain/map alias not in alias file."},
207 struct rpcerr_duple
{
208 enum clnt_stat rpc_stat
;
211 static struct rpcerr_duple rpcerr_duples
[] = {
212 {RPC_SUCCESS
, "RPC success"},
213 {RPC_CANTENCODEARGS
, "RPC Can't encode args"},
214 {RPC_CANTDECODERES
, "RPC Can't decode results"},
215 {RPC_CANTSEND
, "RPC Can't send"},
216 {RPC_CANTRECV
, "RPC Can't recv"},
217 {RPC_TIMEDOUT
, "NIS server registered, but does not respond"},
218 {RPC_VERSMISMATCH
, "RPC version mismatch"},
219 {RPC_AUTHERROR
, "RPC auth error"},
220 {RPC_PROGUNAVAIL
, "RPC remote program unavailable"},
221 {RPC_PROGVERSMISMATCH
, "RPC program mismatch"},
222 {RPC_PROCUNAVAIL
, "RPC unknown procedure"},
223 {RPC_CANTDECODEARGS
, "RPC Can't decode args"},
224 {RPC_UNKNOWNHOST
, "unknown host"},
225 {RPC_RPCBFAILURE
, "rpcbind failure (host is down?)"},
226 {RPC_PROGNOTREGISTERED
, "RPC prog not registered"},
227 {RPC_SYSTEMERROR
, "RPC system error"},
228 {RPC_SUCCESS
, NULL
} /* Duplicate rpc_stat */
229 /* unused in list-end */
233 static void get_default_domain_name(void);
234 static void get_command_line_args(int argc
, char **argv
);
235 static unsigned short send_message(struct server
*ps
,
236 unsigned long program
, long *err
);
237 static void make_server_list(void);
238 static void one_host_list(void);
239 static void add_server(char *sname
, int namelen
);
240 static int generate_callback(unsigned long *program
);
241 static void xactid_seed(unsigned long *xactid
);
242 static void main_loop(unsigned long program
);
243 static void listener_exit(unsigned long program
, int stat
);
244 static void listener_dispatch(struct svc_req
*rqstp
, SVCXPRT
*transp
);
245 static void print_state_msg(struct server
*s
, long e
);
246 static void print_callback_msg(struct server
*s
);
247 static void rpcerr_msg(enum clnt_stat e
);
248 static void get_xfr_response(SVCXPRT
*transp
);
251 extern void sysvconfig(void);
253 extern int yp_getalias(char *key
, char *key_alias
, int maxlen
);
254 extern int getdomainname(char *, int);
256 extern CLIENT
*__yp_clnt_create_rsvdport();
259 main(int argc
, char **argv
)
261 unsigned long program
;
264 get_command_line_args(argc
, argv
);
267 get_default_domain_name();
274 if (yp_getalias(domain
, domain_alias
, NAME_MAX
) != 0)
275 fprintf(stderr
, "domain alias for %s not found\n", domain
);
276 if (yp_getalias(map
, map_alias
, MAXALIASLEN
) != 0)
277 fprintf(stderr
, "map alias for %s not found\n", map
);
279 /* check to see if the map exists in this domain */
281 sprintf(ypmapname
, "%s/%s/%s%s.dir", ypdbpath
, domain_alias
,
282 NTOL_PREFIX
, map_alias
);
284 sprintf(ypmapname
, "%s/%s/%s.dir", ypdbpath
, domain_alias
,
286 if (stat64(ypmapname
, &sbuf
) < 0) {
287 fprintf(stderr
, "yppush: Map does not exist.\n");
298 * All process exits after the call to generate_callback should be
299 * through listener_exit(program, status), not exit(status), so the
300 * transient server can get unregistered with the portmapper.
303 if (!generate_callback(&program
)) {
304 fprintf(stderr
, "Can't set up transient callback server.\n");
309 listener_exit(program
, 0);
316 * This does the command line parsing.
319 get_command_line_args(int argc
, char **argv
)
325 fprintf(stderr
, pusage
);
330 if ((*argv
)[0] == '-') {
331 switch ((*argv
)[1]) {
342 if (((int)strlen(domain
)) >
350 fprintf(stderr
, pusage
);
362 fprintf(stderr
, pusage
);
372 if (sscanf(*argv
, "%d", &curpar
) != 1) {
373 (void) fprintf(stderr
, pusage
);
378 (void) fprintf(stderr
, pusage
);
382 (void) fprintf(stderr
, pusage
);
388 fprintf(stderr
, pusage
);
395 fprintf(stderr
, pusage
);
403 fprintf(stderr
, pusage
);
409 * This gets the local kernel domainname, and sets the global domain to it.
412 get_default_domain_name(void)
414 if (!getdomainname(default_domain_name
, YPMAXDOMAIN
)) {
415 domain
= default_domain_name
;
417 fprintf(stderr
, err_cant_get_kname
, err_bad_domainname
);
421 if ((int)strlen(domain
) == 0) {
422 fprintf(stderr
, err_null_kname
, err_bad_domainname
);
428 * This verifies that the hostname supplied by the user is in the map
429 * "ypservers" then calls add_server to make it the only entry on the
440 char *ypservers
= "ypservers";
443 printf("Verifying YP server: %s\n", host
);
447 if (err
= yp_bind(domain_alias
)) {
448 fprintf(stderr
, err_cant_bind
, domain
, yperr_string(err
));
452 keylen
= strlen(host
);
454 if (yp_match(domain_alias
, ypservers
, host
, keylen
,
456 fprintf(stderr
, err_cant_find_host
, host
);
460 add_server(host
, keylen
);
464 * This uses yp operations to retrieve each server name in the map
465 * "ypservers". add_server is called for each one to add it to the list of
469 make_server_list(void)
478 char *ypservers
= "ypservers";
482 printf("Finding YP servers: ");
487 if (err
= yp_bind(domain_alias
)) {
488 fprintf(stderr
, err_cant_bind
, domain
, yperr_string(err
));
492 if (err
= yp_first(domain_alias
, ypservers
, &outkey
, &outkeylen
,
494 fprintf(stderr
, err_cant_build_serverlist
, yperr_string(err
));
499 add_server(outkey
, outkeylen
);
501 printf(" %s", outkey
);
512 if (err
= yp_next(domain_alias
, ypservers
, key
, keylen
,
513 &outkey
, &outkeylen
, &val
, &vallen
)) {
515 if (err
== YPERR_NOMORE
) {
518 fprintf(stderr
, err_cant_build_serverlist
,
533 * This adds a single server to the server list.
536 add_server(char *sname
, int namelen
)
539 static unsigned long seq
;
540 static unsigned long xactid
= 0;
542 if (strcmp(sname
, my_name
) == 0)
546 xactid_seed(&xactid
);
549 if ((ps
= (struct server
*)malloc((unsigned)sizeof (struct server
)))
551 perror("yppush: malloc failure");
555 sname
[namelen
] = '\0';
556 strcpy(ps
->svc_name
, sname
);
557 ps
->state
= SSTAT_INIT
;
560 ps
->xactid
= xactid
+ seq
++;
561 ps
->pnext
= server_list
;
566 * This sets the base range for the transaction ids used in speaking the the
567 * server ypxfr processes.
570 xactid_seed(unsigned long *xactid
)
574 if (gettimeofday(&t
) == -1) {
575 perror("yppush gettimeofday failure");
583 * This generates the channel which will be used as the listener process'
584 * service rendezvous point, and comes up with a transient program number
585 * for the use of the RPC messages from the ypxfr processes.
588 generate_callback(unsigned long *program
)
590 unsigned long prognum
= 0x40000000, maxprognum
;
593 unsigned char b
[sizeof (unsigned long)];
596 struct netconfig
*nc4
, *nc6
, *nc
;
599 nc4
= getnetconfigent("udp");
600 nc6
= getnetconfigent("udp6");
601 if (nc4
== 0 && nc6
== 0) {
603 "yppush: Could not get udp or udp6 netconfig entry\n");
607 transport4
= (nc4
== 0) ? 0 : svc_tli_create(RPC_ANYFD
, nc4
, 0, 0, 0);
608 transport6
= (nc6
== 0) ? 0 : svc_tli_create(RPC_ANYFD
, nc6
, 0, 0, 0);
609 if (transport4
== 0 && transport6
== 0) {
610 fprintf(stderr
, "yppush: Could not create server handle(s)\n");
614 /* Find the maximum possible program number using an unsigned long */
615 for (i
= 0; i
< sizeof (u
.b
); i
++)
619 if (transport4
!= 0) {
626 while (prognum
< maxprognum
&& (ret
=
627 rpcb_set(prognum
, YPPUSHVERS
, nc
, &trans
->xp_ltaddr
)) == 0)
631 fprintf(stderr
, "yppush: Could not create callback service\n");
634 if (trans
== transport4
&& transport6
!= 0) {
635 ret
= rpcb_set(prognum
, YPPUSHVERS
, nc6
,
636 &transport6
->xp_ltaddr
);
639 "yppush: Could not create udp6 callback service\n");
650 * This is the main loop. Send messages to each server,
651 * and then wait for a response.
662 server_list
= server_list
->pnext
; /* delete from server_list */
663 ps
->pnext
= active_list
;
674 if (in
== active_list
) {
675 active_list
= active_list
->pnext
;
679 for (n
= active_list
; n
; n
= n
->pnext
) {
692 unsigned long program
;
694 pollfd_t
*pollset
= NULL
;
699 int hpar
; /* this times par count */
707 if (grace_period
< MIN_GRACE
)
708 grace_period
= MIN_GRACE
;
709 if (transport4
!= 0) {
710 if (!svc_reg(transport4
, program
, YPPUSHVERS
,
711 listener_dispatch
, 0)) {
713 "Can't set up transient udp callback server.\n");
716 if (transport6
!= 0) {
717 if (!svc_reg(transport6
, program
, YPPUSHVERS
,
718 listener_dispatch
, 0)) {
720 "Can't set up transient udp6 callback server.\n");
725 if (server_list
== NULL
) {
728 for (ps
= active_list
; ps
; ps
= ps
->pnext
)
729 if (ps
->state
== SSTAT_CALLED
) {
730 if ((time_now
- ps
->start_time
) <
738 printf("terminating %d dead\n", dead
);
742 for (ps
= active_list
; ps
; ps
= ps
->pnext
)
743 if (ps
->state
== SSTAT_CALLED
) {
744 if ((time_now
- ps
->start_time
)
748 "no response from %s -- grace of %d seconds expired.\n",
749 ps
->svc_name
, grace_period
);
753 "No response from ypxfr on %s\n", ps
->svc_name
);
760 for (ps
= active_list
; ps
; ps
= ps
->pnext
) {
761 if (ps
->state
== SSTAT_CALLED
) {
762 if ((time_now
- ps
->start_time
)
768 "No response yet from ypxfr on %s\n", ps
->svc_name
);
774 printf("Deactivating %s\n",
782 /* add someone to the active list keep up with curpar */
783 for (i
= 0; i
< (curpar
- actives
); i
++) {
784 if (add_to_active()) {
786 ps
->state
= send_message(ps
, program
, &error
);
787 print_state_msg(ps
, error
);
788 if (ps
->state
!= SSTAT_CALLED
)
789 delete_active(ps
); /* zorch it */
791 ps
->start_time
= time(0); /* set time */
795 for (ps
= active_list
; ps
; ps
= ps
->pnext
)
796 if (ps
->state
== SSTAT_CALLED
) {
802 printf("No one to wait for this pass.\n");
805 continue; /* try curpar more */
808 if (npollfds
!= svc_max_pollfd
) {
809 pollset
= reallocarray(pollset
, svc_max_pollfd
,
811 npollfds
= svc_max_pollfd
;
815 * Get existing array of pollfd's, should really compress
816 * this but it shouldn't get very large (or sparse).
818 (void) memcpy(pollset
, svc_pollfd
,
819 sizeof (pollfd_t
) * svc_max_pollfd
);
822 switch (pollret
= poll(pollset
, npollfds
, MIN_GRACE
* 1000)) {
824 if (errno
!= EINTR
) {
825 (void) perror("main loop select");
831 (void) printf("timeout in main loop select.\n");
837 svc_getreq_poll(pollset
, pollret
);
844 * This does the listener process cleanup and process exit.
847 listener_exit(unsigned long program
, int stat
)
849 svc_unreg(program
, YPPUSHVERS
);
854 * This is the listener process' RPC service dispatcher.
857 listener_dispatch(struct svc_req
*rqstp
, SVCXPRT
*transp
)
859 switch (rqstp
->rq_proc
) {
861 case YPPUSHPROC_NULL
:
862 if (!svc_sendreply(transp
, xdr_void
, 0)) {
863 fprintf(stderr
, "Can't reply to rpc call.\n");
867 case YPPUSHPROC_XFRRESP
:
868 get_xfr_response(transp
);
872 svcerr_noproc(transp
);
879 * This dumps a server state message to stdout. It is called in cases where
880 * we have no expectation of receiving a callback from the remote ypxfr.
883 print_state_msg(struct server
*s
, long e
)
885 struct state_duple
*sd
;
887 if (s
->state
== SSTAT_SYSTEM
)
888 return; /* already printed */
890 if (!verbose
&& (s
->state
== SSTAT_RESPONDED
||
891 s
->state
== SSTAT_CALLED
))
894 for (sd
= state_duples
; sd
->state_msg
; sd
++) {
895 if (sd
->state
== s
->state
) {
896 printf(sd
->state_msg
, s
->svc_name
);
898 if (s
->state
== SSTAT_RPC
) {
899 rpcerr_msg((enum clnt_stat
) e
);
908 fprintf(stderr
, "yppush: Bad server state value %d.\n", s
->state
);
912 * This dumps a transfer status message to stdout. It is called in
913 * response to a received RPC message from the called ypxfr.
916 print_callback_msg(struct server
*s
)
918 register struct status_duple
*sd
;
921 (s
->status
== YPPUSH_AGE
) ||
922 (s
->status
== YPPUSH_SUCC
))
926 for (sd
= status_duples
; sd
->status_msg
; sd
++) {
928 if (sd
->status
== s
->status
) {
929 printf("Status received from ypxfr on %s:\n\t%s\n",
930 s
->svc_name
, sd
->status_msg
);
936 fprintf(stderr
, "yppush listener: Garbage transaction "
937 "status (value %d) from ypxfr on %s.\n",
938 (int)s
->status
, s
->svc_name
);
942 * This dumps an RPC error message to stdout. This is basically a rewrite
943 * of clnt_perrno, but writes to stdout instead of stderr.
946 rpcerr_msg(enum clnt_stat e
)
948 struct rpcerr_duple
*rd
;
950 for (rd
= rpcerr_duples
; rd
->rpc_msg
; rd
++) {
952 if (rd
->rpc_stat
== e
) {
958 fprintf(stderr
, "Bad error code passed to rpcerr_msg: %d.\n", e
);
962 * This picks up the response from the ypxfr process which has been started
963 * up on the remote node. The response status must be non-zero, otherwise
964 * the status will be set to "ypxfr error".
967 get_xfr_response(SVCXPRT
*transp
)
969 struct yppushresp_xfr resp
;
970 register struct server
*s
;
972 if (!svc_getargs(transp
, (xdrproc_t
)xdr_yppushresp_xfr
,
974 svcerr_decode(transp
);
978 if (!svc_sendreply(transp
, xdr_void
, 0)) {
979 (void) fprintf(stderr
, "Can't reply to rpc call.\n");
982 for (s
= active_list
; s
; s
= s
->pnext
) {
984 if (s
->xactid
== resp
.transid
) {
985 s
->status
= resp
.status
? resp
.status
: YPPUSH_XFRERR
;
986 print_callback_msg(s
);
987 s
->state
= SSTAT_RESPONDED
;
994 * This sends a message to a single ypserv process. The return value is
995 * a state value. If the RPC call fails because of a version
996 * mismatch, we'll assume that we're talking to a version 1 ypserv process,
997 * and will send it an old "YPPROC_GET" request, as was defined in the
998 * earlier version of yp_prot.h
1000 static unsigned short
1001 send_message(struct server
*ps
, unsigned long program
, long *err
)
1003 struct ypreq_newxfr req
;
1004 struct ypreq_xfr oldreq
;
1006 struct rpc_err rpcerr
;
1008 if ((ps
->domb
.dom_client
= __yp_clnt_create_rsvdport(ps
->svc_name
,
1009 YPPROG
, YPVERS
, NULL
, 0, 0)) == NULL
) {
1011 if (rpc_createerr
.cf_stat
== RPC_PROGNOTREGISTERED
) {
1012 return (SSTAT_PROGNOTREG
);
1014 printf("Error talking to %s: ", ps
->svc_name
);
1015 rpcerr_msg(rpc_createerr
.cf_stat
);
1018 return (SSTAT_SYSTEM
);
1022 if (sysinfo(SI_HOSTNAME
, my_name
, sizeof (my_name
)) == -1) {
1023 return (SSTAT_RSCRC
);
1027 req
.ypxfr_domain
= domain
;
1028 req
.ypxfr_map
= map
;
1029 req
.ypxfr_ordernum
= 0;
1030 req
.ypxfr_owner
= my_name
;
1031 req
.name
= ps
->svc_name
;
1033 * the creation of field req.name, instead of ypreq_xfr (old)
1034 * req.port, does not make any sense. it doesn't give any
1035 * information to receiving ypserv except its own name !!
1036 * new ypserv duplicates work for YPPROC_XFR and YPPROC_NEWXFR
1038 req
.transid
= ps
->xactid
;
1039 req
.proto
= program
;
1040 s
= (enum clnt_stat
) clnt_call(ps
->domb
.dom_client
,
1041 YPPROC_NEWXFR
, (xdrproc_t
)xdr_ypreq_newxfr
, (caddr_t
)&req
,
1042 xdr_void
, 0, timeout
);
1045 clnt_geterr(ps
->domb
.dom_client
, &rpcerr
);
1047 if (s
== RPC_PROCUNAVAIL
) {
1048 oldreq
.ypxfr_domain
= domain
;
1049 oldreq
.ypxfr_map
= map
;
1050 oldreq
.ypxfr_ordernum
= 0;
1051 oldreq
.ypxfr_owner
= my_name
;
1052 oldreq
.transid
= ps
->xactid
;
1053 oldreq
.proto
= program
;
1055 s
= (enum clnt_stat
) clnt_call(ps
->domb
.dom_client
,
1056 YPPROC_XFR
, (xdrproc_t
)xdr_ypreq_xfr
, (caddr_t
)&oldreq
,
1057 xdr_void
, 0, timeout
);
1058 clnt_geterr(ps
->domb
.dom_client
, &rpcerr
);
1061 clnt_destroy(ps
->domb
.dom_client
);
1063 if (s
== RPC_SUCCESS
) {
1064 return (SSTAT_CALLED
);
1066 *err
= (long)rpcerr
.re_status
;
1073 * FUNCTION: is_yptol_mode();
1075 * DESCRIPTION: Determines if we should run in N2L or traditional mode based
1076 * on the presence of the N2L mapping file.
1078 * This is a copy of a function from libnisdb. If more than this
1079 * one function become required it may be worth linking the
1084 * OUTPUTS: TRUE = Run in N2L mode
1085 * FALSE = Run in traditional mode.
1090 struct stat filestat
;
1092 if (stat(NTOL_MAP_FILE
, &filestat
) != -1)