xref: /illumos-gate/usr/src/cmd/ypcmd/yppush.c (revision 7c478bd95313f5f23a4c958a745db2134aa0324)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  *
22*7c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
23*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
24*7c478bd9Sstevel@tonic-gate  *
25*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
26*7c478bd9Sstevel@tonic-gate  * All Rights Reserved
27*7c478bd9Sstevel@tonic-gate  *
28*7c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley
29*7c478bd9Sstevel@tonic-gate  * 4.3 BSD under license from the Regents of the University of
30*7c478bd9Sstevel@tonic-gate  * California.
31*7c478bd9Sstevel@tonic-gate  */
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate #define	_SVID_GETTOD
36*7c478bd9Sstevel@tonic-gate #include	<sys/time.h>
37*7c478bd9Sstevel@tonic-gate extern int gettimeofday(struct timeval *);
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate #include	<sys/types.h>
40*7c478bd9Sstevel@tonic-gate #include	<stdio.h>
41*7c478bd9Sstevel@tonic-gate #include	<string.h>
42*7c478bd9Sstevel@tonic-gate #include	<malloc.h>
43*7c478bd9Sstevel@tonic-gate #include	<errno.h>
44*7c478bd9Sstevel@tonic-gate #include	<signal.h>
45*7c478bd9Sstevel@tonic-gate #include	<limits.h>
46*7c478bd9Sstevel@tonic-gate #include	<stdlib.h>
47*7c478bd9Sstevel@tonic-gate #include	<unistd.h>
48*7c478bd9Sstevel@tonic-gate #include	<sys/types.h>
49*7c478bd9Sstevel@tonic-gate #include	<sys/wait.h>
50*7c478bd9Sstevel@tonic-gate #include	<sys/stat.h>
51*7c478bd9Sstevel@tonic-gate #include	<ctype.h>
52*7c478bd9Sstevel@tonic-gate #include	<dirent.h>
53*7c478bd9Sstevel@tonic-gate #include	<rpc/rpc.h>
54*7c478bd9Sstevel@tonic-gate #include	<rpc/nettype.h>
55*7c478bd9Sstevel@tonic-gate #include	<rpc/rpcb_prot.h>
56*7c478bd9Sstevel@tonic-gate #include	<rpc/rpcb_clnt.h>
57*7c478bd9Sstevel@tonic-gate #include	<sys/systeminfo.h>
58*7c478bd9Sstevel@tonic-gate #include	<sys/select.h>
59*7c478bd9Sstevel@tonic-gate #include	"ypsym.h"
60*7c478bd9Sstevel@tonic-gate #include	"ypdefs.h"
61*7c478bd9Sstevel@tonic-gate #include	"yp_b.h"
62*7c478bd9Sstevel@tonic-gate #include	"shim.h"
63*7c478bd9Sstevel@tonic-gate #include	"yptol.h"
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
67*7c478bd9Sstevel@tonic-gate #undef YPPROG
68*7c478bd9Sstevel@tonic-gate #define	YPPROG ((ulong_t)109999)
69*7c478bd9Sstevel@tonic-gate #undef YPBINDPROG
70*7c478bd9Sstevel@tonic-gate #define	YPBINDPROG ((ulong_t)109998)
71*7c478bd9Sstevel@tonic-gate #endif
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate #define	INTER_TRY 12			/* Seconds between tries */
74*7c478bd9Sstevel@tonic-gate #define	PORTMAP_TIME 30			/* Seconds before decide its down */
75*7c478bd9Sstevel@tonic-gate #define	TIMEOUT INTER_TRY*4		/* Total time for timeout */
76*7c478bd9Sstevel@tonic-gate #define	CUR_PAR 4			/* Total  parallal yppushes */
77*7c478bd9Sstevel@tonic-gate #define	MIN_GRACE 25			/* select timeout and minimum grace */
78*7c478bd9Sstevel@tonic-gate #define	GRACE_PERIOD 800		/* Total seconds we'll wait for	*/
79*7c478bd9Sstevel@tonic-gate 					/* responses from ypxfrs, yes	*/
80*7c478bd9Sstevel@tonic-gate 					/* virginia yp map transfers	*/
81*7c478bd9Sstevel@tonic-gate 					/* can take a long time, we	*/
82*7c478bd9Sstevel@tonic-gate 					/* only worry if the slave 	*/
83*7c478bd9Sstevel@tonic-gate 					/* crashes ...			*/
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate USE_YPDBPATH
86*7c478bd9Sstevel@tonic-gate static char *pusage;
87*7c478bd9Sstevel@tonic-gate static char *domain = NULL;
88*7c478bd9Sstevel@tonic-gate static char *host = NULL;
89*7c478bd9Sstevel@tonic-gate static char my_name[YPMAXPEER +1];
90*7c478bd9Sstevel@tonic-gate static char default_domain_name[YPMAXDOMAIN];
91*7c478bd9Sstevel@tonic-gate static char domain_alias[MAXNAMLEN]; 	/* nickname for domain -	*/
92*7c478bd9Sstevel@tonic-gate 					/*	used in sysv filesystems */
93*7c478bd9Sstevel@tonic-gate static char map_alias[MAXNAMLEN];	/* nickname for map -		*/
94*7c478bd9Sstevel@tonic-gate 					/*	used in sysv filesystems */
95*7c478bd9Sstevel@tonic-gate static char *map = NULL;
96*7c478bd9Sstevel@tonic-gate static bool verbose = FALSE;
97*7c478bd9Sstevel@tonic-gate static bool onehost = FALSE;
98*7c478bd9Sstevel@tonic-gate static bool oldxfr = FALSE;
99*7c478bd9Sstevel@tonic-gate static bool callback_timeout = FALSE;	/* set when a callback times out */
100*7c478bd9Sstevel@tonic-gate int grace_period = GRACE_PERIOD;
101*7c478bd9Sstevel@tonic-gate int curpar = CUR_PAR;			/* should be set by other stuff */
102*7c478bd9Sstevel@tonic-gate static char ypmapname[1024];		/* Used to check for map's existence */
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate static struct timeval intertry = {
105*7c478bd9Sstevel@tonic-gate 	INTER_TRY,			/* Seconds */
106*7c478bd9Sstevel@tonic-gate 	0				/* Microseconds */
107*7c478bd9Sstevel@tonic-gate };
108*7c478bd9Sstevel@tonic-gate static struct timeval timeout = {
109*7c478bd9Sstevel@tonic-gate 	TIMEOUT,			/* Seconds */
110*7c478bd9Sstevel@tonic-gate 	0				/* Microseconds */
111*7c478bd9Sstevel@tonic-gate };
112*7c478bd9Sstevel@tonic-gate static SVCXPRT *transport4;
113*7c478bd9Sstevel@tonic-gate static SVCXPRT *transport6;
114*7c478bd9Sstevel@tonic-gate struct server {
115*7c478bd9Sstevel@tonic-gate 	struct server *pnext;
116*7c478bd9Sstevel@tonic-gate 	struct dom_binding domb;
117*7c478bd9Sstevel@tonic-gate 	char svc_name[YPMAXPEER+1];
118*7c478bd9Sstevel@tonic-gate 	unsigned long xactid;
119*7c478bd9Sstevel@tonic-gate 	unsigned short state;
120*7c478bd9Sstevel@tonic-gate 	unsigned long status;
121*7c478bd9Sstevel@tonic-gate 	bool oldvers;
122*7c478bd9Sstevel@tonic-gate 	int start_time;
123*7c478bd9Sstevel@tonic-gate };
124*7c478bd9Sstevel@tonic-gate #define	n_conf dom_binding->ypbind_nconf
125*7c478bd9Sstevel@tonic-gate #define	svc_addr dom_binding->ypbind_svcaddr
126*7c478bd9Sstevel@tonic-gate static struct server *server_list = (struct server *)NULL;
127*7c478bd9Sstevel@tonic-gate static struct server *active_list = (struct server *)NULL;
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate /*  State values for server.state field */
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate #define	SSTAT_INIT 0
132*7c478bd9Sstevel@tonic-gate #define	SSTAT_CALLED 1
133*7c478bd9Sstevel@tonic-gate #define	SSTAT_RESPONDED 2
134*7c478bd9Sstevel@tonic-gate #define	SSTAT_PROGNOTREG 3
135*7c478bd9Sstevel@tonic-gate #define	SSTAT_RPC 4
136*7c478bd9Sstevel@tonic-gate #define	SSTAT_RSCRC 5
137*7c478bd9Sstevel@tonic-gate #define	SSTAT_SYSTEM 6
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate static char err_usage[] =
140*7c478bd9Sstevel@tonic-gate "Usage:\n\typpush [-p <par>] [-d <domainname>] [-h <hostname>] [-v] map\n";
141*7c478bd9Sstevel@tonic-gate static char err_bad_args[] =
142*7c478bd9Sstevel@tonic-gate 	"The %s argument is bad.\n";
143*7c478bd9Sstevel@tonic-gate static char err_cant_get_kname[] =
144*7c478bd9Sstevel@tonic-gate 	"Can't get %s from system call.\n";
145*7c478bd9Sstevel@tonic-gate static char err_null_kname[] =
146*7c478bd9Sstevel@tonic-gate 	"The %s hasn't been set on this machine.\n";
147*7c478bd9Sstevel@tonic-gate static char err_bad_domainname[] = "domainname";
148*7c478bd9Sstevel@tonic-gate static char err_cant_bind[] =
149*7c478bd9Sstevel@tonic-gate 	"Can't find a yp server for domain %s.  Reason:  %s.\n";
150*7c478bd9Sstevel@tonic-gate static char err_cant_build_serverlist[] =
151*7c478bd9Sstevel@tonic-gate 	"Can't build server list from map \"ypservers\".  Reason:  %s.\n";
152*7c478bd9Sstevel@tonic-gate static char err_cant_find_host[] =
153*7c478bd9Sstevel@tonic-gate 	"Can't find host %s in map \"ypservers\".\n";
154*7c478bd9Sstevel@tonic-gate /*
155*7c478bd9Sstevel@tonic-gate  * State_duple table.  All messages should take 1 arg - the node name.
156*7c478bd9Sstevel@tonic-gate  */
157*7c478bd9Sstevel@tonic-gate struct state_duple {
158*7c478bd9Sstevel@tonic-gate 	int state;
159*7c478bd9Sstevel@tonic-gate 	char *state_msg;
160*7c478bd9Sstevel@tonic-gate };
161*7c478bd9Sstevel@tonic-gate static struct state_duple state_duples[] = {
162*7c478bd9Sstevel@tonic-gate 	{SSTAT_INIT, "Internal error trying to talk to %s."},
163*7c478bd9Sstevel@tonic-gate 	{SSTAT_CALLED, "%s has been called."},
164*7c478bd9Sstevel@tonic-gate 	{SSTAT_RESPONDED, "%s (v1 ypserv) sent an old-style request."},
165*7c478bd9Sstevel@tonic-gate 	{SSTAT_PROGNOTREG, "nis server not registered at %s."},
166*7c478bd9Sstevel@tonic-gate 	{SSTAT_RPC, "RPC error to %s:  "},
167*7c478bd9Sstevel@tonic-gate 	{SSTAT_RSCRC, "Local resource allocation failure - can't talk to %s."},
168*7c478bd9Sstevel@tonic-gate 	{SSTAT_SYSTEM, "System error talking to %s:  "},
169*7c478bd9Sstevel@tonic-gate 	{0, (char *)NULL}
170*7c478bd9Sstevel@tonic-gate };
171*7c478bd9Sstevel@tonic-gate /*
172*7c478bd9Sstevel@tonic-gate  * Status_duple table.  No messages should require any args.
173*7c478bd9Sstevel@tonic-gate  */
174*7c478bd9Sstevel@tonic-gate static struct status_duple {
175*7c478bd9Sstevel@tonic-gate 	long status;
176*7c478bd9Sstevel@tonic-gate 	char *status_msg;
177*7c478bd9Sstevel@tonic-gate };
178*7c478bd9Sstevel@tonic-gate static struct status_duple status_duples[] = {
179*7c478bd9Sstevel@tonic-gate 	{YPPUSH_SUCC, "Map successfully transferred."},
180*7c478bd9Sstevel@tonic-gate 	{YPPUSH_AGE,
181*7c478bd9Sstevel@tonic-gate 	    "Transfer not done:  master's version isn't newer."},
182*7c478bd9Sstevel@tonic-gate 	{YPPUSH_NOMAP, "Failed - ypxfr there can't find a server for map."},
183*7c478bd9Sstevel@tonic-gate 	{YPPUSH_NODOM, "Failed - domain isn't supported."},
184*7c478bd9Sstevel@tonic-gate 	{YPPUSH_RSRC, "Failed - local resource allocation failure."},
185*7c478bd9Sstevel@tonic-gate 	{YPPUSH_RPC, "Failed - ypxfr had an RPC failure"},
186*7c478bd9Sstevel@tonic-gate 	{YPPUSH_MADDR, "Failed - ypxfr couldn't get the map master's address."},
187*7c478bd9Sstevel@tonic-gate 	{YPPUSH_YPERR, "Failed - nis server or map format error."},
188*7c478bd9Sstevel@tonic-gate 	{YPPUSH_BADARGS, "Failed - args to ypxfr were bad."},
189*7c478bd9Sstevel@tonic-gate 	{YPPUSH_DBM, "Failed - dbm operation on map failed."},
190*7c478bd9Sstevel@tonic-gate 	{YPPUSH_FILE, "Failed - file I/O operation on map failed"},
191*7c478bd9Sstevel@tonic-gate 	{YPPUSH_SKEW, "Failed - map version skew during transfer."},
192*7c478bd9Sstevel@tonic-gate 	{YPPUSH_CLEAR,
193*7c478bd9Sstevel@tonic-gate 		"Map successfully transferred, but ypxfr \
194*7c478bd9Sstevel@tonic-gate 		couldn't send \"Clear map\" to ypserv "},
195*7c478bd9Sstevel@tonic-gate 	{YPPUSH_FORCE,
196*7c478bd9Sstevel@tonic-gate 	    "Failed - no local order number in map - use -f flag to ypxfr."},
197*7c478bd9Sstevel@tonic-gate 	{YPPUSH_XFRERR, "Failed - ypxfr internal error."},
198*7c478bd9Sstevel@tonic-gate 	{YPPUSH_REFUSED, "Failed - Transfer request refused."},
199*7c478bd9Sstevel@tonic-gate 	{YPPUSH_NOALIAS,
200*7c478bd9Sstevel@tonic-gate 		"Failed - System V domain/map alias not in alias file."},
201*7c478bd9Sstevel@tonic-gate 	{0, (char *)NULL}
202*7c478bd9Sstevel@tonic-gate };
203*7c478bd9Sstevel@tonic-gate /*
204*7c478bd9Sstevel@tonic-gate  * rpcerr_duple table
205*7c478bd9Sstevel@tonic-gate  */
206*7c478bd9Sstevel@tonic-gate static struct rpcerr_duple {
207*7c478bd9Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
208*7c478bd9Sstevel@tonic-gate 	char *rpc_msg;
209*7c478bd9Sstevel@tonic-gate };
210*7c478bd9Sstevel@tonic-gate static struct rpcerr_duple rpcerr_duples[] = {
211*7c478bd9Sstevel@tonic-gate 	{RPC_SUCCESS, "RPC success"},
212*7c478bd9Sstevel@tonic-gate 	{RPC_CANTENCODEARGS, "RPC Can't encode args"},
213*7c478bd9Sstevel@tonic-gate 	{RPC_CANTDECODERES, "RPC Can't decode results"},
214*7c478bd9Sstevel@tonic-gate 	{RPC_CANTSEND, "RPC Can't send"},
215*7c478bd9Sstevel@tonic-gate 	{RPC_CANTRECV, "RPC Can't recv"},
216*7c478bd9Sstevel@tonic-gate 	{RPC_TIMEDOUT, "NIS server registered, but does not respond"},
217*7c478bd9Sstevel@tonic-gate 	{RPC_VERSMISMATCH, "RPC version mismatch"},
218*7c478bd9Sstevel@tonic-gate 	{RPC_AUTHERROR, "RPC auth error"},
219*7c478bd9Sstevel@tonic-gate 	{RPC_PROGUNAVAIL, "RPC remote program unavailable"},
220*7c478bd9Sstevel@tonic-gate 	{RPC_PROGVERSMISMATCH, "RPC program mismatch"},
221*7c478bd9Sstevel@tonic-gate 	{RPC_PROCUNAVAIL, "RPC unknown procedure"},
222*7c478bd9Sstevel@tonic-gate 	{RPC_CANTDECODEARGS, "RPC Can't decode args"},
223*7c478bd9Sstevel@tonic-gate 	{RPC_UNKNOWNHOST, "unknown host"},
224*7c478bd9Sstevel@tonic-gate 	{RPC_RPCBFAILURE, "rpcbind failure (host is down?)"},
225*7c478bd9Sstevel@tonic-gate 	{RPC_PROGNOTREGISTERED, "RPC prog not registered"},
226*7c478bd9Sstevel@tonic-gate 	{RPC_SYSTEMERROR, "RPC system error"},
227*7c478bd9Sstevel@tonic-gate 	{RPC_SUCCESS, (char *)NULL}		/* Duplicate rpc_stat 	*/
228*7c478bd9Sstevel@tonic-gate 						/* unused in list-end 	*/
229*7c478bd9Sstevel@tonic-gate 						/* entry */
230*7c478bd9Sstevel@tonic-gate };
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate static void get_default_domain_name(void);
233*7c478bd9Sstevel@tonic-gate static void get_command_line_args(int argc, char **argv);
234*7c478bd9Sstevel@tonic-gate static unsigned short send_message(struct server *ps,
235*7c478bd9Sstevel@tonic-gate 					unsigned long program, long *err);
236*7c478bd9Sstevel@tonic-gate static void make_server_list(void);
237*7c478bd9Sstevel@tonic-gate static void one_host_list(void);
238*7c478bd9Sstevel@tonic-gate static void add_server(char *sname, int namelen);
239*7c478bd9Sstevel@tonic-gate static int  generate_callback(unsigned long *program);
240*7c478bd9Sstevel@tonic-gate static void xactid_seed(unsigned long *xactid);
241*7c478bd9Sstevel@tonic-gate static void main_loop(unsigned long program);
242*7c478bd9Sstevel@tonic-gate static void listener_exit(unsigned long program, int stat);
243*7c478bd9Sstevel@tonic-gate static void listener_dispatch(struct svc_req *rqstp, SVCXPRT *transp);
244*7c478bd9Sstevel@tonic-gate static void print_state_msg(struct server *s, long e);
245*7c478bd9Sstevel@tonic-gate static void print_callback_msg(struct server *s);
246*7c478bd9Sstevel@tonic-gate static void rpcerr_msg(enum clnt_stat e);
247*7c478bd9Sstevel@tonic-gate static void get_xfr_response(SVCXPRT *transp);
248*7c478bd9Sstevel@tonic-gate 
249*7c478bd9Sstevel@tonic-gate #ifdef SYSVCONFIG
250*7c478bd9Sstevel@tonic-gate extern void sysvconfig(void);
251*7c478bd9Sstevel@tonic-gate #endif
252*7c478bd9Sstevel@tonic-gate extern int yp_getalias(char *key, char *key_alias, int maxlen);
253*7c478bd9Sstevel@tonic-gate extern int getdomainname(char *, int);
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate extern struct rpc_createerr rpc_createerr;
256*7c478bd9Sstevel@tonic-gate extern char *sys_errlist[];
257*7c478bd9Sstevel@tonic-gate extern int sys_nerr;
258*7c478bd9Sstevel@tonic-gate extern CLIENT *__yp_clnt_create_rsvdport();
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate int
261*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
262*7c478bd9Sstevel@tonic-gate {
263*7c478bd9Sstevel@tonic-gate 	unsigned long program;
264*7c478bd9Sstevel@tonic-gate 	struct stat sbuf;
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 	get_command_line_args(argc, argv);
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 	if (!domain) {
269*7c478bd9Sstevel@tonic-gate 		get_default_domain_name();
270*7c478bd9Sstevel@tonic-gate 	}
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate #ifdef SYSVCONFIG
273*7c478bd9Sstevel@tonic-gate 	sysvconfig();
274*7c478bd9Sstevel@tonic-gate #endif
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate 	if (yp_getalias(domain, domain_alias, NAME_MAX) != 0)
277*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "domain alias for %s not found\n", domain);
278*7c478bd9Sstevel@tonic-gate 	if (yp_getalias(map, map_alias, MAXALIASLEN) != 0)
279*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "map alias for %s not found\n", map);
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate 	/* check to see if the map exists in this domain */
282*7c478bd9Sstevel@tonic-gate 	if (is_yptol_mode())
283*7c478bd9Sstevel@tonic-gate 		sprintf(ypmapname, "%s/%s/%s%s.dir", ypdbpath, domain_alias,
284*7c478bd9Sstevel@tonic-gate 						NTOL_PREFIX, map_alias);
285*7c478bd9Sstevel@tonic-gate 	else
286*7c478bd9Sstevel@tonic-gate 		sprintf(ypmapname, "%s/%s/%s.dir", ypdbpath, domain_alias,
287*7c478bd9Sstevel@tonic-gate 								map_alias);
288*7c478bd9Sstevel@tonic-gate 	if (stat(ypmapname, &sbuf) < 0) {
289*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "yppush: Map does not exist.\n");
290*7c478bd9Sstevel@tonic-gate 		exit(1);
291*7c478bd9Sstevel@tonic-gate 	}
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 	if (onehost) {
294*7c478bd9Sstevel@tonic-gate 		one_host_list();
295*7c478bd9Sstevel@tonic-gate 	} else {
296*7c478bd9Sstevel@tonic-gate 		make_server_list();
297*7c478bd9Sstevel@tonic-gate 	}
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 	/*
300*7c478bd9Sstevel@tonic-gate 	 * All process exits after the call to generate_callback should be
301*7c478bd9Sstevel@tonic-gate 	 * through listener_exit(program, status), not exit(status), so the
302*7c478bd9Sstevel@tonic-gate 	 * transient server can get unregistered with the portmapper.
303*7c478bd9Sstevel@tonic-gate 	 */
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate 	if (!generate_callback(&program)) {
306*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Can't set up transient callback server.\n");
307*7c478bd9Sstevel@tonic-gate 	}
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate 	main_loop(program);
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate 	listener_exit(program, 0);
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
314*7c478bd9Sstevel@tonic-gate 	return (0);
315*7c478bd9Sstevel@tonic-gate }
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate /*
318*7c478bd9Sstevel@tonic-gate  * This does the command line parsing.
319*7c478bd9Sstevel@tonic-gate  */
320*7c478bd9Sstevel@tonic-gate static void
321*7c478bd9Sstevel@tonic-gate get_command_line_args(int argc, char **argv)
322*7c478bd9Sstevel@tonic-gate {
323*7c478bd9Sstevel@tonic-gate 	pusage = err_usage;
324*7c478bd9Sstevel@tonic-gate 	argv++;
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate 	if (argc < 2) {
327*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, pusage);
328*7c478bd9Sstevel@tonic-gate 		exit(1);
329*7c478bd9Sstevel@tonic-gate 	}
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate 	while (--argc) {
332*7c478bd9Sstevel@tonic-gate 		if ((*argv)[0] == '-') {
333*7c478bd9Sstevel@tonic-gate 			switch ((*argv)[1]) {
334*7c478bd9Sstevel@tonic-gate 			case 'v':
335*7c478bd9Sstevel@tonic-gate 				verbose = TRUE;
336*7c478bd9Sstevel@tonic-gate 				argv++;
337*7c478bd9Sstevel@tonic-gate 				break;
338*7c478bd9Sstevel@tonic-gate 			case 'd':
339*7c478bd9Sstevel@tonic-gate 				if (argc > 1) {
340*7c478bd9Sstevel@tonic-gate 					argv++;
341*7c478bd9Sstevel@tonic-gate 					argc--;
342*7c478bd9Sstevel@tonic-gate 					domain = *argv;
343*7c478bd9Sstevel@tonic-gate 					argv++;
344*7c478bd9Sstevel@tonic-gate 					if (((int)strlen(domain)) >
345*7c478bd9Sstevel@tonic-gate 								YPMAXDOMAIN) {
346*7c478bd9Sstevel@tonic-gate 						fprintf(stderr,
347*7c478bd9Sstevel@tonic-gate 							err_bad_args,
348*7c478bd9Sstevel@tonic-gate 							err_bad_domainname);
349*7c478bd9Sstevel@tonic-gate 						exit(1);
350*7c478bd9Sstevel@tonic-gate 					}
351*7c478bd9Sstevel@tonic-gate 				} else {
352*7c478bd9Sstevel@tonic-gate 					fprintf(stderr, pusage);
353*7c478bd9Sstevel@tonic-gate 					exit(1);
354*7c478bd9Sstevel@tonic-gate 				}
355*7c478bd9Sstevel@tonic-gate 				break;
356*7c478bd9Sstevel@tonic-gate 			case 'h':
357*7c478bd9Sstevel@tonic-gate 				if (argc > 1) {
358*7c478bd9Sstevel@tonic-gate 					onehost = TRUE;
359*7c478bd9Sstevel@tonic-gate 					argv++;
360*7c478bd9Sstevel@tonic-gate 					argc--;
361*7c478bd9Sstevel@tonic-gate 					host = *argv;
362*7c478bd9Sstevel@tonic-gate 					argv++;
363*7c478bd9Sstevel@tonic-gate 				} else {
364*7c478bd9Sstevel@tonic-gate 					fprintf(stderr, pusage);
365*7c478bd9Sstevel@tonic-gate 					exit(1);
366*7c478bd9Sstevel@tonic-gate 				}
367*7c478bd9Sstevel@tonic-gate 				break;
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate 			case 'p':
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate 				if (argc > 1) {
372*7c478bd9Sstevel@tonic-gate 					argv++;
373*7c478bd9Sstevel@tonic-gate 					argc--;
374*7c478bd9Sstevel@tonic-gate 					if (sscanf(*argv, "%d", &curpar) != 1) {
375*7c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr, pusage);
376*7c478bd9Sstevel@tonic-gate 						exit(1);
377*7c478bd9Sstevel@tonic-gate 					}
378*7c478bd9Sstevel@tonic-gate 					argv++;
379*7c478bd9Sstevel@tonic-gate 					if (curpar < 1) {
380*7c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr, pusage);
381*7c478bd9Sstevel@tonic-gate 						exit(1);
382*7c478bd9Sstevel@tonic-gate 					}
383*7c478bd9Sstevel@tonic-gate 				} else {
384*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr, pusage);
385*7c478bd9Sstevel@tonic-gate 					exit(1);
386*7c478bd9Sstevel@tonic-gate 				}
387*7c478bd9Sstevel@tonic-gate 				break;
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate 			default:
390*7c478bd9Sstevel@tonic-gate 				fprintf(stderr, pusage);
391*7c478bd9Sstevel@tonic-gate 				exit(1);
392*7c478bd9Sstevel@tonic-gate 			}
393*7c478bd9Sstevel@tonic-gate 		} else {
394*7c478bd9Sstevel@tonic-gate 			if (!map) {
395*7c478bd9Sstevel@tonic-gate 				map = *argv;
396*7c478bd9Sstevel@tonic-gate 			} else {
397*7c478bd9Sstevel@tonic-gate 				fprintf(stderr, pusage);
398*7c478bd9Sstevel@tonic-gate 				exit(1);
399*7c478bd9Sstevel@tonic-gate 			}
400*7c478bd9Sstevel@tonic-gate 			argv++;
401*7c478bd9Sstevel@tonic-gate 		}
402*7c478bd9Sstevel@tonic-gate 	}
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate 	if (!map) {
405*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, pusage);
406*7c478bd9Sstevel@tonic-gate 		exit(1);
407*7c478bd9Sstevel@tonic-gate 	}
408*7c478bd9Sstevel@tonic-gate }
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate /*
411*7c478bd9Sstevel@tonic-gate  *  This gets the local kernel domainname, and sets the global domain to it.
412*7c478bd9Sstevel@tonic-gate  */
413*7c478bd9Sstevel@tonic-gate static void
414*7c478bd9Sstevel@tonic-gate get_default_domain_name(void)
415*7c478bd9Sstevel@tonic-gate {
416*7c478bd9Sstevel@tonic-gate 	if (!getdomainname(default_domain_name, YPMAXDOMAIN)) {
417*7c478bd9Sstevel@tonic-gate 		domain = default_domain_name;
418*7c478bd9Sstevel@tonic-gate 	} else {
419*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, err_cant_get_kname, err_bad_domainname);
420*7c478bd9Sstevel@tonic-gate 		exit(1);
421*7c478bd9Sstevel@tonic-gate 	}
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate 	if ((int)strlen(domain) == 0) {
424*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, err_null_kname, err_bad_domainname);
425*7c478bd9Sstevel@tonic-gate 		exit(1);
426*7c478bd9Sstevel@tonic-gate 	}
427*7c478bd9Sstevel@tonic-gate }
428*7c478bd9Sstevel@tonic-gate 
429*7c478bd9Sstevel@tonic-gate /*
430*7c478bd9Sstevel@tonic-gate  * This verifies that the hostname supplied by the user is in the map
431*7c478bd9Sstevel@tonic-gate  * "ypservers" then calls add_server to make it the only entry on the
432*7c478bd9Sstevel@tonic-gate  * list of servers.
433*7c478bd9Sstevel@tonic-gate  */
434*7c478bd9Sstevel@tonic-gate static void
435*7c478bd9Sstevel@tonic-gate one_host_list(void)
436*7c478bd9Sstevel@tonic-gate {
437*7c478bd9Sstevel@tonic-gate 	char *key;
438*7c478bd9Sstevel@tonic-gate 	int keylen;
439*7c478bd9Sstevel@tonic-gate 	char *val;
440*7c478bd9Sstevel@tonic-gate 	int vallen;
441*7c478bd9Sstevel@tonic-gate 	int err;
442*7c478bd9Sstevel@tonic-gate 	char *ypservers = "ypservers";
443*7c478bd9Sstevel@tonic-gate 
444*7c478bd9Sstevel@tonic-gate 	if (verbose) {
445*7c478bd9Sstevel@tonic-gate 		printf("Verifying YP server: %s\n", host);
446*7c478bd9Sstevel@tonic-gate 		fflush(stdout);
447*7c478bd9Sstevel@tonic-gate 	}
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate 	if (err = yp_bind(domain_alias)) {
450*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, err_cant_bind, domain, yperr_string(err));
451*7c478bd9Sstevel@tonic-gate 		exit(1);
452*7c478bd9Sstevel@tonic-gate 	}
453*7c478bd9Sstevel@tonic-gate 
454*7c478bd9Sstevel@tonic-gate 	keylen = strlen(host);
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate 	if (yp_match(domain_alias, ypservers, host, keylen,
457*7c478bd9Sstevel@tonic-gate 			&val, &vallen)) {
458*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, err_cant_find_host, host);
459*7c478bd9Sstevel@tonic-gate 		exit(1);
460*7c478bd9Sstevel@tonic-gate 	}
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate 	add_server(host, keylen);
463*7c478bd9Sstevel@tonic-gate }
464*7c478bd9Sstevel@tonic-gate 
465*7c478bd9Sstevel@tonic-gate /*
466*7c478bd9Sstevel@tonic-gate  * This uses yp operations to retrieve each server name in the map
467*7c478bd9Sstevel@tonic-gate  *  "ypservers".  add_server is called for each one to add it to the list of
468*7c478bd9Sstevel@tonic-gate  *  servers.
469*7c478bd9Sstevel@tonic-gate  */
470*7c478bd9Sstevel@tonic-gate static void
471*7c478bd9Sstevel@tonic-gate make_server_list(void)
472*7c478bd9Sstevel@tonic-gate {
473*7c478bd9Sstevel@tonic-gate 	char *key;
474*7c478bd9Sstevel@tonic-gate 	int keylen;
475*7c478bd9Sstevel@tonic-gate 	char *outkey;
476*7c478bd9Sstevel@tonic-gate 	int outkeylen;
477*7c478bd9Sstevel@tonic-gate 	char *val;
478*7c478bd9Sstevel@tonic-gate 	int vallen;
479*7c478bd9Sstevel@tonic-gate 	int err;
480*7c478bd9Sstevel@tonic-gate 	char *ypservers = "ypservers";
481*7c478bd9Sstevel@tonic-gate 	int count;
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate 	if (verbose) {
484*7c478bd9Sstevel@tonic-gate 		printf("Finding YP servers: ");
485*7c478bd9Sstevel@tonic-gate 		fflush(stdout);
486*7c478bd9Sstevel@tonic-gate 		count = 4;
487*7c478bd9Sstevel@tonic-gate 	}
488*7c478bd9Sstevel@tonic-gate 
489*7c478bd9Sstevel@tonic-gate 	if (err = yp_bind(domain_alias)) {
490*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, err_cant_bind, domain, yperr_string(err));
491*7c478bd9Sstevel@tonic-gate 		exit(1);
492*7c478bd9Sstevel@tonic-gate 	}
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate 	if (err = yp_first(domain_alias, ypservers, &outkey, &outkeylen,
495*7c478bd9Sstevel@tonic-gate 				&val, &vallen)) {
496*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, err_cant_build_serverlist, yperr_string(err));
497*7c478bd9Sstevel@tonic-gate 		exit(1);
498*7c478bd9Sstevel@tonic-gate 	}
499*7c478bd9Sstevel@tonic-gate 
500*7c478bd9Sstevel@tonic-gate 	for (;;) {
501*7c478bd9Sstevel@tonic-gate 		add_server(outkey, outkeylen);
502*7c478bd9Sstevel@tonic-gate 		if (verbose) {
503*7c478bd9Sstevel@tonic-gate 			printf(" %s", outkey);
504*7c478bd9Sstevel@tonic-gate 			fflush(stdout);
505*7c478bd9Sstevel@tonic-gate 			if (count++ == 8) {
506*7c478bd9Sstevel@tonic-gate 				printf("\n");
507*7c478bd9Sstevel@tonic-gate 				count = 0;
508*7c478bd9Sstevel@tonic-gate 			}
509*7c478bd9Sstevel@tonic-gate 		}
510*7c478bd9Sstevel@tonic-gate 		free(val);
511*7c478bd9Sstevel@tonic-gate 		key = outkey;
512*7c478bd9Sstevel@tonic-gate 		keylen = outkeylen;
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate 		if (err = yp_next(domain_alias, ypservers, key, keylen,
515*7c478bd9Sstevel@tonic-gate 				&outkey, &outkeylen, &val, &vallen)) {
516*7c478bd9Sstevel@tonic-gate 
517*7c478bd9Sstevel@tonic-gate 		    if (err == YPERR_NOMORE) {
518*7c478bd9Sstevel@tonic-gate 			break;
519*7c478bd9Sstevel@tonic-gate 		    } else {
520*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, err_cant_build_serverlist,
521*7c478bd9Sstevel@tonic-gate 				yperr_string(err));
522*7c478bd9Sstevel@tonic-gate 			exit(1);
523*7c478bd9Sstevel@tonic-gate 		    }
524*7c478bd9Sstevel@tonic-gate 		}
525*7c478bd9Sstevel@tonic-gate 
526*7c478bd9Sstevel@tonic-gate 		free(key);
527*7c478bd9Sstevel@tonic-gate 	}
528*7c478bd9Sstevel@tonic-gate 	if (count != 0) {
529*7c478bd9Sstevel@tonic-gate 		if (verbose)
530*7c478bd9Sstevel@tonic-gate 			printf("\n");
531*7c478bd9Sstevel@tonic-gate 	}
532*7c478bd9Sstevel@tonic-gate }
533*7c478bd9Sstevel@tonic-gate 
534*7c478bd9Sstevel@tonic-gate /*
535*7c478bd9Sstevel@tonic-gate  *  This adds a single server to the server list.
536*7c478bd9Sstevel@tonic-gate  */
537*7c478bd9Sstevel@tonic-gate static void
538*7c478bd9Sstevel@tonic-gate add_server(char *sname, int namelen)
539*7c478bd9Sstevel@tonic-gate {
540*7c478bd9Sstevel@tonic-gate 	struct server *ps;
541*7c478bd9Sstevel@tonic-gate 	static unsigned long seq;
542*7c478bd9Sstevel@tonic-gate 	static unsigned long xactid = 0;
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate 	if (strcmp(sname, my_name) == 0)
545*7c478bd9Sstevel@tonic-gate 		return;
546*7c478bd9Sstevel@tonic-gate 
547*7c478bd9Sstevel@tonic-gate 	if (xactid == 0) {
548*7c478bd9Sstevel@tonic-gate 		xactid_seed(&xactid);
549*7c478bd9Sstevel@tonic-gate 	}
550*7c478bd9Sstevel@tonic-gate 
551*7c478bd9Sstevel@tonic-gate 	if ((ps = (struct server *)malloc((unsigned)sizeof (struct server)))
552*7c478bd9Sstevel@tonic-gate 		== (struct server *)NULL) {
553*7c478bd9Sstevel@tonic-gate 		perror("yppush: malloc failure");
554*7c478bd9Sstevel@tonic-gate 		exit(1);
555*7c478bd9Sstevel@tonic-gate 	}
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate 	sname[namelen] = '\0';
558*7c478bd9Sstevel@tonic-gate 	strcpy(ps->svc_name, sname);
559*7c478bd9Sstevel@tonic-gate 	ps->state = SSTAT_INIT;
560*7c478bd9Sstevel@tonic-gate 	ps->status = 0;
561*7c478bd9Sstevel@tonic-gate 	ps->oldvers = FALSE;
562*7c478bd9Sstevel@tonic-gate 	ps->xactid = xactid + seq++;
563*7c478bd9Sstevel@tonic-gate 	ps->pnext = server_list;
564*7c478bd9Sstevel@tonic-gate 	server_list = ps;
565*7c478bd9Sstevel@tonic-gate }
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate /*
568*7c478bd9Sstevel@tonic-gate  * This sets the base range for the transaction ids used in speaking the the
569*7c478bd9Sstevel@tonic-gate  *  server ypxfr processes.
570*7c478bd9Sstevel@tonic-gate  */
571*7c478bd9Sstevel@tonic-gate static void
572*7c478bd9Sstevel@tonic-gate xactid_seed(unsigned long *xactid)
573*7c478bd9Sstevel@tonic-gate {
574*7c478bd9Sstevel@tonic-gate 	struct timeval t;
575*7c478bd9Sstevel@tonic-gate 
576*7c478bd9Sstevel@tonic-gate 	if (gettimeofday(&t) == -1) {
577*7c478bd9Sstevel@tonic-gate 		perror("yppush gettimeofday failure");
578*7c478bd9Sstevel@tonic-gate 		*xactid = 1234567;
579*7c478bd9Sstevel@tonic-gate 	} else {
580*7c478bd9Sstevel@tonic-gate 		*xactid = t.tv_sec;
581*7c478bd9Sstevel@tonic-gate 	}
582*7c478bd9Sstevel@tonic-gate }
583*7c478bd9Sstevel@tonic-gate 
584*7c478bd9Sstevel@tonic-gate /*
585*7c478bd9Sstevel@tonic-gate  *  This generates the channel which will be used as the listener process'
586*7c478bd9Sstevel@tonic-gate  *  service rendezvous point, and comes up with a transient program number
587*7c478bd9Sstevel@tonic-gate  *  for the use of the RPC messages from the ypxfr processes.
588*7c478bd9Sstevel@tonic-gate  */
589*7c478bd9Sstevel@tonic-gate static int
590*7c478bd9Sstevel@tonic-gate generate_callback(unsigned long *program)
591*7c478bd9Sstevel@tonic-gate {
592*7c478bd9Sstevel@tonic-gate 	unsigned long prognum = 0x40000000, maxprognum;
593*7c478bd9Sstevel@tonic-gate 	union {
594*7c478bd9Sstevel@tonic-gate 		unsigned long	p;
595*7c478bd9Sstevel@tonic-gate 		unsigned char	b[sizeof (unsigned long)];
596*7c478bd9Sstevel@tonic-gate 	} u;
597*7c478bd9Sstevel@tonic-gate 	int ret, i;
598*7c478bd9Sstevel@tonic-gate 	struct netconfig *nc4, *nc6, *nc;
599*7c478bd9Sstevel@tonic-gate 	SVCXPRT *trans;
600*7c478bd9Sstevel@tonic-gate 
601*7c478bd9Sstevel@tonic-gate 	nc4 = getnetconfigent("udp");
602*7c478bd9Sstevel@tonic-gate 	nc6 = getnetconfigent("udp6");
603*7c478bd9Sstevel@tonic-gate 	if (nc4 == 0 && nc6 == 0) {
604*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
605*7c478bd9Sstevel@tonic-gate 			"yppush: Could not get udp or udp6 netconfig entry\n");
606*7c478bd9Sstevel@tonic-gate 		exit(1);
607*7c478bd9Sstevel@tonic-gate 	}
608*7c478bd9Sstevel@tonic-gate 
609*7c478bd9Sstevel@tonic-gate 	transport4 = (nc4 == 0) ? 0 : svc_tli_create(RPC_ANYFD, nc4, 0, 0, 0);
610*7c478bd9Sstevel@tonic-gate 	transport6 = (nc6 == 0) ? 0 : svc_tli_create(RPC_ANYFD, nc6, 0, 0, 0);
611*7c478bd9Sstevel@tonic-gate 	if (transport4 == 0 && transport6 == 0) {
612*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "yppush: Could not create server handle(s)\n");
613*7c478bd9Sstevel@tonic-gate 		exit(1);
614*7c478bd9Sstevel@tonic-gate 	}
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate 	/* Find the maximum possible program number using an unsigned long */
617*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < sizeof (u.b); i++)
618*7c478bd9Sstevel@tonic-gate 		u.b[i] = 0xff;
619*7c478bd9Sstevel@tonic-gate 	maxprognum = u.p;
620*7c478bd9Sstevel@tonic-gate 
621*7c478bd9Sstevel@tonic-gate 	if (transport4 != 0) {
622*7c478bd9Sstevel@tonic-gate 		trans = transport4;
623*7c478bd9Sstevel@tonic-gate 		nc = nc4;
624*7c478bd9Sstevel@tonic-gate 	} else {
625*7c478bd9Sstevel@tonic-gate 		trans = transport6;
626*7c478bd9Sstevel@tonic-gate 		nc = nc6;
627*7c478bd9Sstevel@tonic-gate 	}
628*7c478bd9Sstevel@tonic-gate 	while (prognum < maxprognum && (ret =
629*7c478bd9Sstevel@tonic-gate 		rpcb_set(prognum, YPPUSHVERS, nc, &trans->xp_ltaddr)) == 0)
630*7c478bd9Sstevel@tonic-gate 		prognum++;
631*7c478bd9Sstevel@tonic-gate 
632*7c478bd9Sstevel@tonic-gate 	if (ret == 0) {
633*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "yppush: Could not create callback service\n");
634*7c478bd9Sstevel@tonic-gate 		exit(1);
635*7c478bd9Sstevel@tonic-gate 	} else {
636*7c478bd9Sstevel@tonic-gate 		if (trans == transport4 && transport6 != 0) {
637*7c478bd9Sstevel@tonic-gate 			ret = rpcb_set(prognum, YPPUSHVERS, nc6,
638*7c478bd9Sstevel@tonic-gate 					&transport6->xp_ltaddr);
639*7c478bd9Sstevel@tonic-gate 			if (ret == 0) {
640*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
641*7c478bd9Sstevel@tonic-gate 			"yppush: Could not create udp6 callback service\n");
642*7c478bd9Sstevel@tonic-gate 				exit(1);
643*7c478bd9Sstevel@tonic-gate 			}
644*7c478bd9Sstevel@tonic-gate 		}
645*7c478bd9Sstevel@tonic-gate 		*program = prognum;
646*7c478bd9Sstevel@tonic-gate 	}
647*7c478bd9Sstevel@tonic-gate 
648*7c478bd9Sstevel@tonic-gate 	return (ret);
649*7c478bd9Sstevel@tonic-gate }
650*7c478bd9Sstevel@tonic-gate 
651*7c478bd9Sstevel@tonic-gate /*
652*7c478bd9Sstevel@tonic-gate  * This is the main loop. Send messages to each server,
653*7c478bd9Sstevel@tonic-gate  * and then wait for a response.
654*7c478bd9Sstevel@tonic-gate  */
655*7c478bd9Sstevel@tonic-gate 
656*7c478bd9Sstevel@tonic-gate 
657*7c478bd9Sstevel@tonic-gate add_to_active()
658*7c478bd9Sstevel@tonic-gate {
659*7c478bd9Sstevel@tonic-gate 	struct server  *ps;
660*7c478bd9Sstevel@tonic-gate 	ps = server_list;
661*7c478bd9Sstevel@tonic-gate 	if (ps == NULL)
662*7c478bd9Sstevel@tonic-gate 		return (0);
663*7c478bd9Sstevel@tonic-gate 	server_list = server_list->pnext;	/* delete from server_list */
664*7c478bd9Sstevel@tonic-gate 	ps->pnext = active_list;
665*7c478bd9Sstevel@tonic-gate 	active_list = ps;
666*7c478bd9Sstevel@tonic-gate 	return (1);
667*7c478bd9Sstevel@tonic-gate }
668*7c478bd9Sstevel@tonic-gate 
669*7c478bd9Sstevel@tonic-gate delete_active(in)
670*7c478bd9Sstevel@tonic-gate 	struct server  *in;
671*7c478bd9Sstevel@tonic-gate {
672*7c478bd9Sstevel@tonic-gate 	struct server  *p;
673*7c478bd9Sstevel@tonic-gate 	struct server  *n;
674*7c478bd9Sstevel@tonic-gate 	if (in == active_list) {
675*7c478bd9Sstevel@tonic-gate 		active_list = active_list->pnext;
676*7c478bd9Sstevel@tonic-gate 		return (1);
677*7c478bd9Sstevel@tonic-gate 	}
678*7c478bd9Sstevel@tonic-gate 	p = active_list;
679*7c478bd9Sstevel@tonic-gate 	for (n = active_list; n; n = n->pnext) {
680*7c478bd9Sstevel@tonic-gate 		if (in == n) {
681*7c478bd9Sstevel@tonic-gate 			p->pnext = n->pnext;
682*7c478bd9Sstevel@tonic-gate 			return (0);
683*7c478bd9Sstevel@tonic-gate 
684*7c478bd9Sstevel@tonic-gate 		}
685*7c478bd9Sstevel@tonic-gate 		p = n;
686*7c478bd9Sstevel@tonic-gate 	}
687*7c478bd9Sstevel@tonic-gate 	return (-1);
688*7c478bd9Sstevel@tonic-gate }
689*7c478bd9Sstevel@tonic-gate 
690*7c478bd9Sstevel@tonic-gate void
691*7c478bd9Sstevel@tonic-gate main_loop(program)
692*7c478bd9Sstevel@tonic-gate 	unsigned long   program;
693*7c478bd9Sstevel@tonic-gate {
694*7c478bd9Sstevel@tonic-gate 	pollfd_t	*pollset = NULL;
695*7c478bd9Sstevel@tonic-gate 	int		npollfds = 0;
696*7c478bd9Sstevel@tonic-gate 	int		pollret;
697*7c478bd9Sstevel@tonic-gate 	struct server	*ps;
698*7c478bd9Sstevel@tonic-gate 	long		error;
699*7c478bd9Sstevel@tonic-gate 	int		hpar;	/* this times par count */
700*7c478bd9Sstevel@tonic-gate 	int		i;
701*7c478bd9Sstevel@tonic-gate 	int		j;
702*7c478bd9Sstevel@tonic-gate 	int		time_now;
703*7c478bd9Sstevel@tonic-gate 	int		docb;
704*7c478bd9Sstevel@tonic-gate 	int		actives = 0;
705*7c478bd9Sstevel@tonic-gate 	int		dead = 0;
706*7c478bd9Sstevel@tonic-gate 
707*7c478bd9Sstevel@tonic-gate 	if (grace_period < MIN_GRACE)
708*7c478bd9Sstevel@tonic-gate 		grace_period = MIN_GRACE;
709*7c478bd9Sstevel@tonic-gate 	if (transport4 != 0) {
710*7c478bd9Sstevel@tonic-gate 		if (!svc_reg(transport4, program, YPPUSHVERS,
711*7c478bd9Sstevel@tonic-gate 				listener_dispatch, 0)) {
712*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
713*7c478bd9Sstevel@tonic-gate 			"Can't set up transient udp callback server.\n");
714*7c478bd9Sstevel@tonic-gate 		}
715*7c478bd9Sstevel@tonic-gate 	}
716*7c478bd9Sstevel@tonic-gate 	if (transport6 != 0) {
717*7c478bd9Sstevel@tonic-gate 		if (!svc_reg(transport6, program, YPPUSHVERS,
718*7c478bd9Sstevel@tonic-gate 				listener_dispatch, 0)) {
719*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
720*7c478bd9Sstevel@tonic-gate 			"Can't set up transient udp6 callback server.\n");
721*7c478bd9Sstevel@tonic-gate 		}
722*7c478bd9Sstevel@tonic-gate 	}
723*7c478bd9Sstevel@tonic-gate 	for (;;) {
724*7c478bd9Sstevel@tonic-gate 		time_now = time(0);
725*7c478bd9Sstevel@tonic-gate 		if (server_list == NULL) {
726*7c478bd9Sstevel@tonic-gate 			actives = 0;
727*7c478bd9Sstevel@tonic-gate 			dead = 0;
728*7c478bd9Sstevel@tonic-gate 			for (ps = active_list; ps; ps = ps->pnext)
729*7c478bd9Sstevel@tonic-gate 				if (ps->state == SSTAT_CALLED) {
730*7c478bd9Sstevel@tonic-gate 					if ((time_now - ps->start_time) <
731*7c478bd9Sstevel@tonic-gate 								grace_period)
732*7c478bd9Sstevel@tonic-gate 						actives++;
733*7c478bd9Sstevel@tonic-gate 					else
734*7c478bd9Sstevel@tonic-gate 						dead++;
735*7c478bd9Sstevel@tonic-gate 				}
736*7c478bd9Sstevel@tonic-gate 			if (actives == 0) {
737*7c478bd9Sstevel@tonic-gate 				if (verbose) {
738*7c478bd9Sstevel@tonic-gate 					printf("terminating %d dead\n", dead);
739*7c478bd9Sstevel@tonic-gate 					fflush(stdout);
740*7c478bd9Sstevel@tonic-gate 				}
741*7c478bd9Sstevel@tonic-gate 
742*7c478bd9Sstevel@tonic-gate 				for (ps = active_list; ps; ps = ps->pnext)
743*7c478bd9Sstevel@tonic-gate 					if (ps->state == SSTAT_CALLED) {
744*7c478bd9Sstevel@tonic-gate 						if ((time_now - ps->start_time)
745*7c478bd9Sstevel@tonic-gate 							>= grace_period) {
746*7c478bd9Sstevel@tonic-gate 							if (verbose) {
747*7c478bd9Sstevel@tonic-gate 								printf(
748*7c478bd9Sstevel@tonic-gate 		    "no response from %s -- grace of %d seconds expired.\n",
749*7c478bd9Sstevel@tonic-gate 		    ps->svc_name, grace_period);
750*7c478bd9Sstevel@tonic-gate 								fflush(stdout);
751*7c478bd9Sstevel@tonic-gate 							}
752*7c478bd9Sstevel@tonic-gate 							fprintf(stderr,
753*7c478bd9Sstevel@tonic-gate 		    "No response from ypxfr on %s\n", ps->svc_name);
754*7c478bd9Sstevel@tonic-gate 						}
755*7c478bd9Sstevel@tonic-gate 					}
756*7c478bd9Sstevel@tonic-gate 				break;
757*7c478bd9Sstevel@tonic-gate 			}
758*7c478bd9Sstevel@tonic-gate 		}
759*7c478bd9Sstevel@tonic-gate 		actives = 0;
760*7c478bd9Sstevel@tonic-gate 		for (ps = active_list; ps; ps = ps->pnext) {
761*7c478bd9Sstevel@tonic-gate 			if (ps->state == SSTAT_CALLED) {
762*7c478bd9Sstevel@tonic-gate 				if ((time_now - ps->start_time)
763*7c478bd9Sstevel@tonic-gate 						< grace_period) {
764*7c478bd9Sstevel@tonic-gate 					actives++;
765*7c478bd9Sstevel@tonic-gate 
766*7c478bd9Sstevel@tonic-gate 					if (verbose) {
767*7c478bd9Sstevel@tonic-gate 						printf(
768*7c478bd9Sstevel@tonic-gate 		    "No response yet from ypxfr on %s\n", ps->svc_name);
769*7c478bd9Sstevel@tonic-gate 						fflush(stdout);
770*7c478bd9Sstevel@tonic-gate 					}
771*7c478bd9Sstevel@tonic-gate 				}
772*7c478bd9Sstevel@tonic-gate 			} else {
773*7c478bd9Sstevel@tonic-gate 				if (verbose) {
774*7c478bd9Sstevel@tonic-gate 					printf("Deactivating  %s\n",
775*7c478bd9Sstevel@tonic-gate 						ps->svc_name);
776*7c478bd9Sstevel@tonic-gate 					fflush(stdout);
777*7c478bd9Sstevel@tonic-gate 				}
778*7c478bd9Sstevel@tonic-gate 				delete_active(ps);
779*7c478bd9Sstevel@tonic-gate 			}
780*7c478bd9Sstevel@tonic-gate 		}
781*7c478bd9Sstevel@tonic-gate 
782*7c478bd9Sstevel@tonic-gate 		/* add someone to the active list keep up with curpar */
783*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < (curpar - actives); i++) {
784*7c478bd9Sstevel@tonic-gate 			if (add_to_active()) {
785*7c478bd9Sstevel@tonic-gate 				ps = active_list;
786*7c478bd9Sstevel@tonic-gate 				ps->state = send_message(ps, program, &error);
787*7c478bd9Sstevel@tonic-gate 				print_state_msg(ps, error);
788*7c478bd9Sstevel@tonic-gate 				if (ps->state != SSTAT_CALLED)
789*7c478bd9Sstevel@tonic-gate 					delete_active(ps);	/* zorch it */
790*7c478bd9Sstevel@tonic-gate 				else
791*7c478bd9Sstevel@tonic-gate 					ps->start_time = time(0); /* set time */
792*7c478bd9Sstevel@tonic-gate 			}
793*7c478bd9Sstevel@tonic-gate 		}
794*7c478bd9Sstevel@tonic-gate 		docb = 0;
795*7c478bd9Sstevel@tonic-gate 		for (ps = active_list; ps; ps = ps->pnext)
796*7c478bd9Sstevel@tonic-gate 			if (ps->state == SSTAT_CALLED) {
797*7c478bd9Sstevel@tonic-gate 				docb = 1;
798*7c478bd9Sstevel@tonic-gate 				break;
799*7c478bd9Sstevel@tonic-gate 			}
800*7c478bd9Sstevel@tonic-gate 		if (docb == 0) {
801*7c478bd9Sstevel@tonic-gate 			if (verbose) {
802*7c478bd9Sstevel@tonic-gate 				printf("No one to wait for this pass.\n");
803*7c478bd9Sstevel@tonic-gate 				fflush(stdout);
804*7c478bd9Sstevel@tonic-gate 			}
805*7c478bd9Sstevel@tonic-gate 			continue;	/* try curpar more */
806*7c478bd9Sstevel@tonic-gate 		}
807*7c478bd9Sstevel@tonic-gate 
808*7c478bd9Sstevel@tonic-gate 		if (npollfds != svc_max_pollfd) {
809*7c478bd9Sstevel@tonic-gate 			pollset = realloc(pollset,
810*7c478bd9Sstevel@tonic-gate 					sizeof (pollfd_t) * svc_max_pollfd);
811*7c478bd9Sstevel@tonic-gate 			npollfds = svc_max_pollfd;
812*7c478bd9Sstevel@tonic-gate 		}
813*7c478bd9Sstevel@tonic-gate 
814*7c478bd9Sstevel@tonic-gate 		/*
815*7c478bd9Sstevel@tonic-gate 		 * Get existing array of pollfd's, should really compress
816*7c478bd9Sstevel@tonic-gate 		 * this but it shouldn't get very large (or sparse).
817*7c478bd9Sstevel@tonic-gate 		 */
818*7c478bd9Sstevel@tonic-gate 		(void) memcpy(pollset, svc_pollfd,
819*7c478bd9Sstevel@tonic-gate 					sizeof (pollfd_t) * svc_max_pollfd);
820*7c478bd9Sstevel@tonic-gate 
821*7c478bd9Sstevel@tonic-gate 		errno = 0;
822*7c478bd9Sstevel@tonic-gate 		switch (pollret = poll(pollset, npollfds, MIN_GRACE * 1000)) {
823*7c478bd9Sstevel@tonic-gate 		    case -1:
824*7c478bd9Sstevel@tonic-gate 			if (errno != EINTR) {
825*7c478bd9Sstevel@tonic-gate 				(void) perror("main loop select");
826*7c478bd9Sstevel@tonic-gate 			}
827*7c478bd9Sstevel@tonic-gate 			break;
828*7c478bd9Sstevel@tonic-gate 
829*7c478bd9Sstevel@tonic-gate 		    case 0:
830*7c478bd9Sstevel@tonic-gate 			if (verbose) {
831*7c478bd9Sstevel@tonic-gate 				(void) printf("timeout in main loop select.\n");
832*7c478bd9Sstevel@tonic-gate 				fflush(stdout);
833*7c478bd9Sstevel@tonic-gate 			}
834*7c478bd9Sstevel@tonic-gate 			break;
835*7c478bd9Sstevel@tonic-gate 
836*7c478bd9Sstevel@tonic-gate 		    default:
837*7c478bd9Sstevel@tonic-gate 			svc_getreq_poll(pollset, pollret);
838*7c478bd9Sstevel@tonic-gate 			break;
839*7c478bd9Sstevel@tonic-gate 		}		/* switch */
840*7c478bd9Sstevel@tonic-gate 	}			/* for */
841*7c478bd9Sstevel@tonic-gate }
842*7c478bd9Sstevel@tonic-gate 
843*7c478bd9Sstevel@tonic-gate /*
844*7c478bd9Sstevel@tonic-gate  * This does the listener process cleanup and process exit.
845*7c478bd9Sstevel@tonic-gate  */
846*7c478bd9Sstevel@tonic-gate static void
847*7c478bd9Sstevel@tonic-gate listener_exit(unsigned long program, int stat)
848*7c478bd9Sstevel@tonic-gate {
849*7c478bd9Sstevel@tonic-gate 	svc_unreg(program, YPPUSHVERS);
850*7c478bd9Sstevel@tonic-gate 	exit(stat);
851*7c478bd9Sstevel@tonic-gate }
852*7c478bd9Sstevel@tonic-gate 
853*7c478bd9Sstevel@tonic-gate /*
854*7c478bd9Sstevel@tonic-gate  * This is the listener process' RPC service dispatcher.
855*7c478bd9Sstevel@tonic-gate  */
856*7c478bd9Sstevel@tonic-gate static void
857*7c478bd9Sstevel@tonic-gate listener_dispatch(struct svc_req *rqstp, SVCXPRT *transp)
858*7c478bd9Sstevel@tonic-gate {
859*7c478bd9Sstevel@tonic-gate 	switch (rqstp->rq_proc) {
860*7c478bd9Sstevel@tonic-gate 
861*7c478bd9Sstevel@tonic-gate 	case YPPUSHPROC_NULL:
862*7c478bd9Sstevel@tonic-gate 		if (!svc_sendreply(transp, xdr_void, 0)) {
863*7c478bd9Sstevel@tonic-gate 		    fprintf(stderr, "Can't reply to rpc call.\n");
864*7c478bd9Sstevel@tonic-gate 		}
865*7c478bd9Sstevel@tonic-gate 		break;
866*7c478bd9Sstevel@tonic-gate 
867*7c478bd9Sstevel@tonic-gate 	case YPPUSHPROC_XFRRESP:
868*7c478bd9Sstevel@tonic-gate 		get_xfr_response(transp);
869*7c478bd9Sstevel@tonic-gate 		break;
870*7c478bd9Sstevel@tonic-gate 
871*7c478bd9Sstevel@tonic-gate 	default:
872*7c478bd9Sstevel@tonic-gate 		svcerr_noproc(transp);
873*7c478bd9Sstevel@tonic-gate 		break;
874*7c478bd9Sstevel@tonic-gate 	}
875*7c478bd9Sstevel@tonic-gate }
876*7c478bd9Sstevel@tonic-gate 
877*7c478bd9Sstevel@tonic-gate 
878*7c478bd9Sstevel@tonic-gate /*
879*7c478bd9Sstevel@tonic-gate  *  This dumps a server state message to stdout.  It is called in cases where
880*7c478bd9Sstevel@tonic-gate  *  we have no expectation of receiving a callback from the remote ypxfr.
881*7c478bd9Sstevel@tonic-gate  */
882*7c478bd9Sstevel@tonic-gate static void
883*7c478bd9Sstevel@tonic-gate print_state_msg(struct server *s, long e)
884*7c478bd9Sstevel@tonic-gate {
885*7c478bd9Sstevel@tonic-gate 	struct state_duple *sd;
886*7c478bd9Sstevel@tonic-gate 
887*7c478bd9Sstevel@tonic-gate 	if (s->state == SSTAT_SYSTEM)
888*7c478bd9Sstevel@tonic-gate 		return;			/* already printed */
889*7c478bd9Sstevel@tonic-gate 
890*7c478bd9Sstevel@tonic-gate 	if (!verbose && (s->state == SSTAT_RESPONDED ||
891*7c478bd9Sstevel@tonic-gate 				s->state == SSTAT_CALLED))
892*7c478bd9Sstevel@tonic-gate 		return;
893*7c478bd9Sstevel@tonic-gate 
894*7c478bd9Sstevel@tonic-gate 	for (sd = state_duples; sd->state_msg; sd++) {
895*7c478bd9Sstevel@tonic-gate 		if (sd->state == s->state) {
896*7c478bd9Sstevel@tonic-gate 			printf(sd->state_msg, s->svc_name);
897*7c478bd9Sstevel@tonic-gate 
898*7c478bd9Sstevel@tonic-gate 			if (s->state == SSTAT_RPC) {
899*7c478bd9Sstevel@tonic-gate 				rpcerr_msg((enum clnt_stat) e);
900*7c478bd9Sstevel@tonic-gate 			}
901*7c478bd9Sstevel@tonic-gate 
902*7c478bd9Sstevel@tonic-gate 			printf("\n");
903*7c478bd9Sstevel@tonic-gate 			fflush(stdout);
904*7c478bd9Sstevel@tonic-gate 			return;
905*7c478bd9Sstevel@tonic-gate 		}
906*7c478bd9Sstevel@tonic-gate 	}
907*7c478bd9Sstevel@tonic-gate 
908*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "yppush: Bad server state value %d.\n", s->state);
909*7c478bd9Sstevel@tonic-gate }
910*7c478bd9Sstevel@tonic-gate 
911*7c478bd9Sstevel@tonic-gate /*
912*7c478bd9Sstevel@tonic-gate  *  This dumps a transfer status message to stdout.  It is called in
913*7c478bd9Sstevel@tonic-gate  *  response to a received RPC message from the called ypxfr.
914*7c478bd9Sstevel@tonic-gate  */
915*7c478bd9Sstevel@tonic-gate static void
916*7c478bd9Sstevel@tonic-gate print_callback_msg(struct server *s)
917*7c478bd9Sstevel@tonic-gate {
918*7c478bd9Sstevel@tonic-gate 	register struct status_duple *sd;
919*7c478bd9Sstevel@tonic-gate 
920*7c478bd9Sstevel@tonic-gate 	if (!verbose &&
921*7c478bd9Sstevel@tonic-gate 		(s->status == YPPUSH_AGE) ||
922*7c478bd9Sstevel@tonic-gate 		(s->status == YPPUSH_SUCC))
923*7c478bd9Sstevel@tonic-gate 
924*7c478bd9Sstevel@tonic-gate 		return;
925*7c478bd9Sstevel@tonic-gate 
926*7c478bd9Sstevel@tonic-gate 	for (sd = status_duples; sd->status_msg; sd++) {
927*7c478bd9Sstevel@tonic-gate 
928*7c478bd9Sstevel@tonic-gate 		if (sd->status == s->status) {
929*7c478bd9Sstevel@tonic-gate 			printf("Status received from ypxfr on %s:\n\t%s\n",
930*7c478bd9Sstevel@tonic-gate 				s->svc_name, sd->status_msg);
931*7c478bd9Sstevel@tonic-gate 			fflush(stdout);
932*7c478bd9Sstevel@tonic-gate 			return;
933*7c478bd9Sstevel@tonic-gate 		}
934*7c478bd9Sstevel@tonic-gate 	}
935*7c478bd9Sstevel@tonic-gate 
936*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "yppush listener: Garbage transaction "
937*7c478bd9Sstevel@tonic-gate 			"status (value %d) from ypxfr on %s.\n",
938*7c478bd9Sstevel@tonic-gate 			(int)s->status, s->svc_name);
939*7c478bd9Sstevel@tonic-gate }
940*7c478bd9Sstevel@tonic-gate 
941*7c478bd9Sstevel@tonic-gate /*
942*7c478bd9Sstevel@tonic-gate  *  This dumps an RPC error message to stdout.  This is basically a rewrite
943*7c478bd9Sstevel@tonic-gate  *  of clnt_perrno, but writes to stdout instead of stderr.
944*7c478bd9Sstevel@tonic-gate  */
945*7c478bd9Sstevel@tonic-gate static void
946*7c478bd9Sstevel@tonic-gate rpcerr_msg(enum clnt_stat e)
947*7c478bd9Sstevel@tonic-gate {
948*7c478bd9Sstevel@tonic-gate 	struct rpcerr_duple *rd;
949*7c478bd9Sstevel@tonic-gate 
950*7c478bd9Sstevel@tonic-gate 	for (rd = rpcerr_duples; rd->rpc_msg; rd++) {
951*7c478bd9Sstevel@tonic-gate 
952*7c478bd9Sstevel@tonic-gate 		if (rd->rpc_stat == e) {
953*7c478bd9Sstevel@tonic-gate 			printf(rd->rpc_msg);
954*7c478bd9Sstevel@tonic-gate 			return;
955*7c478bd9Sstevel@tonic-gate 		}
956*7c478bd9Sstevel@tonic-gate 	}
957*7c478bd9Sstevel@tonic-gate 
958*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "Bad error code passed to rpcerr_msg: %d.\n", e);
959*7c478bd9Sstevel@tonic-gate }
960*7c478bd9Sstevel@tonic-gate 
961*7c478bd9Sstevel@tonic-gate /*
962*7c478bd9Sstevel@tonic-gate  * This picks up the response from the ypxfr process which has been started
963*7c478bd9Sstevel@tonic-gate  * up on the remote node.  The response status must be non-zero, otherwise
964*7c478bd9Sstevel@tonic-gate  * the status will be set to "ypxfr error".
965*7c478bd9Sstevel@tonic-gate  */
966*7c478bd9Sstevel@tonic-gate static void
967*7c478bd9Sstevel@tonic-gate get_xfr_response(SVCXPRT *transp)
968*7c478bd9Sstevel@tonic-gate {
969*7c478bd9Sstevel@tonic-gate 	struct yppushresp_xfr resp;
970*7c478bd9Sstevel@tonic-gate 	register struct server *s;
971*7c478bd9Sstevel@tonic-gate 
972*7c478bd9Sstevel@tonic-gate 	if (!svc_getargs(transp, (xdrproc_t)xdr_yppushresp_xfr,
973*7c478bd9Sstevel@tonic-gate 			(caddr_t)&resp)) {
974*7c478bd9Sstevel@tonic-gate 		svcerr_decode(transp);
975*7c478bd9Sstevel@tonic-gate 		return;
976*7c478bd9Sstevel@tonic-gate 	}
977*7c478bd9Sstevel@tonic-gate 
978*7c478bd9Sstevel@tonic-gate 	if (!svc_sendreply(transp, xdr_void, 0)) {
979*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Can't reply to rpc call.\n");
980*7c478bd9Sstevel@tonic-gate 	}
981*7c478bd9Sstevel@tonic-gate 
982*7c478bd9Sstevel@tonic-gate 	for (s = active_list; s; s = s->pnext) {
983*7c478bd9Sstevel@tonic-gate 
984*7c478bd9Sstevel@tonic-gate 		if (s->xactid == resp.transid) {
985*7c478bd9Sstevel@tonic-gate 			s->status  = resp.status ? resp.status: YPPUSH_XFRERR;
986*7c478bd9Sstevel@tonic-gate 			print_callback_msg(s);
987*7c478bd9Sstevel@tonic-gate 			s->state = SSTAT_RESPONDED;
988*7c478bd9Sstevel@tonic-gate 			return;
989*7c478bd9Sstevel@tonic-gate 		}
990*7c478bd9Sstevel@tonic-gate 	}
991*7c478bd9Sstevel@tonic-gate }
992*7c478bd9Sstevel@tonic-gate 
993*7c478bd9Sstevel@tonic-gate /*
994*7c478bd9Sstevel@tonic-gate  * This sends a message to a single ypserv process.  The return value is
995*7c478bd9Sstevel@tonic-gate  * a state value.  If the RPC call fails because of a version
996*7c478bd9Sstevel@tonic-gate  * mismatch, we'll assume that we're talking to a version 1 ypserv process,
997*7c478bd9Sstevel@tonic-gate  * and will send him an old "YPPROC_GET" request, as was defined in the
998*7c478bd9Sstevel@tonic-gate  * earlier version of yp_prot.h
999*7c478bd9Sstevel@tonic-gate  */
1000*7c478bd9Sstevel@tonic-gate static unsigned short
1001*7c478bd9Sstevel@tonic-gate send_message(struct server *ps, unsigned long program, long *err)
1002*7c478bd9Sstevel@tonic-gate {
1003*7c478bd9Sstevel@tonic-gate 	struct ypreq_newxfr req;
1004*7c478bd9Sstevel@tonic-gate 	struct ypreq_xfr oldreq;
1005*7c478bd9Sstevel@tonic-gate 	enum clnt_stat s;
1006*7c478bd9Sstevel@tonic-gate 	struct rpc_err rpcerr;
1007*7c478bd9Sstevel@tonic-gate 
1008*7c478bd9Sstevel@tonic-gate 	if ((ps->domb.dom_client = __yp_clnt_create_rsvdport(ps->svc_name,
1009*7c478bd9Sstevel@tonic-gate 							YPPROG, YPVERS,
1010*7c478bd9Sstevel@tonic-gate 							(char *)NULL,
1011*7c478bd9Sstevel@tonic-gate 							0, 0))  == NULL) {
1012*7c478bd9Sstevel@tonic-gate 
1013*7c478bd9Sstevel@tonic-gate 		if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED) {
1014*7c478bd9Sstevel@tonic-gate 			return (SSTAT_PROGNOTREG);
1015*7c478bd9Sstevel@tonic-gate 		} else {
1016*7c478bd9Sstevel@tonic-gate 			printf("Error talking to %s: ", ps->svc_name);
1017*7c478bd9Sstevel@tonic-gate 			rpcerr_msg(rpc_createerr.cf_stat);
1018*7c478bd9Sstevel@tonic-gate 			printf("\n");
1019*7c478bd9Sstevel@tonic-gate 			fflush(stdout);
1020*7c478bd9Sstevel@tonic-gate 			return (SSTAT_SYSTEM);
1021*7c478bd9Sstevel@tonic-gate 		}
1022*7c478bd9Sstevel@tonic-gate 	}
1023*7c478bd9Sstevel@tonic-gate 
1024*7c478bd9Sstevel@tonic-gate 	if (sysinfo(SI_HOSTNAME, my_name, sizeof (my_name)) == -1) {
1025*7c478bd9Sstevel@tonic-gate 		return (SSTAT_RSCRC);
1026*7c478bd9Sstevel@tonic-gate 	}
1027*7c478bd9Sstevel@tonic-gate 
1028*7c478bd9Sstevel@tonic-gate 	if (!oldxfr) {
1029*7c478bd9Sstevel@tonic-gate 		req.ypxfr_domain = domain;
1030*7c478bd9Sstevel@tonic-gate 		req.ypxfr_map = map;
1031*7c478bd9Sstevel@tonic-gate 		req.ypxfr_ordernum = 0;
1032*7c478bd9Sstevel@tonic-gate 		req.ypxfr_owner = my_name;
1033*7c478bd9Sstevel@tonic-gate 		req.name = ps->svc_name;
1034*7c478bd9Sstevel@tonic-gate 		/*
1035*7c478bd9Sstevel@tonic-gate 		 * the creation of field req.name, instead of ypreq_xfr (old)
1036*7c478bd9Sstevel@tonic-gate 		 * req.port, does not make any sense. it doesn't give any
1037*7c478bd9Sstevel@tonic-gate 		 * information to receiving ypserv except its own name !!
1038*7c478bd9Sstevel@tonic-gate 		 * new ypserv duplicates work for YPPROC_XFR and YPPROC_NEWXFR
1039*7c478bd9Sstevel@tonic-gate 		 */
1040*7c478bd9Sstevel@tonic-gate 		req.transid = ps->xactid;
1041*7c478bd9Sstevel@tonic-gate 		req.proto = program;
1042*7c478bd9Sstevel@tonic-gate 		s = (enum clnt_stat) clnt_call(ps->domb.dom_client,
1043*7c478bd9Sstevel@tonic-gate 						YPPROC_NEWXFR,
1044*7c478bd9Sstevel@tonic-gate 						(xdrproc_t)xdr_ypreq_newxfr,
1045*7c478bd9Sstevel@tonic-gate 						(caddr_t)&req,
1046*7c478bd9Sstevel@tonic-gate 						xdr_void, 0, timeout);
1047*7c478bd9Sstevel@tonic-gate 	}
1048*7c478bd9Sstevel@tonic-gate 
1049*7c478bd9Sstevel@tonic-gate 	clnt_geterr(ps->domb.dom_client, &rpcerr);
1050*7c478bd9Sstevel@tonic-gate 
1051*7c478bd9Sstevel@tonic-gate 	if (s == RPC_PROCUNAVAIL) {
1052*7c478bd9Sstevel@tonic-gate 		oldreq.ypxfr_domain = domain;
1053*7c478bd9Sstevel@tonic-gate 		oldreq.ypxfr_map = map;
1054*7c478bd9Sstevel@tonic-gate 		oldreq.ypxfr_ordernum = 0;
1055*7c478bd9Sstevel@tonic-gate 		oldreq.ypxfr_owner = my_name;
1056*7c478bd9Sstevel@tonic-gate 		oldreq.transid = ps->xactid;
1057*7c478bd9Sstevel@tonic-gate 		oldreq.proto = program;
1058*7c478bd9Sstevel@tonic-gate 		oldreq.port = 0;
1059*7c478bd9Sstevel@tonic-gate 		s = (enum clnt_stat) clnt_call(ps->domb.dom_client,
1060*7c478bd9Sstevel@tonic-gate 						YPPROC_XFR,
1061*7c478bd9Sstevel@tonic-gate 						(xdrproc_t)xdr_ypreq_xfr,
1062*7c478bd9Sstevel@tonic-gate 						(caddr_t)&oldreq,
1063*7c478bd9Sstevel@tonic-gate 						xdr_void, 0, timeout);
1064*7c478bd9Sstevel@tonic-gate 		clnt_geterr(ps->domb.dom_client, &rpcerr);
1065*7c478bd9Sstevel@tonic-gate 	}
1066*7c478bd9Sstevel@tonic-gate 
1067*7c478bd9Sstevel@tonic-gate 	clnt_destroy(ps->domb.dom_client);
1068*7c478bd9Sstevel@tonic-gate 
1069*7c478bd9Sstevel@tonic-gate 	if (s == RPC_SUCCESS) {
1070*7c478bd9Sstevel@tonic-gate 		return (SSTAT_CALLED);
1071*7c478bd9Sstevel@tonic-gate 	} else {
1072*7c478bd9Sstevel@tonic-gate 		*err = (long)rpcerr.re_status;
1073*7c478bd9Sstevel@tonic-gate 		return (SSTAT_RPC);
1074*7c478bd9Sstevel@tonic-gate 	}
1075*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
1076*7c478bd9Sstevel@tonic-gate }
1077*7c478bd9Sstevel@tonic-gate 
1078*7c478bd9Sstevel@tonic-gate /*
1079*7c478bd9Sstevel@tonic-gate  * FUNCTION:    is_yptol_mode();
1080*7c478bd9Sstevel@tonic-gate  *
1081*7c478bd9Sstevel@tonic-gate  * DESCRIPTION: Determines if we should run in N2L or traditional mode based
1082*7c478bd9Sstevel@tonic-gate  *              on the presence of the N2L mapping file.
1083*7c478bd9Sstevel@tonic-gate  *
1084*7c478bd9Sstevel@tonic-gate  *		This is a copy of a function from libnisdb. If more than this
1085*7c478bd9Sstevel@tonic-gate  *		one function become required it may be worth linking the
1086*7c478bd9Sstevel@tonic-gate  *		entire lib.
1087*7c478bd9Sstevel@tonic-gate  *
1088*7c478bd9Sstevel@tonic-gate  * INPUTS:      Nothing
1089*7c478bd9Sstevel@tonic-gate  *
1090*7c478bd9Sstevel@tonic-gate  * OUTPUTS:     TRUE = Run in N2L mode
1091*7c478bd9Sstevel@tonic-gate  *              FALSE = Run in traditional mode.
1092*7c478bd9Sstevel@tonic-gate  */
1093*7c478bd9Sstevel@tonic-gate bool_t
1094*7c478bd9Sstevel@tonic-gate is_yptol_mode()
1095*7c478bd9Sstevel@tonic-gate {
1096*7c478bd9Sstevel@tonic-gate 	struct stat filestat;
1097*7c478bd9Sstevel@tonic-gate 
1098*7c478bd9Sstevel@tonic-gate 	if (stat(NTOL_MAP_FILE, &filestat) != -1)
1099*7c478bd9Sstevel@tonic-gate 		return (TRUE);
1100*7c478bd9Sstevel@tonic-gate 
1101*7c478bd9Sstevel@tonic-gate 	return (FALSE);
1102*7c478bd9Sstevel@tonic-gate }
1103