xref: /onnv-gate/usr/src/cmd/ypcmd/yppush.c (revision 7035:f93a1cefda5f)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7035Svt115884  * Common Development and Distribution License (the "License").
6*7035Svt115884  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  *
21*7035Svt115884  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
220Sstevel@tonic-gate  * Use is subject to license terms.
230Sstevel@tonic-gate  *
240Sstevel@tonic-gate  * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
250Sstevel@tonic-gate  * All Rights Reserved
260Sstevel@tonic-gate  *
270Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley
280Sstevel@tonic-gate  * 4.3 BSD under license from the Regents of the University of
290Sstevel@tonic-gate  * California.
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #define	_SVID_GETTOD
350Sstevel@tonic-gate #include	<sys/time.h>
360Sstevel@tonic-gate extern int gettimeofday(struct timeval *);
370Sstevel@tonic-gate 
380Sstevel@tonic-gate #include	<sys/types.h>
390Sstevel@tonic-gate #include	<stdio.h>
400Sstevel@tonic-gate #include	<string.h>
410Sstevel@tonic-gate #include	<malloc.h>
420Sstevel@tonic-gate #include	<errno.h>
430Sstevel@tonic-gate #include	<signal.h>
440Sstevel@tonic-gate #include	<limits.h>
450Sstevel@tonic-gate #include	<stdlib.h>
460Sstevel@tonic-gate #include	<unistd.h>
470Sstevel@tonic-gate #include	<sys/types.h>
480Sstevel@tonic-gate #include	<sys/wait.h>
490Sstevel@tonic-gate #include	<sys/stat.h>
500Sstevel@tonic-gate #include	<ctype.h>
510Sstevel@tonic-gate #include	<dirent.h>
520Sstevel@tonic-gate #include	<rpc/rpc.h>
530Sstevel@tonic-gate #include	<rpc/nettype.h>
540Sstevel@tonic-gate #include	<rpc/rpcb_prot.h>
550Sstevel@tonic-gate #include	<rpc/rpcb_clnt.h>
560Sstevel@tonic-gate #include	<sys/systeminfo.h>
570Sstevel@tonic-gate #include	<sys/select.h>
580Sstevel@tonic-gate #include	"ypsym.h"
590Sstevel@tonic-gate #include	"ypdefs.h"
600Sstevel@tonic-gate #include	"yp_b.h"
610Sstevel@tonic-gate #include	"shim.h"
620Sstevel@tonic-gate #include	"yptol.h"
630Sstevel@tonic-gate 
640Sstevel@tonic-gate 
650Sstevel@tonic-gate #ifdef DEBUG
660Sstevel@tonic-gate #undef YPPROG
670Sstevel@tonic-gate #define	YPPROG ((ulong_t)109999)
680Sstevel@tonic-gate #undef YPBINDPROG
690Sstevel@tonic-gate #define	YPBINDPROG ((ulong_t)109998)
700Sstevel@tonic-gate #endif
710Sstevel@tonic-gate 
720Sstevel@tonic-gate #define	INTER_TRY 12			/* Seconds between tries */
730Sstevel@tonic-gate #define	PORTMAP_TIME 30			/* Seconds before decide its down */
740Sstevel@tonic-gate #define	TIMEOUT INTER_TRY*4		/* Total time for timeout */
750Sstevel@tonic-gate #define	CUR_PAR 4			/* Total  parallal yppushes */
760Sstevel@tonic-gate #define	MIN_GRACE 25			/* select timeout and minimum grace */
770Sstevel@tonic-gate #define	GRACE_PERIOD 800		/* Total seconds we'll wait for	*/
780Sstevel@tonic-gate 					/* responses from ypxfrs, yes	*/
790Sstevel@tonic-gate 					/* virginia yp map transfers	*/
800Sstevel@tonic-gate 					/* can take a long time, we	*/
810Sstevel@tonic-gate 					/* only worry if the slave 	*/
820Sstevel@tonic-gate 					/* crashes ...			*/
830Sstevel@tonic-gate 
840Sstevel@tonic-gate USE_YPDBPATH
850Sstevel@tonic-gate static char *pusage;
860Sstevel@tonic-gate static char *domain = NULL;
870Sstevel@tonic-gate static char *host = NULL;
880Sstevel@tonic-gate static char my_name[YPMAXPEER +1];
890Sstevel@tonic-gate static char default_domain_name[YPMAXDOMAIN];
900Sstevel@tonic-gate static char domain_alias[MAXNAMLEN]; 	/* nickname for domain -	*/
910Sstevel@tonic-gate 					/*	used in sysv filesystems */
920Sstevel@tonic-gate static char map_alias[MAXNAMLEN];	/* nickname for map -		*/
930Sstevel@tonic-gate 					/*	used in sysv filesystems */
940Sstevel@tonic-gate static char *map = NULL;
950Sstevel@tonic-gate static bool verbose = FALSE;
960Sstevel@tonic-gate static bool onehost = FALSE;
970Sstevel@tonic-gate static bool oldxfr = FALSE;
980Sstevel@tonic-gate static bool callback_timeout = FALSE;	/* set when a callback times out */
990Sstevel@tonic-gate int grace_period = GRACE_PERIOD;
1000Sstevel@tonic-gate int curpar = CUR_PAR;			/* should be set by other stuff */
1010Sstevel@tonic-gate static char ypmapname[1024];		/* Used to check for map's existence */
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate static struct timeval intertry = {
1040Sstevel@tonic-gate 	INTER_TRY,			/* Seconds */
1050Sstevel@tonic-gate 	0				/* Microseconds */
1060Sstevel@tonic-gate };
1070Sstevel@tonic-gate static struct timeval timeout = {
1080Sstevel@tonic-gate 	TIMEOUT,			/* Seconds */
1090Sstevel@tonic-gate 	0				/* Microseconds */
1100Sstevel@tonic-gate };
1110Sstevel@tonic-gate static SVCXPRT *transport4;
1120Sstevel@tonic-gate static SVCXPRT *transport6;
1130Sstevel@tonic-gate struct server {
1140Sstevel@tonic-gate 	struct server *pnext;
1150Sstevel@tonic-gate 	struct dom_binding domb;
1160Sstevel@tonic-gate 	char svc_name[YPMAXPEER+1];
1170Sstevel@tonic-gate 	unsigned long xactid;
1180Sstevel@tonic-gate 	unsigned short state;
1190Sstevel@tonic-gate 	unsigned long status;
1200Sstevel@tonic-gate 	bool oldvers;
1210Sstevel@tonic-gate 	int start_time;
1220Sstevel@tonic-gate };
1230Sstevel@tonic-gate #define	n_conf dom_binding->ypbind_nconf
1240Sstevel@tonic-gate #define	svc_addr dom_binding->ypbind_svcaddr
1250Sstevel@tonic-gate static struct server *server_list = (struct server *)NULL;
1260Sstevel@tonic-gate static struct server *active_list = (struct server *)NULL;
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate /*  State values for server.state field */
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate #define	SSTAT_INIT 0
1310Sstevel@tonic-gate #define	SSTAT_CALLED 1
1320Sstevel@tonic-gate #define	SSTAT_RESPONDED 2
1330Sstevel@tonic-gate #define	SSTAT_PROGNOTREG 3
1340Sstevel@tonic-gate #define	SSTAT_RPC 4
1350Sstevel@tonic-gate #define	SSTAT_RSCRC 5
1360Sstevel@tonic-gate #define	SSTAT_SYSTEM 6
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate static char err_usage[] =
1390Sstevel@tonic-gate "Usage:\n\typpush [-p <par>] [-d <domainname>] [-h <hostname>] [-v] map\n";
1400Sstevel@tonic-gate static char err_bad_args[] =
1410Sstevel@tonic-gate 	"The %s argument is bad.\n";
1420Sstevel@tonic-gate static char err_cant_get_kname[] =
1430Sstevel@tonic-gate 	"Can't get %s from system call.\n";
1440Sstevel@tonic-gate static char err_null_kname[] =
1450Sstevel@tonic-gate 	"The %s hasn't been set on this machine.\n";
1460Sstevel@tonic-gate static char err_bad_domainname[] = "domainname";
1470Sstevel@tonic-gate static char err_cant_bind[] =
1480Sstevel@tonic-gate 	"Can't find a yp server for domain %s.  Reason:  %s.\n";
1490Sstevel@tonic-gate static char err_cant_build_serverlist[] =
1500Sstevel@tonic-gate 	"Can't build server list from map \"ypservers\".  Reason:  %s.\n";
1510Sstevel@tonic-gate static char err_cant_find_host[] =
1520Sstevel@tonic-gate 	"Can't find host %s in map \"ypservers\".\n";
1530Sstevel@tonic-gate /*
1540Sstevel@tonic-gate  * State_duple table.  All messages should take 1 arg - the node name.
1550Sstevel@tonic-gate  */
1560Sstevel@tonic-gate struct state_duple {
1570Sstevel@tonic-gate 	int state;
1580Sstevel@tonic-gate 	char *state_msg;
1590Sstevel@tonic-gate };
1600Sstevel@tonic-gate static struct state_duple state_duples[] = {
1610Sstevel@tonic-gate 	{SSTAT_INIT, "Internal error trying to talk to %s."},
1620Sstevel@tonic-gate 	{SSTAT_CALLED, "%s has been called."},
1630Sstevel@tonic-gate 	{SSTAT_RESPONDED, "%s (v1 ypserv) sent an old-style request."},
1640Sstevel@tonic-gate 	{SSTAT_PROGNOTREG, "nis server not registered at %s."},
1650Sstevel@tonic-gate 	{SSTAT_RPC, "RPC error to %s:  "},
1660Sstevel@tonic-gate 	{SSTAT_RSCRC, "Local resource allocation failure - can't talk to %s."},
1670Sstevel@tonic-gate 	{SSTAT_SYSTEM, "System error talking to %s:  "},
1680Sstevel@tonic-gate 	{0, (char *)NULL}
1690Sstevel@tonic-gate };
1700Sstevel@tonic-gate /*
1710Sstevel@tonic-gate  * Status_duple table.  No messages should require any args.
1720Sstevel@tonic-gate  */
173702Sth160488 struct status_duple {
1740Sstevel@tonic-gate 	long status;
1750Sstevel@tonic-gate 	char *status_msg;
1760Sstevel@tonic-gate };
1770Sstevel@tonic-gate static struct status_duple status_duples[] = {
1780Sstevel@tonic-gate 	{YPPUSH_SUCC, "Map successfully transferred."},
1790Sstevel@tonic-gate 	{YPPUSH_AGE,
1800Sstevel@tonic-gate 	    "Transfer not done:  master's version isn't newer."},
1810Sstevel@tonic-gate 	{YPPUSH_NOMAP, "Failed - ypxfr there can't find a server for map."},
1820Sstevel@tonic-gate 	{YPPUSH_NODOM, "Failed - domain isn't supported."},
1830Sstevel@tonic-gate 	{YPPUSH_RSRC, "Failed - local resource allocation failure."},
1840Sstevel@tonic-gate 	{YPPUSH_RPC, "Failed - ypxfr had an RPC failure"},
1850Sstevel@tonic-gate 	{YPPUSH_MADDR, "Failed - ypxfr couldn't get the map master's address."},
1860Sstevel@tonic-gate 	{YPPUSH_YPERR, "Failed - nis server or map format error."},
1870Sstevel@tonic-gate 	{YPPUSH_BADARGS, "Failed - args to ypxfr were bad."},
1880Sstevel@tonic-gate 	{YPPUSH_DBM, "Failed - dbm operation on map failed."},
1890Sstevel@tonic-gate 	{YPPUSH_FILE, "Failed - file I/O operation on map failed"},
1900Sstevel@tonic-gate 	{YPPUSH_SKEW, "Failed - map version skew during transfer."},
1910Sstevel@tonic-gate 	{YPPUSH_CLEAR,
1920Sstevel@tonic-gate 		"Map successfully transferred, but ypxfr \
1930Sstevel@tonic-gate 		couldn't send \"Clear map\" to ypserv "},
1940Sstevel@tonic-gate 	{YPPUSH_FORCE,
1950Sstevel@tonic-gate 	    "Failed - no local order number in map - use -f flag to ypxfr."},
1960Sstevel@tonic-gate 	{YPPUSH_XFRERR, "Failed - ypxfr internal error."},
1970Sstevel@tonic-gate 	{YPPUSH_REFUSED, "Failed - Transfer request refused."},
1980Sstevel@tonic-gate 	{YPPUSH_NOALIAS,
1990Sstevel@tonic-gate 		"Failed - System V domain/map alias not in alias file."},
2000Sstevel@tonic-gate 	{0, (char *)NULL}
2010Sstevel@tonic-gate };
2020Sstevel@tonic-gate /*
2030Sstevel@tonic-gate  * rpcerr_duple table
2040Sstevel@tonic-gate  */
205702Sth160488 struct rpcerr_duple {
2060Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
2070Sstevel@tonic-gate 	char *rpc_msg;
2080Sstevel@tonic-gate };
2090Sstevel@tonic-gate static struct rpcerr_duple rpcerr_duples[] = {
2100Sstevel@tonic-gate 	{RPC_SUCCESS, "RPC success"},
2110Sstevel@tonic-gate 	{RPC_CANTENCODEARGS, "RPC Can't encode args"},
2120Sstevel@tonic-gate 	{RPC_CANTDECODERES, "RPC Can't decode results"},
2130Sstevel@tonic-gate 	{RPC_CANTSEND, "RPC Can't send"},
2140Sstevel@tonic-gate 	{RPC_CANTRECV, "RPC Can't recv"},
2150Sstevel@tonic-gate 	{RPC_TIMEDOUT, "NIS server registered, but does not respond"},
2160Sstevel@tonic-gate 	{RPC_VERSMISMATCH, "RPC version mismatch"},
2170Sstevel@tonic-gate 	{RPC_AUTHERROR, "RPC auth error"},
2180Sstevel@tonic-gate 	{RPC_PROGUNAVAIL, "RPC remote program unavailable"},
2190Sstevel@tonic-gate 	{RPC_PROGVERSMISMATCH, "RPC program mismatch"},
2200Sstevel@tonic-gate 	{RPC_PROCUNAVAIL, "RPC unknown procedure"},
2210Sstevel@tonic-gate 	{RPC_CANTDECODEARGS, "RPC Can't decode args"},
2220Sstevel@tonic-gate 	{RPC_UNKNOWNHOST, "unknown host"},
2230Sstevel@tonic-gate 	{RPC_RPCBFAILURE, "rpcbind failure (host is down?)"},
2240Sstevel@tonic-gate 	{RPC_PROGNOTREGISTERED, "RPC prog not registered"},
2250Sstevel@tonic-gate 	{RPC_SYSTEMERROR, "RPC system error"},
2260Sstevel@tonic-gate 	{RPC_SUCCESS, (char *)NULL}		/* Duplicate rpc_stat 	*/
2270Sstevel@tonic-gate 						/* unused in list-end 	*/
2280Sstevel@tonic-gate 						/* entry */
2290Sstevel@tonic-gate };
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate static void get_default_domain_name(void);
2320Sstevel@tonic-gate static void get_command_line_args(int argc, char **argv);
2330Sstevel@tonic-gate static unsigned short send_message(struct server *ps,
2340Sstevel@tonic-gate 					unsigned long program, long *err);
2350Sstevel@tonic-gate static void make_server_list(void);
2360Sstevel@tonic-gate static void one_host_list(void);
2370Sstevel@tonic-gate static void add_server(char *sname, int namelen);
2380Sstevel@tonic-gate static int  generate_callback(unsigned long *program);
2390Sstevel@tonic-gate static void xactid_seed(unsigned long *xactid);
2400Sstevel@tonic-gate static void main_loop(unsigned long program);
2410Sstevel@tonic-gate static void listener_exit(unsigned long program, int stat);
2420Sstevel@tonic-gate static void listener_dispatch(struct svc_req *rqstp, SVCXPRT *transp);
2430Sstevel@tonic-gate static void print_state_msg(struct server *s, long e);
2440Sstevel@tonic-gate static void print_callback_msg(struct server *s);
2450Sstevel@tonic-gate static void rpcerr_msg(enum clnt_stat e);
2460Sstevel@tonic-gate static void get_xfr_response(SVCXPRT *transp);
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate #ifdef SYSVCONFIG
2490Sstevel@tonic-gate extern void sysvconfig(void);
2500Sstevel@tonic-gate #endif
2510Sstevel@tonic-gate extern int yp_getalias(char *key, char *key_alias, int maxlen);
2520Sstevel@tonic-gate extern int getdomainname(char *, int);
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate extern struct rpc_createerr rpc_createerr;
2550Sstevel@tonic-gate extern CLIENT *__yp_clnt_create_rsvdport();
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate int
main(int argc,char ** argv)2580Sstevel@tonic-gate main(int argc, char **argv)
2590Sstevel@tonic-gate {
2600Sstevel@tonic-gate 	unsigned long program;
261*7035Svt115884 	struct stat64 sbuf;
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	get_command_line_args(argc, argv);
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	if (!domain) {
2660Sstevel@tonic-gate 		get_default_domain_name();
2670Sstevel@tonic-gate 	}
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate #ifdef SYSVCONFIG
2700Sstevel@tonic-gate 	sysvconfig();
2710Sstevel@tonic-gate #endif
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 	if (yp_getalias(domain, domain_alias, NAME_MAX) != 0)
2740Sstevel@tonic-gate 		fprintf(stderr, "domain alias for %s not found\n", domain);
2750Sstevel@tonic-gate 	if (yp_getalias(map, map_alias, MAXALIASLEN) != 0)
2760Sstevel@tonic-gate 		fprintf(stderr, "map alias for %s not found\n", map);
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 	/* check to see if the map exists in this domain */
2790Sstevel@tonic-gate 	if (is_yptol_mode())
2800Sstevel@tonic-gate 		sprintf(ypmapname, "%s/%s/%s%s.dir", ypdbpath, domain_alias,
281*7035Svt115884 		    NTOL_PREFIX, map_alias);
2820Sstevel@tonic-gate 	else
2830Sstevel@tonic-gate 		sprintf(ypmapname, "%s/%s/%s.dir", ypdbpath, domain_alias,
284*7035Svt115884 		    map_alias);
285*7035Svt115884 	if (stat64(ypmapname, &sbuf) < 0) {
2860Sstevel@tonic-gate 		fprintf(stderr, "yppush: Map does not exist.\n");
2870Sstevel@tonic-gate 		exit(1);
2880Sstevel@tonic-gate 	}
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 	if (onehost) {
2910Sstevel@tonic-gate 		one_host_list();
2920Sstevel@tonic-gate 	} else {
2930Sstevel@tonic-gate 		make_server_list();
2940Sstevel@tonic-gate 	}
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 	/*
2970Sstevel@tonic-gate 	 * All process exits after the call to generate_callback should be
2980Sstevel@tonic-gate 	 * through listener_exit(program, status), not exit(status), so the
2990Sstevel@tonic-gate 	 * transient server can get unregistered with the portmapper.
3000Sstevel@tonic-gate 	 */
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 	if (!generate_callback(&program)) {
3030Sstevel@tonic-gate 		fprintf(stderr, "Can't set up transient callback server.\n");
3040Sstevel@tonic-gate 	}
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 	main_loop(program);
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	listener_exit(program, 0);
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 	/* NOTREACHED */
3110Sstevel@tonic-gate 	return (0);
3120Sstevel@tonic-gate }
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate /*
3150Sstevel@tonic-gate  * This does the command line parsing.
3160Sstevel@tonic-gate  */
3170Sstevel@tonic-gate static void
get_command_line_args(int argc,char ** argv)3180Sstevel@tonic-gate get_command_line_args(int argc, char **argv)
3190Sstevel@tonic-gate {
3200Sstevel@tonic-gate 	pusage = err_usage;
3210Sstevel@tonic-gate 	argv++;
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 	if (argc < 2) {
3240Sstevel@tonic-gate 		fprintf(stderr, pusage);
3250Sstevel@tonic-gate 		exit(1);
3260Sstevel@tonic-gate 	}
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	while (--argc) {
3290Sstevel@tonic-gate 		if ((*argv)[0] == '-') {
3300Sstevel@tonic-gate 			switch ((*argv)[1]) {
3310Sstevel@tonic-gate 			case 'v':
3320Sstevel@tonic-gate 				verbose = TRUE;
3330Sstevel@tonic-gate 				argv++;
3340Sstevel@tonic-gate 				break;
3350Sstevel@tonic-gate 			case 'd':
3360Sstevel@tonic-gate 				if (argc > 1) {
3370Sstevel@tonic-gate 					argv++;
3380Sstevel@tonic-gate 					argc--;
3390Sstevel@tonic-gate 					domain = *argv;
3400Sstevel@tonic-gate 					argv++;
3410Sstevel@tonic-gate 					if (((int)strlen(domain)) >
342*7035Svt115884 					    YPMAXDOMAIN) {
3430Sstevel@tonic-gate 						fprintf(stderr,
344*7035Svt115884 						    err_bad_args,
345*7035Svt115884 						    err_bad_domainname);
3460Sstevel@tonic-gate 						exit(1);
3470Sstevel@tonic-gate 					}
3480Sstevel@tonic-gate 				} else {
3490Sstevel@tonic-gate 					fprintf(stderr, pusage);
3500Sstevel@tonic-gate 					exit(1);
3510Sstevel@tonic-gate 				}
3520Sstevel@tonic-gate 				break;
3530Sstevel@tonic-gate 			case 'h':
3540Sstevel@tonic-gate 				if (argc > 1) {
3550Sstevel@tonic-gate 					onehost = TRUE;
3560Sstevel@tonic-gate 					argv++;
3570Sstevel@tonic-gate 					argc--;
3580Sstevel@tonic-gate 					host = *argv;
3590Sstevel@tonic-gate 					argv++;
3600Sstevel@tonic-gate 				} else {
3610Sstevel@tonic-gate 					fprintf(stderr, pusage);
3620Sstevel@tonic-gate 					exit(1);
3630Sstevel@tonic-gate 				}
3640Sstevel@tonic-gate 				break;
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate 			case 'p':
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 				if (argc > 1) {
3690Sstevel@tonic-gate 					argv++;
3700Sstevel@tonic-gate 					argc--;
3710Sstevel@tonic-gate 					if (sscanf(*argv, "%d", &curpar) != 1) {
3720Sstevel@tonic-gate 						(void) fprintf(stderr, pusage);
3730Sstevel@tonic-gate 						exit(1);
3740Sstevel@tonic-gate 					}
3750Sstevel@tonic-gate 					argv++;
3760Sstevel@tonic-gate 					if (curpar < 1) {
3770Sstevel@tonic-gate 						(void) fprintf(stderr, pusage);
3780Sstevel@tonic-gate 						exit(1);
3790Sstevel@tonic-gate 					}
3800Sstevel@tonic-gate 				} else {
3810Sstevel@tonic-gate 					(void) fprintf(stderr, pusage);
3820Sstevel@tonic-gate 					exit(1);
3830Sstevel@tonic-gate 				}
3840Sstevel@tonic-gate 				break;
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 			default:
3870Sstevel@tonic-gate 				fprintf(stderr, pusage);
3880Sstevel@tonic-gate 				exit(1);
3890Sstevel@tonic-gate 			}
3900Sstevel@tonic-gate 		} else {
3910Sstevel@tonic-gate 			if (!map) {
3920Sstevel@tonic-gate 				map = *argv;
3930Sstevel@tonic-gate 			} else {
3940Sstevel@tonic-gate 				fprintf(stderr, pusage);
3950Sstevel@tonic-gate 				exit(1);
3960Sstevel@tonic-gate 			}
3970Sstevel@tonic-gate 			argv++;
3980Sstevel@tonic-gate 		}
3990Sstevel@tonic-gate 	}
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 	if (!map) {
4020Sstevel@tonic-gate 		fprintf(stderr, pusage);
4030Sstevel@tonic-gate 		exit(1);
4040Sstevel@tonic-gate 	}
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate /*
4080Sstevel@tonic-gate  *  This gets the local kernel domainname, and sets the global domain to it.
4090Sstevel@tonic-gate  */
4100Sstevel@tonic-gate static void
get_default_domain_name(void)4110Sstevel@tonic-gate get_default_domain_name(void)
4120Sstevel@tonic-gate {
4130Sstevel@tonic-gate 	if (!getdomainname(default_domain_name, YPMAXDOMAIN)) {
4140Sstevel@tonic-gate 		domain = default_domain_name;
4150Sstevel@tonic-gate 	} else {
4160Sstevel@tonic-gate 		fprintf(stderr, err_cant_get_kname, err_bad_domainname);
4170Sstevel@tonic-gate 		exit(1);
4180Sstevel@tonic-gate 	}
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 	if ((int)strlen(domain) == 0) {
4210Sstevel@tonic-gate 		fprintf(stderr, err_null_kname, err_bad_domainname);
4220Sstevel@tonic-gate 		exit(1);
4230Sstevel@tonic-gate 	}
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate /*
4270Sstevel@tonic-gate  * This verifies that the hostname supplied by the user is in the map
4280Sstevel@tonic-gate  * "ypservers" then calls add_server to make it the only entry on the
4290Sstevel@tonic-gate  * list of servers.
4300Sstevel@tonic-gate  */
4310Sstevel@tonic-gate static void
one_host_list(void)4320Sstevel@tonic-gate one_host_list(void)
4330Sstevel@tonic-gate {
4340Sstevel@tonic-gate 	char *key;
4350Sstevel@tonic-gate 	int keylen;
4360Sstevel@tonic-gate 	char *val;
4370Sstevel@tonic-gate 	int vallen;
4380Sstevel@tonic-gate 	int err;
4390Sstevel@tonic-gate 	char *ypservers = "ypservers";
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate 	if (verbose) {
4420Sstevel@tonic-gate 		printf("Verifying YP server: %s\n", host);
4430Sstevel@tonic-gate 		fflush(stdout);
4440Sstevel@tonic-gate 	}
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate 	if (err = yp_bind(domain_alias)) {
4470Sstevel@tonic-gate 		fprintf(stderr, err_cant_bind, domain, yperr_string(err));
4480Sstevel@tonic-gate 		exit(1);
4490Sstevel@tonic-gate 	}
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 	keylen = strlen(host);
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate 	if (yp_match(domain_alias, ypservers, host, keylen,
454*7035Svt115884 	    &val, &vallen)) {
4550Sstevel@tonic-gate 		fprintf(stderr, err_cant_find_host, host);
4560Sstevel@tonic-gate 		exit(1);
4570Sstevel@tonic-gate 	}
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate 	add_server(host, keylen);
4600Sstevel@tonic-gate }
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate /*
4630Sstevel@tonic-gate  * This uses yp operations to retrieve each server name in the map
4640Sstevel@tonic-gate  *  "ypservers".  add_server is called for each one to add it to the list of
4650Sstevel@tonic-gate  *  servers.
4660Sstevel@tonic-gate  */
4670Sstevel@tonic-gate static void
make_server_list(void)4680Sstevel@tonic-gate make_server_list(void)
4690Sstevel@tonic-gate {
4700Sstevel@tonic-gate 	char *key;
4710Sstevel@tonic-gate 	int keylen;
4720Sstevel@tonic-gate 	char *outkey;
4730Sstevel@tonic-gate 	int outkeylen;
4740Sstevel@tonic-gate 	char *val;
4750Sstevel@tonic-gate 	int vallen;
4760Sstevel@tonic-gate 	int err;
4770Sstevel@tonic-gate 	char *ypservers = "ypservers";
4780Sstevel@tonic-gate 	int count;
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate 	if (verbose) {
4810Sstevel@tonic-gate 		printf("Finding YP servers: ");
4820Sstevel@tonic-gate 		fflush(stdout);
4830Sstevel@tonic-gate 		count = 4;
4840Sstevel@tonic-gate 	}
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 	if (err = yp_bind(domain_alias)) {
4870Sstevel@tonic-gate 		fprintf(stderr, err_cant_bind, domain, yperr_string(err));
4880Sstevel@tonic-gate 		exit(1);
4890Sstevel@tonic-gate 	}
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 	if (err = yp_first(domain_alias, ypservers, &outkey, &outkeylen,
492*7035Svt115884 	    &val, &vallen)) {
4930Sstevel@tonic-gate 		fprintf(stderr, err_cant_build_serverlist, yperr_string(err));
4940Sstevel@tonic-gate 		exit(1);
4950Sstevel@tonic-gate 	}
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 	for (;;) {
4980Sstevel@tonic-gate 		add_server(outkey, outkeylen);
4990Sstevel@tonic-gate 		if (verbose) {
5000Sstevel@tonic-gate 			printf(" %s", outkey);
5010Sstevel@tonic-gate 			fflush(stdout);
5020Sstevel@tonic-gate 			if (count++ == 8) {
5030Sstevel@tonic-gate 				printf("\n");
5040Sstevel@tonic-gate 				count = 0;
5050Sstevel@tonic-gate 			}
5060Sstevel@tonic-gate 		}
5070Sstevel@tonic-gate 		free(val);
5080Sstevel@tonic-gate 		key = outkey;
5090Sstevel@tonic-gate 		keylen = outkeylen;
5100Sstevel@tonic-gate 
5110Sstevel@tonic-gate 		if (err = yp_next(domain_alias, ypservers, key, keylen,
512*7035Svt115884 		    &outkey, &outkeylen, &val, &vallen)) {
5130Sstevel@tonic-gate 
514*7035Svt115884 			if (err == YPERR_NOMORE) {
515*7035Svt115884 				break;
516*7035Svt115884 			} else {
517*7035Svt115884 				fprintf(stderr, err_cant_build_serverlist,
518*7035Svt115884 				    yperr_string(err));
519*7035Svt115884 				exit(1);
520*7035Svt115884 			}
5210Sstevel@tonic-gate 		}
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 		free(key);
5240Sstevel@tonic-gate 	}
5250Sstevel@tonic-gate 	if (count != 0) {
5260Sstevel@tonic-gate 		if (verbose)
5270Sstevel@tonic-gate 			printf("\n");
5280Sstevel@tonic-gate 	}
5290Sstevel@tonic-gate }
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate /*
5320Sstevel@tonic-gate  *  This adds a single server to the server list.
5330Sstevel@tonic-gate  */
5340Sstevel@tonic-gate static void
add_server(char * sname,int namelen)5350Sstevel@tonic-gate add_server(char *sname, int namelen)
5360Sstevel@tonic-gate {
5370Sstevel@tonic-gate 	struct server *ps;
5380Sstevel@tonic-gate 	static unsigned long seq;
5390Sstevel@tonic-gate 	static unsigned long xactid = 0;
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 	if (strcmp(sname, my_name) == 0)
5420Sstevel@tonic-gate 		return;
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate 	if (xactid == 0) {
5450Sstevel@tonic-gate 		xactid_seed(&xactid);
5460Sstevel@tonic-gate 	}
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate 	if ((ps = (struct server *)malloc((unsigned)sizeof (struct server)))
5490Sstevel@tonic-gate 		== (struct server *)NULL) {
5500Sstevel@tonic-gate 		perror("yppush: malloc failure");
5510Sstevel@tonic-gate 		exit(1);
5520Sstevel@tonic-gate 	}
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 	sname[namelen] = '\0';
5550Sstevel@tonic-gate 	strcpy(ps->svc_name, sname);
5560Sstevel@tonic-gate 	ps->state = SSTAT_INIT;
5570Sstevel@tonic-gate 	ps->status = 0;
5580Sstevel@tonic-gate 	ps->oldvers = FALSE;
5590Sstevel@tonic-gate 	ps->xactid = xactid + seq++;
5600Sstevel@tonic-gate 	ps->pnext = server_list;
5610Sstevel@tonic-gate 	server_list = ps;
5620Sstevel@tonic-gate }
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate /*
5650Sstevel@tonic-gate  * This sets the base range for the transaction ids used in speaking the the
5660Sstevel@tonic-gate  *  server ypxfr processes.
5670Sstevel@tonic-gate  */
5680Sstevel@tonic-gate static void
xactid_seed(unsigned long * xactid)5690Sstevel@tonic-gate xactid_seed(unsigned long *xactid)
5700Sstevel@tonic-gate {
5710Sstevel@tonic-gate 	struct timeval t;
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate 	if (gettimeofday(&t) == -1) {
5740Sstevel@tonic-gate 		perror("yppush gettimeofday failure");
5750Sstevel@tonic-gate 		*xactid = 1234567;
5760Sstevel@tonic-gate 	} else {
5770Sstevel@tonic-gate 		*xactid = t.tv_sec;
5780Sstevel@tonic-gate 	}
5790Sstevel@tonic-gate }
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate /*
5820Sstevel@tonic-gate  *  This generates the channel which will be used as the listener process'
5830Sstevel@tonic-gate  *  service rendezvous point, and comes up with a transient program number
5840Sstevel@tonic-gate  *  for the use of the RPC messages from the ypxfr processes.
5850Sstevel@tonic-gate  */
5860Sstevel@tonic-gate static int
generate_callback(unsigned long * program)5870Sstevel@tonic-gate generate_callback(unsigned long *program)
5880Sstevel@tonic-gate {
5890Sstevel@tonic-gate 	unsigned long prognum = 0x40000000, maxprognum;
5900Sstevel@tonic-gate 	union {
5910Sstevel@tonic-gate 		unsigned long	p;
5920Sstevel@tonic-gate 		unsigned char	b[sizeof (unsigned long)];
5930Sstevel@tonic-gate 	} u;
5940Sstevel@tonic-gate 	int ret, i;
5950Sstevel@tonic-gate 	struct netconfig *nc4, *nc6, *nc;
5960Sstevel@tonic-gate 	SVCXPRT *trans;
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate 	nc4 = getnetconfigent("udp");
5990Sstevel@tonic-gate 	nc6 = getnetconfigent("udp6");
6000Sstevel@tonic-gate 	if (nc4 == 0 && nc6 == 0) {
6010Sstevel@tonic-gate 		fprintf(stderr,
602*7035Svt115884 		    "yppush: Could not get udp or udp6 netconfig entry\n");
6030Sstevel@tonic-gate 		exit(1);
6040Sstevel@tonic-gate 	}
6050Sstevel@tonic-gate 
6060Sstevel@tonic-gate 	transport4 = (nc4 == 0) ? 0 : svc_tli_create(RPC_ANYFD, nc4, 0, 0, 0);
6070Sstevel@tonic-gate 	transport6 = (nc6 == 0) ? 0 : svc_tli_create(RPC_ANYFD, nc6, 0, 0, 0);
6080Sstevel@tonic-gate 	if (transport4 == 0 && transport6 == 0) {
6090Sstevel@tonic-gate 		fprintf(stderr, "yppush: Could not create server handle(s)\n");
6100Sstevel@tonic-gate 		exit(1);
6110Sstevel@tonic-gate 	}
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate 	/* Find the maximum possible program number using an unsigned long */
6140Sstevel@tonic-gate 	for (i = 0; i < sizeof (u.b); i++)
6150Sstevel@tonic-gate 		u.b[i] = 0xff;
6160Sstevel@tonic-gate 	maxprognum = u.p;
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate 	if (transport4 != 0) {
6190Sstevel@tonic-gate 		trans = transport4;
6200Sstevel@tonic-gate 		nc = nc4;
6210Sstevel@tonic-gate 	} else {
6220Sstevel@tonic-gate 		trans = transport6;
6230Sstevel@tonic-gate 		nc = nc6;
6240Sstevel@tonic-gate 	}
6250Sstevel@tonic-gate 	while (prognum < maxprognum && (ret =
626*7035Svt115884 	    rpcb_set(prognum, YPPUSHVERS, nc, &trans->xp_ltaddr)) == 0)
6270Sstevel@tonic-gate 		prognum++;
6280Sstevel@tonic-gate 
6290Sstevel@tonic-gate 	if (ret == 0) {
6300Sstevel@tonic-gate 		fprintf(stderr, "yppush: Could not create callback service\n");
6310Sstevel@tonic-gate 		exit(1);
6320Sstevel@tonic-gate 	} else {
6330Sstevel@tonic-gate 		if (trans == transport4 && transport6 != 0) {
6340Sstevel@tonic-gate 			ret = rpcb_set(prognum, YPPUSHVERS, nc6,
635*7035Svt115884 			    &transport6->xp_ltaddr);
6360Sstevel@tonic-gate 			if (ret == 0) {
6370Sstevel@tonic-gate 				fprintf(stderr,
6380Sstevel@tonic-gate 			"yppush: Could not create udp6 callback service\n");
6390Sstevel@tonic-gate 				exit(1);
6400Sstevel@tonic-gate 			}
6410Sstevel@tonic-gate 		}
6420Sstevel@tonic-gate 		*program = prognum;
6430Sstevel@tonic-gate 	}
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate 	return (ret);
6460Sstevel@tonic-gate }
6470Sstevel@tonic-gate 
6480Sstevel@tonic-gate /*
6490Sstevel@tonic-gate  * This is the main loop. Send messages to each server,
6500Sstevel@tonic-gate  * and then wait for a response.
6510Sstevel@tonic-gate  */
6520Sstevel@tonic-gate 
6530Sstevel@tonic-gate 
654702Sth160488 int
add_to_active()6550Sstevel@tonic-gate add_to_active()
6560Sstevel@tonic-gate {
6570Sstevel@tonic-gate 	struct server  *ps;
6580Sstevel@tonic-gate 	ps = server_list;
6590Sstevel@tonic-gate 	if (ps == NULL)
6600Sstevel@tonic-gate 		return (0);
6610Sstevel@tonic-gate 	server_list = server_list->pnext;	/* delete from server_list */
6620Sstevel@tonic-gate 	ps->pnext = active_list;
6630Sstevel@tonic-gate 	active_list = ps;
6640Sstevel@tonic-gate 	return (1);
6650Sstevel@tonic-gate }
6660Sstevel@tonic-gate 
667702Sth160488 int
delete_active(in)6680Sstevel@tonic-gate delete_active(in)
6690Sstevel@tonic-gate 	struct server  *in;
6700Sstevel@tonic-gate {
6710Sstevel@tonic-gate 	struct server  *p;
6720Sstevel@tonic-gate 	struct server  *n;
6730Sstevel@tonic-gate 	if (in == active_list) {
6740Sstevel@tonic-gate 		active_list = active_list->pnext;
6750Sstevel@tonic-gate 		return (1);
6760Sstevel@tonic-gate 	}
6770Sstevel@tonic-gate 	p = active_list;
6780Sstevel@tonic-gate 	for (n = active_list; n; n = n->pnext) {
6790Sstevel@tonic-gate 		if (in == n) {
6800Sstevel@tonic-gate 			p->pnext = n->pnext;
6810Sstevel@tonic-gate 			return (0);
6820Sstevel@tonic-gate 
6830Sstevel@tonic-gate 		}
6840Sstevel@tonic-gate 		p = n;
6850Sstevel@tonic-gate 	}
6860Sstevel@tonic-gate 	return (-1);
6870Sstevel@tonic-gate }
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate void
main_loop(program)6900Sstevel@tonic-gate main_loop(program)
6910Sstevel@tonic-gate 	unsigned long   program;
6920Sstevel@tonic-gate {
6930Sstevel@tonic-gate 	pollfd_t	*pollset = NULL;
6940Sstevel@tonic-gate 	int		npollfds = 0;
6950Sstevel@tonic-gate 	int		pollret;
6960Sstevel@tonic-gate 	struct server	*ps;
6970Sstevel@tonic-gate 	long		error;
6980Sstevel@tonic-gate 	int		hpar;	/* this times par count */
6990Sstevel@tonic-gate 	int		i;
7000Sstevel@tonic-gate 	int		j;
7010Sstevel@tonic-gate 	int		time_now;
7020Sstevel@tonic-gate 	int		docb;
7030Sstevel@tonic-gate 	int		actives = 0;
7040Sstevel@tonic-gate 	int		dead = 0;
7050Sstevel@tonic-gate 
7060Sstevel@tonic-gate 	if (grace_period < MIN_GRACE)
7070Sstevel@tonic-gate 		grace_period = MIN_GRACE;
7080Sstevel@tonic-gate 	if (transport4 != 0) {
7090Sstevel@tonic-gate 		if (!svc_reg(transport4, program, YPPUSHVERS,
7100Sstevel@tonic-gate 				listener_dispatch, 0)) {
7110Sstevel@tonic-gate 			fprintf(stderr,
7120Sstevel@tonic-gate 			"Can't set up transient udp callback server.\n");
7130Sstevel@tonic-gate 		}
7140Sstevel@tonic-gate 	}
7150Sstevel@tonic-gate 	if (transport6 != 0) {
7160Sstevel@tonic-gate 		if (!svc_reg(transport6, program, YPPUSHVERS,
7170Sstevel@tonic-gate 				listener_dispatch, 0)) {
7180Sstevel@tonic-gate 			fprintf(stderr,
7190Sstevel@tonic-gate 			"Can't set up transient udp6 callback server.\n");
7200Sstevel@tonic-gate 		}
7210Sstevel@tonic-gate 	}
7220Sstevel@tonic-gate 	for (;;) {
7230Sstevel@tonic-gate 		time_now = time(0);
7240Sstevel@tonic-gate 		if (server_list == NULL) {
7250Sstevel@tonic-gate 			actives = 0;
7260Sstevel@tonic-gate 			dead = 0;
7270Sstevel@tonic-gate 			for (ps = active_list; ps; ps = ps->pnext)
7280Sstevel@tonic-gate 				if (ps->state == SSTAT_CALLED) {
7290Sstevel@tonic-gate 					if ((time_now - ps->start_time) <
7300Sstevel@tonic-gate 								grace_period)
7310Sstevel@tonic-gate 						actives++;
7320Sstevel@tonic-gate 					else
7330Sstevel@tonic-gate 						dead++;
7340Sstevel@tonic-gate 				}
7350Sstevel@tonic-gate 			if (actives == 0) {
7360Sstevel@tonic-gate 				if (verbose) {
7370Sstevel@tonic-gate 					printf("terminating %d dead\n", dead);
7380Sstevel@tonic-gate 					fflush(stdout);
7390Sstevel@tonic-gate 				}
7400Sstevel@tonic-gate 
7410Sstevel@tonic-gate 				for (ps = active_list; ps; ps = ps->pnext)
7420Sstevel@tonic-gate 					if (ps->state == SSTAT_CALLED) {
7430Sstevel@tonic-gate 						if ((time_now - ps->start_time)
7440Sstevel@tonic-gate 							>= grace_period) {
7450Sstevel@tonic-gate 							if (verbose) {
7460Sstevel@tonic-gate 								printf(
7470Sstevel@tonic-gate 		    "no response from %s -- grace of %d seconds expired.\n",
7480Sstevel@tonic-gate 		    ps->svc_name, grace_period);
7490Sstevel@tonic-gate 								fflush(stdout);
7500Sstevel@tonic-gate 							}
7510Sstevel@tonic-gate 							fprintf(stderr,
7520Sstevel@tonic-gate 		    "No response from ypxfr on %s\n", ps->svc_name);
7530Sstevel@tonic-gate 						}
7540Sstevel@tonic-gate 					}
7550Sstevel@tonic-gate 				break;
7560Sstevel@tonic-gate 			}
7570Sstevel@tonic-gate 		}
7580Sstevel@tonic-gate 		actives = 0;
7590Sstevel@tonic-gate 		for (ps = active_list; ps; ps = ps->pnext) {
7600Sstevel@tonic-gate 			if (ps->state == SSTAT_CALLED) {
7610Sstevel@tonic-gate 				if ((time_now - ps->start_time)
7620Sstevel@tonic-gate 						< grace_period) {
7630Sstevel@tonic-gate 					actives++;
7640Sstevel@tonic-gate 
7650Sstevel@tonic-gate 					if (verbose) {
7660Sstevel@tonic-gate 						printf(
7670Sstevel@tonic-gate 		    "No response yet from ypxfr on %s\n", ps->svc_name);
7680Sstevel@tonic-gate 						fflush(stdout);
7690Sstevel@tonic-gate 					}
7700Sstevel@tonic-gate 				}
7710Sstevel@tonic-gate 			} else {
7720Sstevel@tonic-gate 				if (verbose) {
7730Sstevel@tonic-gate 					printf("Deactivating  %s\n",
7740Sstevel@tonic-gate 						ps->svc_name);
7750Sstevel@tonic-gate 					fflush(stdout);
7760Sstevel@tonic-gate 				}
7770Sstevel@tonic-gate 				delete_active(ps);
7780Sstevel@tonic-gate 			}
7790Sstevel@tonic-gate 		}
7800Sstevel@tonic-gate 
7810Sstevel@tonic-gate 		/* add someone to the active list keep up with curpar */
7820Sstevel@tonic-gate 		for (i = 0; i < (curpar - actives); i++) {
7830Sstevel@tonic-gate 			if (add_to_active()) {
7840Sstevel@tonic-gate 				ps = active_list;
7850Sstevel@tonic-gate 				ps->state = send_message(ps, program, &error);
7860Sstevel@tonic-gate 				print_state_msg(ps, error);
7870Sstevel@tonic-gate 				if (ps->state != SSTAT_CALLED)
7880Sstevel@tonic-gate 					delete_active(ps);	/* zorch it */
7890Sstevel@tonic-gate 				else
7900Sstevel@tonic-gate 					ps->start_time = time(0); /* set time */
7910Sstevel@tonic-gate 			}
7920Sstevel@tonic-gate 		}
7930Sstevel@tonic-gate 		docb = 0;
7940Sstevel@tonic-gate 		for (ps = active_list; ps; ps = ps->pnext)
7950Sstevel@tonic-gate 			if (ps->state == SSTAT_CALLED) {
7960Sstevel@tonic-gate 				docb = 1;
7970Sstevel@tonic-gate 				break;
7980Sstevel@tonic-gate 			}
7990Sstevel@tonic-gate 		if (docb == 0) {
8000Sstevel@tonic-gate 			if (verbose) {
8010Sstevel@tonic-gate 				printf("No one to wait for this pass.\n");
8020Sstevel@tonic-gate 				fflush(stdout);
8030Sstevel@tonic-gate 			}
8040Sstevel@tonic-gate 			continue;	/* try curpar more */
8050Sstevel@tonic-gate 		}
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate 		if (npollfds != svc_max_pollfd) {
8080Sstevel@tonic-gate 			pollset = realloc(pollset,
8090Sstevel@tonic-gate 					sizeof (pollfd_t) * svc_max_pollfd);
8100Sstevel@tonic-gate 			npollfds = svc_max_pollfd;
8110Sstevel@tonic-gate 		}
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate 		/*
8140Sstevel@tonic-gate 		 * Get existing array of pollfd's, should really compress
8150Sstevel@tonic-gate 		 * this but it shouldn't get very large (or sparse).
8160Sstevel@tonic-gate 		 */
8170Sstevel@tonic-gate 		(void) memcpy(pollset, svc_pollfd,
8180Sstevel@tonic-gate 					sizeof (pollfd_t) * svc_max_pollfd);
8190Sstevel@tonic-gate 
8200Sstevel@tonic-gate 		errno = 0;
8210Sstevel@tonic-gate 		switch (pollret = poll(pollset, npollfds, MIN_GRACE * 1000)) {
8220Sstevel@tonic-gate 		    case -1:
8230Sstevel@tonic-gate 			if (errno != EINTR) {
8240Sstevel@tonic-gate 				(void) perror("main loop select");
8250Sstevel@tonic-gate 			}
8260Sstevel@tonic-gate 			break;
8270Sstevel@tonic-gate 
8280Sstevel@tonic-gate 		    case 0:
8290Sstevel@tonic-gate 			if (verbose) {
8300Sstevel@tonic-gate 				(void) printf("timeout in main loop select.\n");
8310Sstevel@tonic-gate 				fflush(stdout);
8320Sstevel@tonic-gate 			}
8330Sstevel@tonic-gate 			break;
8340Sstevel@tonic-gate 
8350Sstevel@tonic-gate 		    default:
8360Sstevel@tonic-gate 			svc_getreq_poll(pollset, pollret);
8370Sstevel@tonic-gate 			break;
8380Sstevel@tonic-gate 		}		/* switch */
8390Sstevel@tonic-gate 	}			/* for */
8400Sstevel@tonic-gate }
8410Sstevel@tonic-gate 
8420Sstevel@tonic-gate /*
8430Sstevel@tonic-gate  * This does the listener process cleanup and process exit.
8440Sstevel@tonic-gate  */
8450Sstevel@tonic-gate static void
listener_exit(unsigned long program,int stat)8460Sstevel@tonic-gate listener_exit(unsigned long program, int stat)
8470Sstevel@tonic-gate {
8480Sstevel@tonic-gate 	svc_unreg(program, YPPUSHVERS);
8490Sstevel@tonic-gate 	exit(stat);
8500Sstevel@tonic-gate }
8510Sstevel@tonic-gate 
8520Sstevel@tonic-gate /*
8530Sstevel@tonic-gate  * This is the listener process' RPC service dispatcher.
8540Sstevel@tonic-gate  */
8550Sstevel@tonic-gate static void
listener_dispatch(struct svc_req * rqstp,SVCXPRT * transp)8560Sstevel@tonic-gate listener_dispatch(struct svc_req *rqstp, SVCXPRT *transp)
8570Sstevel@tonic-gate {
8580Sstevel@tonic-gate 	switch (rqstp->rq_proc) {
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate 	case YPPUSHPROC_NULL:
8610Sstevel@tonic-gate 		if (!svc_sendreply(transp, xdr_void, 0)) {
862*7035Svt115884 			fprintf(stderr, "Can't reply to rpc call.\n");
8630Sstevel@tonic-gate 		}
8640Sstevel@tonic-gate 		break;
8650Sstevel@tonic-gate 
8660Sstevel@tonic-gate 	case YPPUSHPROC_XFRRESP:
8670Sstevel@tonic-gate 		get_xfr_response(transp);
8680Sstevel@tonic-gate 		break;
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate 	default:
8710Sstevel@tonic-gate 		svcerr_noproc(transp);
8720Sstevel@tonic-gate 		break;
8730Sstevel@tonic-gate 	}
8740Sstevel@tonic-gate }
8750Sstevel@tonic-gate 
8760Sstevel@tonic-gate 
8770Sstevel@tonic-gate /*
8780Sstevel@tonic-gate  *  This dumps a server state message to stdout.  It is called in cases where
8790Sstevel@tonic-gate  *  we have no expectation of receiving a callback from the remote ypxfr.
8800Sstevel@tonic-gate  */
8810Sstevel@tonic-gate static void
print_state_msg(struct server * s,long e)8820Sstevel@tonic-gate print_state_msg(struct server *s, long e)
8830Sstevel@tonic-gate {
8840Sstevel@tonic-gate 	struct state_duple *sd;
8850Sstevel@tonic-gate 
8860Sstevel@tonic-gate 	if (s->state == SSTAT_SYSTEM)
8870Sstevel@tonic-gate 		return;			/* already printed */
8880Sstevel@tonic-gate 
8890Sstevel@tonic-gate 	if (!verbose && (s->state == SSTAT_RESPONDED ||
890*7035Svt115884 	    s->state == SSTAT_CALLED))
8910Sstevel@tonic-gate 		return;
8920Sstevel@tonic-gate 
8930Sstevel@tonic-gate 	for (sd = state_duples; sd->state_msg; sd++) {
8940Sstevel@tonic-gate 		if (sd->state == s->state) {
8950Sstevel@tonic-gate 			printf(sd->state_msg, s->svc_name);
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate 			if (s->state == SSTAT_RPC) {
8980Sstevel@tonic-gate 				rpcerr_msg((enum clnt_stat) e);
8990Sstevel@tonic-gate 			}
9000Sstevel@tonic-gate 
9010Sstevel@tonic-gate 			printf("\n");
9020Sstevel@tonic-gate 			fflush(stdout);
9030Sstevel@tonic-gate 			return;
9040Sstevel@tonic-gate 		}
9050Sstevel@tonic-gate 	}
9060Sstevel@tonic-gate 
9070Sstevel@tonic-gate 	fprintf(stderr, "yppush: Bad server state value %d.\n", s->state);
9080Sstevel@tonic-gate }
9090Sstevel@tonic-gate 
9100Sstevel@tonic-gate /*
9110Sstevel@tonic-gate  *  This dumps a transfer status message to stdout.  It is called in
9120Sstevel@tonic-gate  *  response to a received RPC message from the called ypxfr.
9130Sstevel@tonic-gate  */
9140Sstevel@tonic-gate static void
print_callback_msg(struct server * s)9150Sstevel@tonic-gate print_callback_msg(struct server *s)
9160Sstevel@tonic-gate {
9170Sstevel@tonic-gate 	register struct status_duple *sd;
9180Sstevel@tonic-gate 
9190Sstevel@tonic-gate 	if (!verbose &&
920*7035Svt115884 	    (s->status == YPPUSH_AGE) ||
921*7035Svt115884 	    (s->status == YPPUSH_SUCC))
9220Sstevel@tonic-gate 
9230Sstevel@tonic-gate 		return;
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate 	for (sd = status_duples; sd->status_msg; sd++) {
9260Sstevel@tonic-gate 
9270Sstevel@tonic-gate 		if (sd->status == s->status) {
9280Sstevel@tonic-gate 			printf("Status received from ypxfr on %s:\n\t%s\n",
929*7035Svt115884 			    s->svc_name, sd->status_msg);
9300Sstevel@tonic-gate 			fflush(stdout);
9310Sstevel@tonic-gate 			return;
9320Sstevel@tonic-gate 		}
9330Sstevel@tonic-gate 	}
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 	fprintf(stderr, "yppush listener: Garbage transaction "
936*7035Svt115884 	    "status (value %d) from ypxfr on %s.\n",
937*7035Svt115884 	    (int)s->status, s->svc_name);
9380Sstevel@tonic-gate }
9390Sstevel@tonic-gate 
9400Sstevel@tonic-gate /*
9410Sstevel@tonic-gate  *  This dumps an RPC error message to stdout.  This is basically a rewrite
9420Sstevel@tonic-gate  *  of clnt_perrno, but writes to stdout instead of stderr.
9430Sstevel@tonic-gate  */
9440Sstevel@tonic-gate static void
rpcerr_msg(enum clnt_stat e)9450Sstevel@tonic-gate rpcerr_msg(enum clnt_stat e)
9460Sstevel@tonic-gate {
9470Sstevel@tonic-gate 	struct rpcerr_duple *rd;
9480Sstevel@tonic-gate 
9490Sstevel@tonic-gate 	for (rd = rpcerr_duples; rd->rpc_msg; rd++) {
9500Sstevel@tonic-gate 
9510Sstevel@tonic-gate 		if (rd->rpc_stat == e) {
9520Sstevel@tonic-gate 			printf(rd->rpc_msg);
9530Sstevel@tonic-gate 			return;
9540Sstevel@tonic-gate 		}
9550Sstevel@tonic-gate 	}
9560Sstevel@tonic-gate 
9570Sstevel@tonic-gate 	fprintf(stderr, "Bad error code passed to rpcerr_msg: %d.\n", e);
9580Sstevel@tonic-gate }
9590Sstevel@tonic-gate 
9600Sstevel@tonic-gate /*
9610Sstevel@tonic-gate  * This picks up the response from the ypxfr process which has been started
9620Sstevel@tonic-gate  * up on the remote node.  The response status must be non-zero, otherwise
9630Sstevel@tonic-gate  * the status will be set to "ypxfr error".
9640Sstevel@tonic-gate  */
9650Sstevel@tonic-gate static void
get_xfr_response(SVCXPRT * transp)9660Sstevel@tonic-gate get_xfr_response(SVCXPRT *transp)
9670Sstevel@tonic-gate {
9680Sstevel@tonic-gate 	struct yppushresp_xfr resp;
9690Sstevel@tonic-gate 	register struct server *s;
9700Sstevel@tonic-gate 
9710Sstevel@tonic-gate 	if (!svc_getargs(transp, (xdrproc_t)xdr_yppushresp_xfr,
972*7035Svt115884 	    (caddr_t)&resp)) {
9730Sstevel@tonic-gate 		svcerr_decode(transp);
9740Sstevel@tonic-gate 		return;
9750Sstevel@tonic-gate 	}
9760Sstevel@tonic-gate 
9770Sstevel@tonic-gate 	if (!svc_sendreply(transp, xdr_void, 0)) {
9780Sstevel@tonic-gate 		(void) fprintf(stderr, "Can't reply to rpc call.\n");
9790Sstevel@tonic-gate 	}
9800Sstevel@tonic-gate 
9810Sstevel@tonic-gate 	for (s = active_list; s; s = s->pnext) {
9820Sstevel@tonic-gate 
9830Sstevel@tonic-gate 		if (s->xactid == resp.transid) {
9840Sstevel@tonic-gate 			s->status  = resp.status ? resp.status: YPPUSH_XFRERR;
9850Sstevel@tonic-gate 			print_callback_msg(s);
9860Sstevel@tonic-gate 			s->state = SSTAT_RESPONDED;
9870Sstevel@tonic-gate 			return;
9880Sstevel@tonic-gate 		}
9890Sstevel@tonic-gate 	}
9900Sstevel@tonic-gate }
9910Sstevel@tonic-gate 
9920Sstevel@tonic-gate /*
9930Sstevel@tonic-gate  * This sends a message to a single ypserv process.  The return value is
9940Sstevel@tonic-gate  * a state value.  If the RPC call fails because of a version
9950Sstevel@tonic-gate  * mismatch, we'll assume that we're talking to a version 1 ypserv process,
9960Sstevel@tonic-gate  * and will send him an old "YPPROC_GET" request, as was defined in the
9970Sstevel@tonic-gate  * earlier version of yp_prot.h
9980Sstevel@tonic-gate  */
9990Sstevel@tonic-gate static unsigned short
send_message(struct server * ps,unsigned long program,long * err)10000Sstevel@tonic-gate send_message(struct server *ps, unsigned long program, long *err)
10010Sstevel@tonic-gate {
10020Sstevel@tonic-gate 	struct ypreq_newxfr req;
10030Sstevel@tonic-gate 	struct ypreq_xfr oldreq;
10040Sstevel@tonic-gate 	enum clnt_stat s;
10050Sstevel@tonic-gate 	struct rpc_err rpcerr;
10060Sstevel@tonic-gate 
10070Sstevel@tonic-gate 	if ((ps->domb.dom_client = __yp_clnt_create_rsvdport(ps->svc_name,
1008*7035Svt115884 	    YPPROG, YPVERS, (char *)NULL, 0, 0))  == NULL) {
10090Sstevel@tonic-gate 
10100Sstevel@tonic-gate 		if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED) {
10110Sstevel@tonic-gate 			return (SSTAT_PROGNOTREG);
10120Sstevel@tonic-gate 		} else {
10130Sstevel@tonic-gate 			printf("Error talking to %s: ", ps->svc_name);
10140Sstevel@tonic-gate 			rpcerr_msg(rpc_createerr.cf_stat);
10150Sstevel@tonic-gate 			printf("\n");
10160Sstevel@tonic-gate 			fflush(stdout);
10170Sstevel@tonic-gate 			return (SSTAT_SYSTEM);
10180Sstevel@tonic-gate 		}
10190Sstevel@tonic-gate 	}
10200Sstevel@tonic-gate 
10210Sstevel@tonic-gate 	if (sysinfo(SI_HOSTNAME, my_name, sizeof (my_name)) == -1) {
10220Sstevel@tonic-gate 		return (SSTAT_RSCRC);
10230Sstevel@tonic-gate 	}
10240Sstevel@tonic-gate 
10250Sstevel@tonic-gate 	if (!oldxfr) {
10260Sstevel@tonic-gate 		req.ypxfr_domain = domain;
10270Sstevel@tonic-gate 		req.ypxfr_map = map;
10280Sstevel@tonic-gate 		req.ypxfr_ordernum = 0;
10290Sstevel@tonic-gate 		req.ypxfr_owner = my_name;
10300Sstevel@tonic-gate 		req.name = ps->svc_name;
10310Sstevel@tonic-gate 		/*
10320Sstevel@tonic-gate 		 * the creation of field req.name, instead of ypreq_xfr (old)
10330Sstevel@tonic-gate 		 * req.port, does not make any sense. it doesn't give any
10340Sstevel@tonic-gate 		 * information to receiving ypserv except its own name !!
10350Sstevel@tonic-gate 		 * new ypserv duplicates work for YPPROC_XFR and YPPROC_NEWXFR
10360Sstevel@tonic-gate 		 */
10370Sstevel@tonic-gate 		req.transid = ps->xactid;
10380Sstevel@tonic-gate 		req.proto = program;
10390Sstevel@tonic-gate 		s = (enum clnt_stat) clnt_call(ps->domb.dom_client,
1040*7035Svt115884 		    YPPROC_NEWXFR, (xdrproc_t)xdr_ypreq_newxfr, (caddr_t)&req,
1041*7035Svt115884 		    xdr_void, 0, timeout);
10420Sstevel@tonic-gate 	}
10430Sstevel@tonic-gate 
10440Sstevel@tonic-gate 	clnt_geterr(ps->domb.dom_client, &rpcerr);
10450Sstevel@tonic-gate 
10460Sstevel@tonic-gate 	if (s == RPC_PROCUNAVAIL) {
10470Sstevel@tonic-gate 		oldreq.ypxfr_domain = domain;
10480Sstevel@tonic-gate 		oldreq.ypxfr_map = map;
10490Sstevel@tonic-gate 		oldreq.ypxfr_ordernum = 0;
10500Sstevel@tonic-gate 		oldreq.ypxfr_owner = my_name;
10510Sstevel@tonic-gate 		oldreq.transid = ps->xactid;
10520Sstevel@tonic-gate 		oldreq.proto = program;
10530Sstevel@tonic-gate 		oldreq.port = 0;
10540Sstevel@tonic-gate 		s = (enum clnt_stat) clnt_call(ps->domb.dom_client,
1055*7035Svt115884 		    YPPROC_XFR, (xdrproc_t)xdr_ypreq_xfr, (caddr_t)&oldreq,
1056*7035Svt115884 		    xdr_void, 0, timeout);
10570Sstevel@tonic-gate 		clnt_geterr(ps->domb.dom_client, &rpcerr);
10580Sstevel@tonic-gate 	}
10590Sstevel@tonic-gate 
10600Sstevel@tonic-gate 	clnt_destroy(ps->domb.dom_client);
10610Sstevel@tonic-gate 
10620Sstevel@tonic-gate 	if (s == RPC_SUCCESS) {
10630Sstevel@tonic-gate 		return (SSTAT_CALLED);
10640Sstevel@tonic-gate 	} else {
10650Sstevel@tonic-gate 		*err = (long)rpcerr.re_status;
10660Sstevel@tonic-gate 		return (SSTAT_RPC);
10670Sstevel@tonic-gate 	}
10680Sstevel@tonic-gate 	/*NOTREACHED*/
10690Sstevel@tonic-gate }
10700Sstevel@tonic-gate 
10710Sstevel@tonic-gate /*
10720Sstevel@tonic-gate  * FUNCTION:    is_yptol_mode();
10730Sstevel@tonic-gate  *
10740Sstevel@tonic-gate  * DESCRIPTION: Determines if we should run in N2L or traditional mode based
10750Sstevel@tonic-gate  *              on the presence of the N2L mapping file.
10760Sstevel@tonic-gate  *
10770Sstevel@tonic-gate  *		This is a copy of a function from libnisdb. If more than this
10780Sstevel@tonic-gate  *		one function become required it may be worth linking the
10790Sstevel@tonic-gate  *		entire lib.
10800Sstevel@tonic-gate  *
10810Sstevel@tonic-gate  * INPUTS:      Nothing
10820Sstevel@tonic-gate  *
10830Sstevel@tonic-gate  * OUTPUTS:     TRUE = Run in N2L mode
10840Sstevel@tonic-gate  *              FALSE = Run in traditional mode.
10850Sstevel@tonic-gate  */
10860Sstevel@tonic-gate bool_t
is_yptol_mode()10870Sstevel@tonic-gate is_yptol_mode()
10880Sstevel@tonic-gate {
10890Sstevel@tonic-gate 	struct stat filestat;
10900Sstevel@tonic-gate 
10910Sstevel@tonic-gate 	if (stat(NTOL_MAP_FILE, &filestat) != -1)
10920Sstevel@tonic-gate 		return (TRUE);
10930Sstevel@tonic-gate 
10940Sstevel@tonic-gate 	return (FALSE);
10950Sstevel@tonic-gate }
1096