17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
5b892d00vt * Common Development and Distribution License (the "License").
6b892d00vt * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate *
21b892d00vt * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
227c478bdstevel@tonic-gate * Use is subject to license terms.
237c478bdstevel@tonic-gate *
247c478bdstevel@tonic-gate * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
257c478bdstevel@tonic-gate * All Rights Reserved
267c478bdstevel@tonic-gate *
277c478bdstevel@tonic-gate * Portions of this source code were derived from Berkeley
287c478bdstevel@tonic-gate * 4.3 BSD under license from the Regents of the University of
297c478bdstevel@tonic-gate * California.
307c478bdstevel@tonic-gate */
3148bbca8Daniel Hoffman/*
3248bbca8Daniel Hoffman * Copyright (c) 2016 by Delphix. All rights reserved.
3348bbca8Daniel Hoffman */
347c478bdstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
357c478bdstevel@tonic-gate
367c478bdstevel@tonic-gate#define	_SVID_GETTOD
377c478bdstevel@tonic-gate#include	<sys/time.h>
387c478bdstevel@tonic-gateextern int gettimeofday(struct timeval *);
397c478bdstevel@tonic-gate
407c478bdstevel@tonic-gate#include	<sys/types.h>
417c478bdstevel@tonic-gate#include	<stdio.h>
427c478bdstevel@tonic-gate#include	<string.h>
437c478bdstevel@tonic-gate#include	<malloc.h>
447c478bdstevel@tonic-gate#include	<errno.h>
457c478bdstevel@tonic-gate#include	<signal.h>
467c478bdstevel@tonic-gate#include	<limits.h>
477c478bdstevel@tonic-gate#include	<stdlib.h>
487c478bdstevel@tonic-gate#include	<unistd.h>
497c478bdstevel@tonic-gate#include	<sys/types.h>
507c478bdstevel@tonic-gate#include	<sys/wait.h>
517c478bdstevel@tonic-gate#include	<sys/stat.h>
527c478bdstevel@tonic-gate#include	<ctype.h>
537c478bdstevel@tonic-gate#include	<dirent.h>
547c478bdstevel@tonic-gate#include	<rpc/rpc.h>
557c478bdstevel@tonic-gate#include	<rpc/nettype.h>
567c478bdstevel@tonic-gate#include	<rpc/rpcb_prot.h>
577c478bdstevel@tonic-gate#include	<rpc/rpcb_clnt.h>
587c478bdstevel@tonic-gate#include	<sys/systeminfo.h>
597c478bdstevel@tonic-gate#include	<sys/select.h>
607c478bdstevel@tonic-gate#include	"ypsym.h"
617c478bdstevel@tonic-gate#include	"ypdefs.h"
627c478bdstevel@tonic-gate#include	"yp_b.h"
637c478bdstevel@tonic-gate#include	"shim.h"
647c478bdstevel@tonic-gate#include	"yptol.h"
657c478bdstevel@tonic-gate
667c478bdstevel@tonic-gate
677c478bdstevel@tonic-gate#ifdef DEBUG
687c478bdstevel@tonic-gate#undef YPPROG
697c478bdstevel@tonic-gate#define	YPPROG ((ulong_t)109999)
707c478bdstevel@tonic-gate#undef YPBINDPROG
717c478bdstevel@tonic-gate#define	YPBINDPROG ((ulong_t)109998)
727c478bdstevel@tonic-gate#endif
737c478bdstevel@tonic-gate
747c478bdstevel@tonic-gate#define	INTER_TRY 12			/* Seconds between tries */
757c478bdstevel@tonic-gate#define	PORTMAP_TIME 30			/* Seconds before decide its down */
767c478bdstevel@tonic-gate#define	TIMEOUT INTER_TRY*4		/* Total time for timeout */
777c478bdstevel@tonic-gate#define	CUR_PAR 4			/* Total  parallal yppushes */
787c478bdstevel@tonic-gate#define	MIN_GRACE 25			/* select timeout and minimum grace */
797c478bdstevel@tonic-gate#define	GRACE_PERIOD 800		/* Total seconds we'll wait for	*/
807c478bdstevel@tonic-gate					/* responses from ypxfrs, yes	*/
817c478bdstevel@tonic-gate					/* virginia yp map transfers	*/
827c478bdstevel@tonic-gate					/* can take a long time, we	*/
837c478bdstevel@tonic-gate					/* only worry if the slave 	*/
847c478bdstevel@tonic-gate					/* crashes ...			*/
857c478bdstevel@tonic-gate
867c478bdstevel@tonic-gateUSE_YPDBPATH
877c478bdstevel@tonic-gatestatic char *pusage;
887c478bdstevel@tonic-gatestatic char *domain = NULL;
897c478bdstevel@tonic-gatestatic char *host = NULL;
907c478bdstevel@tonic-gatestatic char my_name[YPMAXPEER +1];
917c478bdstevel@tonic-gatestatic char default_domain_name[YPMAXDOMAIN];
927c478bdstevel@tonic-gatestatic char domain_alias[MAXNAMLEN]; 	/* nickname for domain -	*/
937c478bdstevel@tonic-gate					/*	used in sysv filesystems */
947c478bdstevel@tonic-gatestatic char map_alias[MAXNAMLEN];	/* nickname for map -		*/
957c478bdstevel@tonic-gate					/*	used in sysv filesystems */
967c478bdstevel@tonic-gatestatic char *map = NULL;
977c478bdstevel@tonic-gatestatic bool verbose = FALSE;
987c478bdstevel@tonic-gatestatic bool onehost = FALSE;
997c478bdstevel@tonic-gatestatic bool oldxfr = FALSE;
1007c478bdstevel@tonic-gatestatic bool callback_timeout = FALSE;	/* set when a callback times out */
1017c478bdstevel@tonic-gateint grace_period = GRACE_PERIOD;
1027c478bdstevel@tonic-gateint curpar = CUR_PAR;			/* should be set by other stuff */
1037c478bdstevel@tonic-gatestatic char ypmapname[1024];		/* Used to check for map's existence */
1047c478bdstevel@tonic-gate
1057c478bdstevel@tonic-gatestatic struct timeval intertry = {
1067c478bdstevel@tonic-gate	INTER_TRY,			/* Seconds */
1077c478bdstevel@tonic-gate	0				/* Microseconds */
1087c478bdstevel@tonic-gate};
1097c478bdstevel@tonic-gatestatic struct timeval timeout = {
1107c478bdstevel@tonic-gate	TIMEOUT,			/* Seconds */
1117c478bdstevel@tonic-gate	0				/* Microseconds */
1127c478bdstevel@tonic-gate};
1137c478bdstevel@tonic-gatestatic SVCXPRT *transport4;
1147c478bdstevel@tonic-gatestatic SVCXPRT *transport6;
1157c478bdstevel@tonic-gatestruct server {
1167c478bdstevel@tonic-gate	struct server *pnext;
1177c478bdstevel@tonic-gate	struct dom_binding domb;
1187c478bdstevel@tonic-gate	char svc_name[YPMAXPEER+1];
1197c478bdstevel@tonic-gate	unsigned long xactid;
1207c478bdstevel@tonic-gate	unsigned short state;
1217c478bdstevel@tonic-gate	unsigned long status;
1227c478bdstevel@tonic-gate	bool oldvers;
1237c478bdstevel@tonic-gate	int start_time;
1247c478bdstevel@tonic-gate};
1257c478bdstevel@tonic-gate#define	n_conf dom_binding->ypbind_nconf
1267c478bdstevel@tonic-gate#define	svc_addr dom_binding->ypbind_svcaddr
1277c478bdstevel@tonic-gatestatic struct server *server_list = (struct server *)NULL;
1287c478bdstevel@tonic-gatestatic struct server *active_list = (struct server *)NULL;
1297c478bdstevel@tonic-gate
1307c478bdstevel@tonic-gate/*  State values for server.state field */
1317c478bdstevel@tonic-gate
1327c478bdstevel@tonic-gate#define	SSTAT_INIT 0
1337c478bdstevel@tonic-gate#define	SSTAT_CALLED 1
1347c478bdstevel@tonic-gate#define	SSTAT_RESPONDED 2
1357c478bdstevel@tonic-gate#define	SSTAT_PROGNOTREG 3
1367c478bdstevel@tonic-gate#define	SSTAT_RPC 4
1377c478bdstevel@tonic-gate#define	SSTAT_RSCRC 5
1387c478bdstevel@tonic-gate#define	SSTAT_SYSTEM 6
1397c478bdstevel@tonic-gate
1407c478bdstevel@tonic-gatestatic char err_usage[] =
1417c478bdstevel@tonic-gate"Usage:\n\typpush [-p <par>] [-d <domainname>] [-h <hostname>] [-v] map\n";
1427c478bdstevel@tonic-gatestatic char err_bad_args[] =
1437c478bdstevel@tonic-gate	"The %s argument is bad.\n";
1447c478bdstevel@tonic-gatestatic char err_cant_get_kname[] =
1457c478bdstevel@tonic-gate	"Can't get %s from system call.\n";
1467c478bdstevel@tonic-gatestatic char err_null_kname[] =
1477c478bdstevel@tonic-gate	"The %s hasn't been set on this machine.\n";
1487c478bdstevel@tonic-gatestatic char err_bad_domainname[] = "domainname";
1497c478bdstevel@tonic-gatestatic char err_cant_bind[] =
1507c478bdstevel@tonic-gate	"Can't find a yp server for domain %s.  Reason:  %s.\n";
1517c478bdstevel@tonic-gatestatic char err_cant_build_serverlist[] =
1527c478bdstevel@tonic-gate	"Can't build server list from map \"ypservers\".  Reason:  %s.\n";
1537c478bdstevel@tonic-gatestatic char err_cant_find_host[] =
1547c478bdstevel@tonic-gate	"Can't find host %s in map \"ypservers\".\n";
1557c478bdstevel@tonic-gate/*
1567c478bdstevel@tonic-gate * State_duple table.  All messages should take 1 arg - the node name.
1577c478bdstevel@tonic-gate */
1587c478bdstevel@tonic-gatestruct state_duple {
1597c478bdstevel@tonic-gate	int state;
1607c478bdstevel@tonic-gate	char *state_msg;
1617c478bdstevel@tonic-gate};
1627c478bdstevel@tonic-gatestatic struct state_duple state_duples[] = {
1637c478bdstevel@tonic-gate	{SSTAT_INIT, "Internal error trying to talk to %s."},
1647c478bdstevel@tonic-gate	{SSTAT_CALLED, "%s has been called."},
1657c478bdstevel@tonic-gate	{SSTAT_RESPONDED, "%s (v1 ypserv) sent an old-style request."},
1667c478bdstevel@tonic-gate	{SSTAT_PROGNOTREG, "nis server not registered at %s."},
1677c478bdstevel@tonic-gate	{SSTAT_RPC, "RPC error to %s:  "},
1687c478bdstevel@tonic-gate	{SSTAT_RSCRC, "Local resource allocation failure - can't talk to %s."},
1697c478bdstevel@tonic-gate	{SSTAT_SYSTEM, "System error talking to %s:  "},
1707c478bdstevel@tonic-gate	{0, (char *)NULL}
1717c478bdstevel@tonic-gate};
1727c478bdstevel@tonic-gate/*
1737c478bdstevel@tonic-gate * Status_duple table.  No messages should require any args.
1747c478bdstevel@tonic-gate */
175a506a34thstruct status_duple {
1767c478bdstevel@tonic-gate	long status;
1777c478bdstevel@tonic-gate	char *status_msg;
1787c478bdstevel@tonic-gate};
1797c478bdstevel@tonic-gatestatic struct status_duple status_duples[] = {
1807c478bdstevel@tonic-gate	{YPPUSH_SUCC, "Map successfully transferred."},
1817c478bdstevel@tonic-gate	{YPPUSH_AGE,
1827c478bdstevel@tonic-gate	    "Transfer not done:  master's version isn't newer."},
1837c478bdstevel@tonic-gate	{YPPUSH_NOMAP, "Failed - ypxfr there can't find a server for map."},
1847c478bdstevel@tonic-gate	{YPPUSH_NODOM, "Failed - domain isn't supported."},
1857c478bdstevel@tonic-gate	{YPPUSH_RSRC, "Failed - local resource allocation failure."},
1867c478bdstevel@tonic-gate	{YPPUSH_RPC, "Failed - ypxfr had an RPC failure"},
1877c478bdstevel@tonic-gate	{YPPUSH_MADDR, "Failed - ypxfr couldn't get the map master's address."},
1887c478bdstevel@tonic-gate	{YPPUSH_YPERR, "Failed - nis server or map format error."},
1897c478bdstevel@tonic-gate	{YPPUSH_BADARGS, "Failed - args to ypxfr were bad."},
1907c478bdstevel@tonic-gate	{YPPUSH_DBM, "Failed - dbm operation on map failed."},
1917c478bdstevel@tonic-gate	{YPPUSH_FILE, "Failed - file I/O operation on map failed"},
1927c478bdstevel@tonic-gate	{YPPUSH_SKEW, "Failed - map version skew during transfer."},
1937c478bdstevel@tonic-gate	{YPPUSH_CLEAR,
1947c478bdstevel@tonic-gate		"Map successfully transferred, but ypxfr \
1957c478bdstevel@tonic-gate		couldn't send \"Clear map\" to ypserv "},
1967c478bdstevel@tonic-gate	{YPPUSH_FORCE,
1977c478bdstevel@tonic-gate	    "Failed - no local order number in map - use -f flag to ypxfr."},
1987c478bdstevel@tonic-gate	{YPPUSH_XFRERR, "Failed - ypxfr internal error."},
1997c478bdstevel@tonic-gate	{YPPUSH_REFUSED, "Failed - Transfer request refused."},
2007c478bdstevel@tonic-gate	{YPPUSH_NOALIAS,
2017c478bdstevel@tonic-gate		"Failed - System V domain/map alias not in alias file."},
2027c478bdstevel@tonic-gate	{0, (char *)NULL}
2037c478bdstevel@tonic-gate};
2047c478bdstevel@tonic-gate/*
2057c478bdstevel@tonic-gate * rpcerr_duple table
2067c478bdstevel@tonic-gate */
207a506a34thstruct rpcerr_duple {
2087c478bdstevel@tonic-gate	enum clnt_stat rpc_stat;
2097c478bdstevel@tonic-gate	char *rpc_msg;
2107c478bdstevel@tonic-gate};
2117c478bdstevel@tonic-gatestatic struct rpcerr_duple rpcerr_duples[] = {
2127c478bdstevel@tonic-gate	{RPC_SUCCESS, "RPC success"},
2137c478bdstevel@tonic-gate	{RPC_CANTENCODEARGS, "RPC Can't encode args"},
2147c478bdstevel@tonic-gate	{RPC_CANTDECODERES, "RPC Can't decode results"},
2157c478bdstevel@tonic-gate	{RPC_CANTSEND, "RPC Can't send"},
2167c478bdstevel@tonic-gate	{RPC_CANTRECV, "RPC Can't recv"},
2177c478bdstevel@tonic-gate	{RPC_TIMEDOUT, "NIS server registered, but does not respond"},
2187c478bdstevel@tonic-gate	{RPC_VERSMISMATCH, "RPC version mismatch"},
2197c478bdstevel@tonic-gate	{RPC_AUTHERROR, "RPC auth error"},
2207c478bdstevel@tonic-gate	{RPC_PROGUNAVAIL, "RPC remote program unavailable"},
2217c478bdstevel@tonic-gate	{RPC_PROGVERSMISMATCH, "RPC program mismatch"},
2227c478bdstevel@tonic-gate	{RPC_PROCUNAVAIL, "RPC unknown procedure"},
2237c478bdstevel@tonic-gate	{RPC_CANTDECODEARGS, "RPC Can't decode args"},
2247c478bdstevel@tonic-gate	{RPC_UNKNOWNHOST, "unknown host"},
2257c478bdstevel@tonic-gate	{RPC_RPCBFAILURE, "rpcbind failure (host is down?)"},
2267c478bdstevel@tonic-gate	{RPC_PROGNOTREGISTERED, "RPC prog not registered"},
2277c478bdstevel@tonic-gate	{RPC_SYSTEMERROR, "RPC system error"},
2287c478bdstevel@tonic-gate	{RPC_SUCCESS, (char *)NULL}		/* Duplicate rpc_stat 	*/
2297c478bdstevel@tonic-gate						/* unused in list-end 	*/
2307c478bdstevel@tonic-gate						/* entry */
2317c478bdstevel@tonic-gate};
2327c478bdstevel@tonic-gate
2337c478bdstevel@tonic-gatestatic void get_default_domain_name(void);
2347c478bdstevel@tonic-gatestatic void get_command_line_args(int argc, char **argv);
2357c478bdstevel@tonic-gatestatic unsigned short send_message(struct server *ps,
2367c478bdstevel@tonic-gate					unsigned long program, long *err);
2377c478bdstevel@tonic-gatestatic void make_server_list(void);
2387c478bdstevel@tonic-gatestatic void one_host_list(void);
2397c478bdstevel@tonic-gatestatic void add_server(char *sname, int namelen);
2407c478bdstevel@tonic-gatestatic int  generate_callback(unsigned long *program);
2417c478bdstevel@tonic-gatestatic void xactid_seed(unsigned long *xactid);
2427c478bdstevel@tonic-gatestatic void main_loop(unsigned long program);
2437c478bdstevel@tonic-gatestatic void listener_exit(unsigned long program, int stat);
2447c478bdstevel@tonic-gatestatic void listener_dispatch(struct svc_req *rqstp, SVCXPRT *transp);
2457c478bdstevel@tonic-gatestatic void print_state_msg(struct server *s, long e);
2467c478bdstevel@tonic-gatestatic void print_callback_msg(struct server *s);
2477c478bdstevel@tonic-gatestatic void rpcerr_msg(enum clnt_stat e);
2487c478bdstevel@tonic-gatestatic void get_xfr_response(SVCXPRT *transp);
2497c478bdstevel@tonic-gate
2507c478bdstevel@tonic-gate#ifdef SYSVCONFIG
2517c478bdstevel@tonic-gateextern void sysvconfig(void);
2527c478bdstevel@tonic-gate#endif
2537c478bdstevel@tonic-gateextern int yp_getalias(char *key, char *key_alias, int maxlen);
2547c478bdstevel@tonic-gateextern int getdomainname(char *, int);
2557c478bdstevel@tonic-gate
2567c478bdstevel@tonic-gateextern struct rpc_createerr rpc_createerr;
2577c478bdstevel@tonic-gateextern CLIENT *__yp_clnt_create_rsvdport();
2587c478bdstevel@tonic-gate
2597c478bdstevel@tonic-gateint
2607c478bdstevel@tonic-gatemain(int argc, char **argv)
2617c478bdstevel@tonic-gate{
2627c478bdstevel@tonic-gate	unsigned long program;
263b892d00vt	struct stat64 sbuf;
2647c478bdstevel@tonic-gate
2657c478bdstevel@tonic-gate	get_command_line_args(argc, argv);
2667c478bdstevel@tonic-gate
2677c478bdstevel@tonic-gate	if (!domain) {
2687c478bdstevel@tonic-gate		get_default_domain_name();
2697c478bdstevel@tonic-gate	}
2707c478bdstevel@tonic-gate
2717c478bdstevel@tonic-gate#ifdef SYSVCONFIG
2727c478bdstevel@tonic-gate	sysvconfig();
2737c478bdstevel@tonic-gate#endif
2747c478bdstevel@tonic-gate
2757c478bdstevel@tonic-gate	if (yp_getalias(domain, domain_alias, NAME_MAX) != 0)
2767c478bdstevel@tonic-gate		fprintf(stderr, "domain alias for %s not found\n", domain);
2777c478bdstevel@tonic-gate	if (yp_getalias(map, map_alias, MAXALIASLEN) != 0)
2787c478bdstevel@tonic-gate		fprintf(stderr, "map alias for %s not found\n", map);
2797c478bdstevel@tonic-gate
2807c478bdstevel@tonic-gate	/* check to see if the map exists in this domain */
2817c478bdstevel@tonic-gate	if (is_yptol_mode())
2827c478bdstevel@tonic-gate		sprintf(ypmapname, "%s/%s/%s%s.dir", ypdbpath, domain_alias,
283b892d00vt		    NTOL_PREFIX, map_alias);
2847c478bdstevel@tonic-gate	else
2857c478bdstevel@tonic-gate		sprintf(ypmapname, "%s/%s/%s.dir", ypdbpath, domain_alias,
286b892d00vt		    map_alias);
287b892d00vt	if (stat64(ypmapname, &sbuf) < 0) {
2887c478bdstevel@tonic-gate		fprintf(stderr, "yppush: Map does not exist.\n");
2897c478bdstevel@tonic-gate		exit(1);
2907c478bdstevel@tonic-gate	}
2917c478bdstevel@tonic-gate
2927c478bdstevel@tonic-gate	if (onehost) {
2937c478bdstevel@tonic-gate		one_host_list();
2947c478bdstevel@tonic-gate	} else {
2957c478bdstevel@tonic-gate		make_server_list();
2967c478bdstevel@tonic-gate	}
2977c478bdstevel@tonic-gate
2987c478bdstevel@tonic-gate	/*
2997c478bdstevel@tonic-gate	 * All process exits after the call to generate_callback should be
3007c478bdstevel@tonic-gate	 * through listener_exit(program, status), not exit(status), so the
3017c478bdstevel@tonic-gate	 * transient server can get unregistered with the portmapper.
3027c478bdstevel@tonic-gate	 */
3037c478bdstevel@tonic-gate
3047c478bdstevel@tonic-gate	if (!generate_callback(&program)) {
3057c478bdstevel@tonic-gate		fprintf(stderr, "Can't set up transient callback server.\n");
3067c478bdstevel@tonic-gate	}
3077c478bdstevel@tonic-gate
3087c478bdstevel@tonic-gate	main_loop(program);
3097c478bdstevel@tonic-gate
3107c478bdstevel@tonic-gate	listener_exit(program, 0);
3117c478bdstevel@tonic-gate
3127c478bdstevel@tonic-gate	/* NOTREACHED */
3137c478bdstevel@tonic-gate	return (0);
3147c478bdstevel@tonic-gate}
3157c478bdstevel@tonic-gate
3167c478bdstevel@tonic-gate/*
3177c478bdstevel@tonic-gate * This does the command line parsing.
3187c478bdstevel@tonic-gate */
3197c478bdstevel@tonic-gatestatic void
3207c478bdstevel@tonic-gateget_command_line_args(int argc, char **argv)
3217c478bdstevel@tonic-gate{
3227c478bdstevel@tonic-gate	pusage = err_usage;
3237c478bdstevel@tonic-gate	argv++;
3247c478bdstevel@tonic-gate
3257c478bdstevel@tonic-gate	if (argc < 2) {
3267c478bdstevel@tonic-gate		fprintf(stderr, pusage);
3277c478bdstevel@tonic-gate		exit(1);
3287c478bdstevel@tonic-gate	}
3297c478bdstevel@tonic-gate
3307c478bdstevel@tonic-gate	while (--argc) {
3317c478bdstevel@tonic-gate		if ((*argv)[0] == '-') {
3327c478bdstevel@tonic-gate			switch ((*argv)[1]) {
3337c478bdstevel@tonic-gate			case 'v':
3347c478bdstevel@tonic-gate				verbose = TRUE;
3357c478bdstevel@tonic-gate				argv++;
3367c478bdstevel@tonic-gate				break;
3377c478bdstevel@tonic-gate			case 'd':
3387c478bdstevel@tonic-gate				if (argc > 1) {
3397c478bdstevel@tonic-gate					argv++;
3407c478bdstevel@tonic-gate					argc--;
3417c478bdstevel@tonic-gate					domain = *argv;
3427c478bdstevel@tonic-gate					argv++;
3437c478bdstevel@tonic-gate					if (((int)strlen(domain)) >
344b892d00vt					    YPMAXDOMAIN) {
3457c478bdstevel@tonic-gate						fprintf(stderr,
346b892d00vt						    err_bad_args,
347b892d00vt						    err_bad_domainname);
3487c478bdstevel@tonic-gate						exit(1);
3497c478bdstevel@tonic-gate					}
3507c478bdstevel@tonic-gate				} else {
3517c478bdstevel@tonic-gate					fprintf(stderr, pusage);
3527c478bdstevel@tonic-gate					exit(1);
3537c478bdstevel@tonic-gate				}
3547c478bdstevel@tonic-gate				break;
3557c478bdstevel@tonic-gate			case 'h':
3567c478bdstevel@tonic-gate				if (argc > 1) {
3577c478bdstevel@tonic-gate					onehost = TRUE;
3587c478bdstevel@tonic-gate					argv++;
3597c478bdstevel@tonic-gate					argc--;
3607c478bdstevel@tonic-gate					host = *argv;
3617c478bdstevel@tonic-gate					argv++;
3627c478bdstevel@tonic-gate				} else {
3637c478bdstevel@tonic-gate					fprintf(stderr, pusage);
3647c478bdstevel@tonic-gate					exit(1);
3657c478bdstevel@tonic-gate				}
3667c478bdstevel@tonic-gate				break;
3677c478bdstevel@tonic-gate
3687c478bdstevel@tonic-gate			case 'p':
3697c478bdstevel@tonic-gate
3707c478bdstevel@tonic-gate				if (argc > 1) {
3717c478bdstevel@tonic-gate					argv++;
3727c478bdstevel@tonic-gate					argc--;
3737c478bdstevel@tonic-gate					if (sscanf(*argv, "%d", &curpar) != 1) {
3747c478bdstevel@tonic-gate						(void) fprintf(stderr, pusage);
3757c478bdstevel@tonic-gate						exit(1);
3767c478bdstevel@tonic-gate					}
3777c478bdstevel@tonic-gate					argv++;
3787c478bdstevel@tonic-gate					if (curpar < 1) {
3797c478bdstevel@tonic-gate						(void) fprintf(stderr, pusage);
3807c478bdstevel@tonic-gate						exit(1);
3817c478bdstevel@tonic-gate					}
3827c478bdstevel@tonic-gate				} else {
3837c478bdstevel@tonic-gate					(void) fprintf(stderr, pusage);
3847c478bdstevel@tonic-gate					exit(1);
3857c478bdstevel@tonic-gate				}
3867c478bdstevel@tonic-gate				break;
3877c478bdstevel@tonic-gate
3887c478bdstevel@tonic-gate			default:
3897c478bdstevel@tonic-gate				fprintf(stderr, pusage);
3907c478bdstevel@tonic-gate				exit(1);
3917c478bdstevel@tonic-gate			}
3927c478bdstevel@tonic-gate		} else {
3937c478bdstevel@tonic-gate			if (!map) {
3947c478bdstevel@tonic-gate				map = *argv;
3957c478bdstevel@tonic-gate			} else {
3967c478bdstevel@tonic-gate				fprintf(stderr, pusage);
3977c478bdstevel@tonic-gate				exit(1);
3987c478bdstevel@tonic-gate			}
3997c478bdstevel@tonic-gate			argv++;
4007c478bdstevel@tonic-gate		}
4017c478bdstevel@tonic-gate	}
4027c478bdstevel@tonic-gate
4037c478bdstevel@tonic-gate	if (!map) {
4047c478bdstevel@tonic-gate		fprintf(stderr, pusage);
4057c478bdstevel@tonic-gate		exit(1);
4067c478bdstevel@tonic-gate	}
4077c478bdstevel@tonic-gate}
4087c478bdstevel@tonic-gate
4097c478bdstevel@tonic-gate/*
4107c478bdstevel@tonic-gate *  This gets the local kernel domainname, and sets the global domain to it.
4117c478bdstevel@tonic-gate */
4127c478bdstevel@tonic-gatestatic void
4137c478bdstevel@tonic-gateget_default_domain_name(void)
4147c478bdstevel@tonic-gate{
4157c478bdstevel@tonic-gate	if (!getdomainname(default_domain_name, YPMAXDOMAIN)) {
4167c478bdstevel@tonic-gate		domain = default_domain_name;
4177c478bdstevel@tonic-gate	} else {
4187c478bdstevel@tonic-gate		fprintf(stderr, err_cant_get_kname, err_bad_domainname);
4197c478bdstevel@tonic-gate		exit(1);
4207c478bdstevel@tonic-gate	}
4217c478bdstevel@tonic-gate
4227c478bdstevel@tonic-gate	if ((int)strlen(domain) == 0) {
4237c478bdstevel@tonic-gate		fprintf(stderr, err_null_kname, err_bad_domainname);
4247c478bdstevel@tonic-gate		exit(1);
4257c478bdstevel@tonic-gate	}
4267c478bdstevel@tonic-gate}
4277c478bdstevel@tonic-gate
4287c478bdstevel@tonic-gate/*
4297c478bdstevel@tonic-gate * This verifies that the hostname supplied by the user is in the map
4307c478bdstevel@tonic-gate * "ypservers" then calls add_server to make it the only entry on the
4317c478bdstevel@tonic-gate * list of servers.
4327c478bdstevel@tonic-gate */
4337c478bdstevel@tonic-gatestatic void
4347c478bdstevel@tonic-gateone_host_list(void)
4357c478bdstevel@tonic-gate{
4367c478bdstevel@tonic-gate	char *key;
4377c478bdstevel@tonic-gate	int keylen;
4387c478bdstevel@tonic-gate	char *val;
4397c478bdstevel@tonic-gate	int vallen;
4407c478bdstevel@tonic-gate	int err;
4417c478bdstevel@tonic-gate	char *ypservers = "ypservers";
4427c478bdstevel@tonic-gate
4437c478bdstevel@tonic-gate	if (verbose) {
4447c478bdstevel@tonic-gate		printf("Verifying YP server: %s\n", host);
4457c478bdstevel@tonic-gate		fflush(stdout);
4467c478bdstevel@tonic-gate	}
4477c478bdstevel@tonic-gate
4487c478bdstevel@tonic-gate	if (err = yp_bind(domain_alias)) {
4497c478bdstevel@tonic-gate		fprintf(stderr, err_cant_bind, domain, yperr_string(err));
4507c478bdstevel@tonic-gate		exit(1);
4517c478bdstevel@tonic-gate	}
4527c478bdstevel@tonic-gate
4537c478bdstevel@tonic-gate	keylen = strlen(host);
4547c478bdstevel@tonic-gate
4557c478bdstevel@tonic-gate	if (yp_match(domain_alias, ypservers, host, keylen,
456b892d00vt	    &val, &vallen)) {
4577c478bdstevel@tonic-gate		fprintf(stderr, err_cant_find_host, host);
4587c478bdstevel@tonic-gate		exit(1);
4597c478bdstevel@tonic-gate	}
4607c478bdstevel@tonic-gate
4617c478bdstevel@tonic-gate	add_server(host, keylen);
4627c478bdstevel@tonic-gate}
4637c478bdstevel@tonic-gate
4647c478bdstevel@tonic-gate/*
4657c478bdstevel@tonic-gate * This uses yp operations to retrieve each server name in the map
4667c478bdstevel@tonic-gate *  "ypservers".  add_server is called for each one to add it to the list of
4677c478bdstevel@tonic-gate *  servers.
4687c478bdstevel@tonic-gate */
4697c478bdstevel@tonic-gatestatic void
4707c478bdstevel@tonic-gatemake_server_list(void)
4717c478bdstevel@tonic-gate{
4727c478bdstevel@tonic-gate	char *key;
4737c478bdstevel@tonic-gate	int keylen;
4747c478bdstevel@tonic-gate	char *outkey;
4757c478bdstevel@tonic-gate	int outkeylen;
4767c478bdstevel@tonic-gate	char *val;
4777c478bdstevel@tonic-gate	int vallen;
4787c478bdstevel@tonic-gate	int err;
4797c478bdstevel@tonic-gate	char *ypservers = "ypservers";
4807c478bdstevel@tonic-gate	int count;
4817c478bdstevel@tonic-gate
4827c478bdstevel@tonic-gate	if (verbose) {
4837c478bdstevel@tonic-gate		printf("Finding YP servers: ");
4847c478bdstevel@tonic-gate		fflush(stdout);
4857c478bdstevel@tonic-gate		count = 4;
4867c478bdstevel@tonic-gate	}
4877c478bdstevel@tonic-gate
4887c478bdstevel@tonic-gate	if (err = yp_bind(domain_alias)) {
4897c478bdstevel@tonic-gate		fprintf(stderr, err_cant_bind, domain, yperr_string(err));
4907c478bdstevel@tonic-gate		exit(1);
4917c478bdstevel@tonic-gate	}
4927c478bdstevel@tonic-gate
4937c478bdstevel@tonic-gate	if (err = yp_first(domain_alias, ypservers, &outkey, &outkeylen,
494b892d00vt	    &val, &vallen)) {
4957c478bdstevel@tonic-gate		fprintf(stderr, err_cant_build_serverlist, yperr_string(err));
4967c478bdstevel@tonic-gate		exit(1);
4977c478bdstevel@tonic-gate	}
4987c478bdstevel@tonic-gate
4997c478bdstevel@tonic-gate	for (;;) {
5007c478bdstevel@tonic-gate		add_server(outkey, outkeylen);
5017c478bdstevel@tonic-gate		if (verbose) {
5027c478bdstevel@tonic-gate			printf(" %s", outkey);
5037c478bdstevel@tonic-gate			fflush(stdout);
5047c478bdstevel@tonic-gate			if (count++ == 8) {
5057c478bdstevel@tonic-gate				printf("\n");
5067c478bdstevel@tonic-gate				count = 0;
5077c478bdstevel@tonic-gate			}
5087c478bdstevel@tonic-gate		}
5097c478bdstevel@tonic-gate		free(val);
5107c478bdstevel@tonic-gate		key = outkey;
5117c478bdstevel@tonic-gate		keylen = outkeylen;
5127c478bdstevel@tonic-gate
5137c478bdstevel@tonic-gate		if (err = yp_next(domain_alias, ypservers, key, keylen,
514b892d00vt		    &outkey, &outkeylen, &val, &vallen)) {
5157c478bdstevel@tonic-gate
516b892d00vt			if (err == YPERR_NOMORE) {
517b892d00vt				break;
518b892d00vt			} else {
519b892d00vt				fprintf(stderr, err_cant_build_serverlist,
520b892d00vt				    yperr_string(err));
521b892d00vt				exit(1);
522b892d00vt			}
5237c478bdstevel@tonic-gate		}
5247c478bdstevel@tonic-gate
5257c478bdstevel@tonic-gate		free(key);
5267c478bdstevel@tonic-gate	}
5277c478bdstevel@tonic-gate	if (count != 0) {
5287c478bdstevel@tonic-gate		if (verbose)
5297c478bdstevel@tonic-gate			printf("\n");
5307c478bdstevel@tonic-gate	}
5317c478bdstevel@tonic-gate}
5327c478bdstevel@tonic-gate
5337c478bdstevel@tonic-gate/*
5347c478bdstevel@tonic-gate *  This adds a single server to the server list.
5357c478bdstevel@tonic-gate */
5367c478bdstevel@tonic-gatestatic void
5377c478bdstevel@tonic-gateadd_server(char *sname, int namelen)
5387c478bdstevel@tonic-gate{
5397c478bdstevel@tonic-gate	struct server *ps;
5407c478bdstevel@tonic-gate	static unsigned long seq;
5417c478bdstevel@tonic-gate	static unsigned long xactid = 0;
5427c478bdstevel@tonic-gate
5437c478bdstevel@tonic-gate	if (strcmp(sname, my_name) == 0)
5447c478bdstevel@tonic-gate		return;
5457c478bdstevel@tonic-gate
5467c478bdstevel@tonic-gate	if (xactid == 0) {
5477c478bdstevel@tonic-gate		xactid_seed(&xactid);
5487c478bdstevel@tonic-gate	}
5497c478bdstevel@tonic-gate
5507c478bdstevel@tonic-gate	if ((ps = (struct server *)malloc((unsigned)sizeof (struct server)))
5517c478bdstevel@tonic-gate		== (struct server *)NULL) {
5527c478bdstevel@tonic-gate		perror("yppush: malloc failure");
5537c478bdstevel@tonic-gate		exit(1);
5547c478bdstevel@tonic-gate	}
5557c478bdstevel@tonic-gate
5567c478bdstevel@tonic-gate	sname[namelen] = '\0';
5577c478bdstevel@tonic-gate	strcpy(ps->svc_name, sname);
5587c478bdstevel@tonic-gate	ps->state = SSTAT_INIT;
5597c478bdstevel@tonic-gate	ps->status = 0;
5607c478bdstevel@tonic-gate	ps->oldvers = FALSE;
5617c478bdstevel@tonic-gate	ps->xactid = xactid + seq++;
5627c478bdstevel@tonic-gate	ps->pnext = server_list;
5637c478bdstevel@tonic-gate	server_list = ps;
5647c478bdstevel@tonic-gate}
5657c478bdstevel@tonic-gate
5667c478bdstevel@tonic-gate/*
5677c478bdstevel@tonic-gate * This sets the base range for the transaction ids used in speaking the the
5687c478bdstevel@tonic-gate *  server ypxfr processes.
5697c478bdstevel@tonic-gate */
5707c478bdstevel@tonic-gatestatic void
5717c478bdstevel@tonic-gatexactid_seed(unsigned long *xactid)
5727c478bdstevel@tonic-gate{
5737c478bdstevel@tonic-gate	struct timeval t;
5747c478bdstevel@tonic-gate
5757c478bdstevel@tonic-gate	if (gettimeofday(&t) == -1) {
5767c478bdstevel@tonic-gate		perror("yppush gettimeofday failure");
5777c478bdstevel@tonic-gate		*xactid = 1234567;
5787c478bdstevel@tonic-gate	} else {
5797c478bdstevel@tonic-gate		*xactid = t.tv_sec;
5807c478bdstevel@tonic-gate	}
5817c478bdstevel@tonic-gate}
5827c478bdstevel@tonic-gate
5837c478bdstevel@tonic-gate/*
5847c478bdstevel@tonic-gate *  This generates the channel which will be used as the listener process'
5857c478bdstevel@tonic-gate *  service rendezvous point, and comes up with a transient program number
5867c478bdstevel@tonic-gate *  for the use of the RPC messages from the ypxfr processes.
5877c478bdstevel@tonic-gate */
5887c478bdstevel@tonic-gatestatic int
5897c478bdstevel@tonic-gategenerate_callback(unsigned long *program)
5907c478bdstevel@tonic-gate{
5917c478bdstevel@tonic-gate	unsigned long prognum = 0x40000000, maxprognum;
5927c478bdstevel@tonic-gate	union {
5937c478bdstevel@tonic-gate		unsigned long	p;
5947c478bdstevel@tonic-gate		unsigned char	b[sizeof (unsigned long)];
5957c478bdstevel@tonic-gate	} u;
5967c478bdstevel@tonic-gate	int ret, i;
5977c478bdstevel@tonic-gate	struct netconfig *nc4, *nc6, *nc;
5987c478bdstevel@tonic-gate	SVCXPRT *trans;
5997c478bdstevel@tonic-gate
6007c478bdstevel@tonic-gate	nc4 = getnetconfigent("udp");
6017c478bdstevel@tonic-gate	nc6 = getnetconfigent("udp6");
6027c478bdstevel@tonic-gate	if (nc4 == 0 && nc6 == 0) {
6037c478bdstevel@tonic-gate		fprintf(stderr,
604b892d00vt		    "yppush: Could not get udp or udp6 netconfig entry\n");
6057c478bdstevel@tonic-gate		exit(1);
6067c478bdstevel@tonic-gate	}
6077c478bdstevel@tonic-gate
6087c478bdstevel@tonic-gate	transport4 = (nc4 == 0) ? 0 : svc_tli_create(RPC_ANYFD, nc4, 0, 0, 0);
6097c478bdstevel@tonic-gate	transport6 = (nc6 == 0) ? 0 : svc_tli_create(RPC_ANYFD, nc6, 0, 0, 0);
6107c478bdstevel@tonic-gate	if (transport4 == 0 && transport6 == 0) {
6117c478bdstevel@tonic-gate		fprintf(stderr, "yppush: Could not create server handle(s)\n");
6127c478bdstevel@tonic-gate		exit(1);
6137c478bdstevel@tonic-gate	}
6147c478bdstevel@tonic-gate
6157c478bdstevel@tonic-gate	/* Find the maximum possible program number using an unsigned long */
6167c478bdstevel@tonic-gate	for (i = 0; i < sizeof (u.b); i++)
6177c478bdstevel@tonic-gate		u.b[i] = 0xff;
6187c478bdstevel@tonic-gate	maxprognum = u.p;
6197c478bdstevel@tonic-gate
6207c478bdstevel@tonic-gate	if (transport4 != 0) {
6217c478bdstevel@tonic-gate		trans = transport4;
6227c478bdstevel@tonic-gate		nc = nc4;
6237c478bdstevel@tonic-gate	} else {
6247c478bdstevel@tonic-gate		trans = transport6;
6257c478bdstevel@tonic-gate		nc = nc6;
6267c478bdstevel@tonic-gate	}
6277c478bdstevel@tonic-gate	while (prognum < maxprognum && (ret =
628b892d00vt	    rpcb_set(prognum, YPPUSHVERS, nc, &trans->xp_ltaddr)) == 0)
6297c478bdstevel@tonic-gate		prognum++;
6307c478bdstevel@tonic-gate
6317c478bdstevel@tonic-gate	if (ret == 0) {
6327c478bdstevel@tonic-gate		fprintf(stderr, "yppush: Could not create callback service\n");
6337c478bdstevel@tonic-gate		exit(1);
6347c478bdstevel@tonic-gate	} else {
6357c478bdstevel@tonic-gate		if (trans == transport4 && transport6 != 0) {
6367c478bdstevel@tonic-gate			ret = rpcb_set(prognum, YPPUSHVERS, nc6,
637b892d00vt			    &transport6->xp_ltaddr);
6387c478bdstevel@tonic-gate			if (ret == 0) {
6397c478bdstevel@tonic-gate				fprintf(stderr,
6407c478bdstevel@tonic-gate			"yppush: Could not create udp6 callback service\n");
6417c478bdstevel@tonic-gate				exit(1);
6427c478bdstevel@tonic-gate			}
6437c478bdstevel@tonic-gate		}
6447c478bdstevel@tonic-gate		*program = prognum;
6457c478bdstevel@tonic-gate	}
6467c478bdstevel@tonic-gate
6477c478bdstevel@tonic-gate	return (ret);
6487c478bdstevel@tonic-gate}
6497c478bdstevel@tonic-gate
6507c478bdstevel@tonic-gate/*
6517c478bdstevel@tonic-gate * This is the main loop. Send messages to each server,
6527c478bdstevel@tonic-gate * and then wait for a response.
6537c478bdstevel@tonic-gate */
6547c478bdstevel@tonic-gate
6557c478bdstevel@tonic-gate
656a506a34thint
6577c478bdstevel@tonic-gateadd_to_active()
6587c478bdstevel@tonic-gate{
6597c478bdstevel@tonic-gate	struct server  *ps;
6607c478bdstevel@tonic-gate	ps = server_list;
6617c478bdstevel@tonic-gate	if (ps == NULL)
6627c478bdstevel@tonic-gate		return (0);
6637c478bdstevel@tonic-gate	server_list = server_list->pnext;	/* delete from server_list */
6647c478bdstevel@tonic-gate	ps->pnext = active_list;
6657c478bdstevel@tonic-gate	active_list = ps;
6667c478bdstevel@tonic-gate	return (1);
6677c478bdstevel@tonic-gate}
6687c478bdstevel@tonic-gate
669a506a34thint
6707c478bdstevel@tonic-gatedelete_active(in)
6717c478bdstevel@tonic-gate	struct server  *in;
6727c478bdstevel@tonic-gate{
6737c478bdstevel@tonic-gate	struct server  *p;
6747c478bdstevel@tonic-gate	struct server  *n;
6757c478bdstevel@tonic-gate	if (in == active_list) {
6767c478bdstevel@tonic-gate		active_list = active_list->pnext;
6777c478bdstevel@tonic-gate		return (1);
6787c478bdstevel@tonic-gate	}
6797c478bdstevel@tonic-gate	p = active_list;
6807c478bdstevel@tonic-gate	for (n = active_list; n; n = n->pnext) {
6817c478bdstevel@tonic-gate		if (in == n) {
6827c478bdstevel@tonic-gate			p->pnext = n->pnext;
6837c478bdstevel@tonic-gate			return (0);
6847c478bdstevel@tonic-gate
6857c478bdstevel@tonic-gate		}
6867c478bdstevel@tonic-gate		p = n;
6877c478bdstevel@tonic-gate	}
6887c478bdstevel@tonic-gate	return (-1);
6897c478bdstevel@tonic-gate}
6907c478bdstevel@tonic-gate
6917c478bdstevel@tonic-gatevoid
6927c478bdstevel@tonic-gatemain_loop(program)
6937c478bdstevel@tonic-gate	unsigned long   program;
6947c478bdstevel@tonic-gate{
6957c478bdstevel@tonic-gate	pollfd_t	*pollset = NULL;
6967c478bdstevel@tonic-gate	int		npollfds = 0;
6977c478bdstevel@tonic-gate	int		pollret;
6987c478bdstevel@tonic-gate	struct server	*ps;
6997c478bdstevel@tonic-gate	long		error;
7007c478bdstevel@tonic-gate	int		hpar;	/* this times par count */
7017c478bdstevel@tonic-gate	int		i;
7027c478bdstevel@tonic-gate	int		j;
7037c478bdstevel@tonic-gate	int		time_now;
7047c478bdstevel@tonic-gate	int		docb;
7057c478bdstevel@tonic-gate	int		actives = 0;
7067c478bdstevel@tonic-gate	int		dead = 0;
7077c478bdstevel@tonic-gate
7087c478bdstevel@tonic-gate	if (grace_period < MIN_GRACE)
7097c478bdstevel@tonic-gate		grace_period = MIN_GRACE;
7107c478bdstevel@tonic-gate	if (transport4 != 0) {
7117c478bdstevel@tonic-gate		if (!svc_reg(transport4, program, YPPUSHVERS,
7127c478bdstevel@tonic-gate				listener_dispatch, 0)) {
7137c478bdstevel@tonic-gate			fprintf(stderr,
7147c478bdstevel@tonic-gate			"Can't set up transient udp callback server.\n");
7157c478bdstevel@tonic-gate		}
7167c478bdstevel@tonic-gate	}
7177c478bdstevel@tonic-gate	if (transport6 != 0) {
7187c478bdstevel@tonic-gate		if (!svc_reg(transport6, program, YPPUSHVERS,
7197c478bdstevel@tonic-gate				listener_dispatch, 0)) {
7207c478bdstevel@tonic-gate			fprintf(stderr,
7217c478bdstevel@tonic-gate			"Can't set up transient udp6 callback server.\n");
7227c478bdstevel@tonic-gate		}
7237c478bdstevel@tonic-gate	}
7247c478bdstevel@tonic-gate	for (;;) {
7257c478bdstevel@tonic-gate		time_now = time(0);
7267c478bdstevel@tonic-gate		if (server_list == NULL) {
7277c478bdstevel@tonic-gate			actives = 0;
7287c478bdstevel@tonic-gate			dead = 0;
7297c478bdstevel@tonic-gate			for (ps = active_list; ps; ps = ps->pnext)
7307c478bdstevel@tonic-gate				if (ps->state == SSTAT_CALLED) {
7317c478bdstevel@tonic-gate					if ((time_now - ps->start_time) <
7327c478bdstevel@tonic-gate								grace_period)
7337c478bdstevel@tonic-gate						actives++;
7347c478bdstevel@tonic-gate					else
7357c478bdstevel@tonic-gate						dead++;
7367c478bdstevel@tonic-gate				}
7377c478bdstevel@tonic-gate			if (actives == 0) {
7387c478bdstevel@tonic-gate				if (verbose) {
7397c478bdstevel@tonic-gate					printf("terminating %d dead\n", dead);
7407c478bdstevel@tonic-gate					fflush(stdout);
7417c478bdstevel@tonic-gate				}
7427c478bdstevel@tonic-gate
7437c478bdstevel@tonic-gate				for (ps = active_list; ps; ps = ps->pnext)
7447c478bdstevel@tonic-gate					if (ps->state == SSTAT_CALLED) {
7457c478bdstevel@tonic-gate						if ((time_now - ps->start_time)
7467c478bdstevel@tonic-gate							>= grace_period) {
7477c478bdstevel@tonic-gate							if (verbose) {
7487c478bdstevel@tonic-gate								printf(
7497c478bdstevel@tonic-gate		    "no response from %s -- grace of %d seconds expired.\n",
7507c478bdstevel@tonic-gate		    ps->svc_name, grace_period);
7517c478bdstevel@tonic-gate								fflush(stdout);
7527c478bdstevel@tonic-gate							}
7537c478bdstevel@tonic-gate							fprintf(stderr,
7547c478bdstevel@tonic-gate		    "No response from ypxfr on %s\n", ps->svc_name);
7557c478bdstevel@tonic-gate						}
7567c478bdstevel@tonic-gate					}
7577c478bdstevel@tonic-gate				break;
7587c478bdstevel@tonic-gate			}
7597c478bdstevel@tonic-gate		}
7607c478bdstevel@tonic-gate		actives = 0;
7617c478bdstevel@tonic-gate		for (ps = active_list; ps; ps = ps->pnext) {
7627c478bdstevel@tonic-gate			if (ps->state == SSTAT_CALLED) {
7637c478bdstevel@tonic-gate				if ((time_now - ps->start_time)
7647c478bdstevel@tonic-gate						< grace_period) {
7657c478bdstevel@tonic-gate					actives++;
7667c478bdstevel@tonic-gate
7677c478bdstevel@tonic-gate					if (verbose) {
7687c478bdstevel@tonic-gate						printf(
7697c478bdstevel@tonic-gate		    "No response yet from ypxfr on %s\n", ps->svc_name);
7707c478bdstevel@tonic-gate						fflush(stdout);
7717c478bdstevel@tonic-gate					}
7727c478bdstevel@tonic-gate				}
7737c478bdstevel@tonic-gate			} else {
7747c478bdstevel@tonic-gate				if (verbose) {
7757c478bdstevel@tonic-gate					printf("Deactivating  %s\n",
7767c478bdstevel@tonic-gate						ps->svc_name);
7777c478bdstevel@tonic-gate					fflush(stdout);
7787c478bdstevel@tonic-gate				}
7797c478bdstevel@tonic-gate				delete_active(ps);
7807c478bdstevel@tonic-gate			}
7817c478bdstevel@tonic-gate		}
7827c478bdstevel@tonic-gate
7837c478bdstevel@tonic-gate		/* add someone to the active list keep up with curpar */
7847c478bdstevel@tonic-gate		for (i = 0; i < (curpar - actives); i++) {
7857c478bdstevel@tonic-gate			if (add_to_active()) {
7867c478bdstevel@tonic-gate				ps = active_list;
7877c478bdstevel@tonic-gate				ps->state = send_message(ps, program, &error);
7887c478bdstevel@tonic-gate				print_state_msg(ps, error);
7897c478bdstevel@tonic-gate				if (ps->state != SSTAT_CALLED)
7907c478bdstevel@tonic-gate					delete_active(ps);	/* zorch it */
7917c478bdstevel@tonic-gate				else
7927c478bdstevel@tonic-gate					ps->start_time = time(0); /* set time */
7937c478bdstevel@tonic-gate			}
7947c478bdstevel@tonic-gate		}
7957c478bdstevel@tonic-gate		docb = 0;
7967c478bdstevel@tonic-gate		for (ps = active_list; ps; ps = ps->pnext)
7977c478bdstevel@tonic-gate			if (ps->state == SSTAT_CALLED) {
7987c478bdstevel@tonic-gate				docb = 1;
7997c478bdstevel@tonic-gate				break;
8007c478bdstevel@tonic-gate			}
8017c478bdstevel@tonic-gate		if (docb == 0) {
8027c478bdstevel@tonic-gate			if (verbose) {
8037c478bdstevel@tonic-gate				printf("No one to wait for this pass.\n");
8047c478bdstevel@tonic-gate				fflush(stdout);
8057c478bdstevel@tonic-gate			}
8067c478bdstevel@tonic-gate			continue;	/* try curpar more */
8077c478bdstevel@tonic-gate		}
8087c478bdstevel@tonic-gate
8097c478bdstevel@tonic-gate		if (npollfds != svc_max_pollfd) {
8107c478bdstevel@tonic-gate			pollset = realloc(pollset,
8117c478bdstevel@tonic-gate					sizeof (pollfd_t) * svc_max_pollfd);
8127c478bdstevel@tonic-gate			npollfds = svc_max_pollfd;
8137c478bdstevel@tonic-gate		}
8147c478bdstevel@tonic-gate
8157c478bdstevel@tonic-gate		/*
8167c478bdstevel@tonic-gate		 * Get existing array of pollfd's, should really compress
8177c478bdstevel@tonic-gate		 * this but it shouldn't get very large (or sparse).
8187c478bdstevel@tonic-gate		 */
8197c478bdstevel@tonic-gate		(void) memcpy(pollset, svc_pollfd,
8207c478bdstevel@tonic-gate					sizeof (pollfd_t) * svc_max_pollfd);
8217c478bdstevel@tonic-gate
8227c478bdstevel@tonic-gate		errno = 0;
8237c478bdstevel@tonic-gate		switch (pollret = poll(pollset, npollfds, MIN_GRACE * 1000)) {
8247c478bdstevel@tonic-gate		    case -1:
8257c478bdstevel@tonic-gate			if (errno != EINTR) {
8267c478bdstevel@tonic-gate				(void) perror("main loop select");
8277c478bdstevel@tonic-gate			}
8287c478bdstevel@tonic-gate			break;
8297c478bdstevel@tonic-gate
8307c478bdstevel@tonic-gate		    case 0:
8317c478bdstevel@tonic-gate			if (verbose) {
8327c478bdstevel@tonic-gate				(void) printf("timeout in main loop select.\n");
8337c478bdstevel@tonic-gate				fflush(stdout);
8347c478bdstevel@tonic-gate			}
8357c478bdstevel@tonic-gate			break;
8367c478bdstevel@tonic-gate
8377c478bdstevel@tonic-gate		    default:
8387c478bdstevel@tonic-gate			svc_getreq_poll(pollset, pollret);
8397c478bdstevel@tonic-gate			break;
8407c478bdstevel@tonic-gate		}		/* switch */
8417c478bdstevel@tonic-gate	}			/* for */
8427c478bdstevel@tonic-gate}
8437c478bdstevel@tonic-gate
8447c478bdstevel@tonic-gate/*
8457c478bdstevel@tonic-gate * This does the listener process cleanup and process exit.
8467c478bdstevel@tonic-gate */
8477c478bdstevel@tonic-gatestatic void
8487c478bdstevel@tonic-gatelistener_exit(unsigned long program, int stat)
8497c478bdstevel@tonic-gate{
8507c478bdstevel@tonic-gate	svc_unreg(program, YPPUSHVERS);
8517c478bdstevel@tonic-gate	exit(stat);
8527c478bdstevel@tonic-gate}
8537c478bdstevel@tonic-gate
8547c478bdstevel@tonic-gate/*
8557c478bdstevel@tonic-gate * This is the listener process' RPC service dispatcher.
8567c478bdstevel@tonic-gate */
8577c478bdstevel@tonic-gatestatic void
8587c478bdstevel@tonic-gatelistener_dispatch(struct svc_req *rqstp, SVCXPRT *transp)
8597c478bdstevel@tonic-gate{
8607c478bdstevel@tonic-gate	switch (rqstp->rq_proc) {
8617c478bdstevel@tonic-gate
8627c478bdstevel@tonic-gate	case YPPUSHPROC_NULL:
8637c478bdstevel@tonic-gate		if (!svc_sendreply(transp, xdr_void, 0)) {
864b892d00vt			fprintf(stderr, "Can't reply to rpc call.\n");
8657c478bdstevel@tonic-gate		}
8667c478bdstevel@tonic-gate		break;
8677c478bdstevel@tonic-gate
8687c478bdstevel@tonic-gate	case YPPUSHPROC_XFRRESP:
8697c478bdstevel@tonic-gate		get_xfr_response(transp);
8707c478bdstevel@tonic-gate		break;
8717c478bdstevel@tonic-gate
8727c478bdstevel@tonic-gate	default:
8737c478bdstevel@tonic-gate		svcerr_noproc(transp);
8747c478bdstevel@tonic-gate		break;
8757c478bdstevel@tonic-gate	}
8767c478bdstevel@tonic-gate}
8777c478bdstevel@tonic-gate
8787c478bdstevel@tonic-gate
8797c478bdstevel@tonic-gate/*
8807c478bdstevel@tonic-gate *  This dumps a server state message to stdout.  It is called in cases where
8817c478bdstevel@tonic-gate *  we have no expectation of receiving a callback from the remote ypxfr.
8827c478bdstevel@tonic-gate */
8837c478bdstevel@tonic-gatestatic void
8847c478bdstevel@tonic-gateprint_state_msg(struct server *s, long e)
8857c478bdstevel@tonic-gate{
8867c478bdstevel@tonic-gate	struct state_duple *sd;
8877c478bdstevel@tonic-gate
8887c478bdstevel@tonic-gate	if (s->state == SSTAT_SYSTEM)
8897c478bdstevel@tonic-gate		return;			/* already printed */
8907c478bdstevel@tonic-gate
8917c478bdstevel@tonic-gate	if (!verbose && (s->state == SSTAT_RESPONDED ||
892b892d00vt	    s->state == SSTAT_CALLED))
8937c478bdstevel@tonic-gate		return;
8947c478bdstevel@tonic-gate
8957c478bdstevel@tonic-gate	for (sd = state_duples; sd->state_msg; sd++) {
8967c478bdstevel@tonic-gate		if (sd->state == s->state) {
8977c478bdstevel@tonic-gate			printf(sd->state_msg, s->svc_name);
8987c478bdstevel@tonic-gate
8997c478bdstevel@tonic-gate			if (s->state == SSTAT_RPC) {
9007c478bdstevel@tonic-gate				rpcerr_msg((enum clnt_stat) e);
9017c478bdstevel@tonic-gate			}
9027c478bdstevel@tonic-gate
9037c478bdstevel@tonic-gate			printf("\n");
9047c478bdstevel@tonic-gate			fflush(stdout);
9057c478bdstevel@tonic-gate			return;
9067c478bdstevel@tonic-gate		}
9077c478bdstevel@tonic-gate	}
9087c478bdstevel@tonic-gate
9097c478bdstevel@tonic-gate	fprintf(stderr, "yppush: Bad server state value %d.\n", s->state);
9107c478bdstevel@tonic-gate}
9117c478bdstevel@tonic-gate
9127c478bdstevel@tonic-gate/*
9137c478bdstevel@tonic-gate *  This dumps a transfer status message to stdout.  It is called in
9147c478bdstevel@tonic-gate *  response to a received RPC message from the called ypxfr.
9157c478bdstevel@tonic-gate */
9167c478bdstevel@tonic-gatestatic void
9177c478bdstevel@tonic-gateprint_callback_msg(struct server *s)
9187c478bdstevel@tonic-gate{
9197c478bdstevel@tonic-gate	register struct status_duple *sd;
9207c478bdstevel@tonic-gate
9217c478bdstevel@tonic-gate	if (!verbose &&
922b892d00vt	    (s->status == YPPUSH_AGE) ||
923b892d00vt	    (s->status == YPPUSH_SUCC))
9247c478bdstevel@tonic-gate
9257c478bdstevel@tonic-gate		return;
9267c478bdstevel@tonic-gate
9277c478bdstevel@tonic-gate	for (sd = status_duples; sd->status_msg; sd++) {
9287c478bdstevel@tonic-gate
9297c478bdstevel@tonic-gate		if (sd->status == s->status) {
9307c478bdstevel@tonic-gate			printf("Status received from ypxfr on %s:\n\t%s\n",
931b892d00vt			    s->svc_name, sd->status_msg);
9327c478bdstevel@tonic-gate			fflush(stdout);
9337c478bdstevel@tonic-gate			return;
9347c478bdstevel@tonic-gate		}
9357c478bdstevel@tonic-gate	}
9367c478bdstevel@tonic-gate
9377c478bdstevel@tonic-gate	fprintf(stderr, "yppush listener: Garbage transaction "
938b892d00vt	    "status (value %d) from ypxfr on %s.\n",
939b892d00vt	    (int)s->status, s->svc_name);
9407c478bdstevel@tonic-gate}
9417c478bdstevel@tonic-gate
9427c478bdstevel@tonic-gate/*
9437c478bdstevel@tonic-gate *  This dumps an RPC error message to stdout.  This is basically a rewrite
9447c478bdstevel@tonic-gate *  of clnt_perrno, but writes to stdout instead of stderr.
9457c478bdstevel@tonic-gate */
9467c478bdstevel@tonic-gatestatic void
9477c478bdstevel@tonic-gaterpcerr_msg(enum clnt_stat e)
9487c478bdstevel@tonic-gate{
9497c478bdstevel@tonic-gate	struct rpcerr_duple *rd;
9507c478bdstevel@tonic-gate
9517c478bdstevel@tonic-gate	for (rd = rpcerr_duples; rd->rpc_msg; rd++) {
9527c478bdstevel@tonic-gate
9537c478bdstevel@tonic-gate		if (rd->rpc_stat == e) {
9547c478bdstevel@tonic-gate			printf(rd->rpc_msg);
9557c478bdstevel@tonic-gate			return;
9567c478bdstevel@tonic-gate		}
9577c478bdstevel@tonic-gate	}
9587c478bdstevel@tonic-gate
9597c478bdstevel@tonic-gate	fprintf(stderr, "Bad error code passed to rpcerr_msg: %d.\n", e);
9607c478bdstevel@tonic-gate}
9617c478bdstevel@tonic-gate
9627c478bdstevel@tonic-gate/*
9637c478bdstevel@tonic-gate * This picks up the response from the ypxfr process which has been started
9647c478bdstevel@tonic-gate * up on the remote node.  The response status must be non-zero, otherwise
9657c478bdstevel@tonic-gate * the status will be set to "ypxfr error".
9667c478bdstevel@tonic-gate */
9677c478bdstevel@tonic-gatestatic void
9687c478bdstevel@tonic-gateget_xfr_response(SVCXPRT *transp)
9697c478bdstevel@tonic-gate{
9707c478bdstevel@tonic-gate	struct yppushresp_xfr resp;
9717c478bdstevel@tonic-gate	register struct server *s;
9727c478bdstevel@tonic-gate
9737c478bdstevel@tonic-gate	if (!svc_getargs(transp, (xdrproc_t)xdr_yppushresp_xfr,
974b892d00vt	    (caddr_t)&resp)) {
9757c478bdstevel@tonic-gate		svcerr_decode(transp);
9767c478bdstevel@tonic-gate		return;
9777c478bdstevel@tonic-gate	}
9787c478bdstevel@tonic-gate
9797c478bdstevel@tonic-gate	if (!svc_sendreply(transp, xdr_void, 0)) {
9807c478bdstevel@tonic-gate		(void) fprintf(stderr, "Can't reply to rpc call.\n");
9817c478bdstevel@tonic-gate	}
9827c478bdstevel@tonic-gate
9837c478bdstevel@tonic-gate	for (s = active_list; s; s = s->pnext) {
9847c478bdstevel@tonic-gate
9857c478bdstevel@tonic-gate		if (s->xactid == resp.transid) {
9867c478bdstevel@tonic-gate			s->status  = resp.status ? resp.status: YPPUSH_XFRERR;
9877c478bdstevel@tonic-gate			print_callback_msg(s);
9887c478bdstevel@tonic-gate			s->state = SSTAT_RESPONDED;
9897c478bdstevel@tonic-gate			return;
9907c478bdstevel@tonic-gate		}
9917c478bdstevel@tonic-gate	}
9927c478bdstevel@tonic-gate}
9937c478bdstevel@tonic-gate
9947c478bdstevel@tonic-gate/*
9957c478bdstevel@tonic-gate * This sends a message to a single ypserv process.  The return value is
9967c478bdstevel@tonic-gate * a state value.  If the RPC call fails because of a version
9977c478bdstevel@tonic-gate * mismatch, we'll assume that we're talking to a version 1 ypserv process,
99848bbca8Daniel Hoffman * and will send it an old "YPPROC_GET" request, as was defined in the
9997c478bdstevel@tonic-gate * earlier version of yp_prot.h
10007c478bdstevel@tonic-gate */
10017c478bdstevel@tonic-gatestatic unsigned short
10027c478bdstevel@tonic-gatesend_message(struct server *ps, unsigned long program, long *err)
10037c478bdstevel@tonic-gate{
10047c478bdstevel@tonic-gate	struct ypreq_newxfr req;
10057c478bdstevel@tonic-gate	struct ypreq_xfr oldreq;
10067c478bdstevel@tonic-gate	enum clnt_stat s;
10077c478bdstevel@tonic-gate	struct rpc_err rpcerr;
10087c478bdstevel@tonic-gate
10097c478bdstevel@tonic-gate	if ((ps->domb.dom_client = __yp_clnt_create_rsvdport(ps->svc_name,
1010b892d00vt	    YPPROG, YPVERS, (char *)NULL, 0, 0))  == NULL) {
10117c478bdstevel@tonic-gate
10127c478bdstevel@tonic-gate		if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED) {
10137c478bdstevel@tonic-gate			return (SSTAT_PROGNOTREG);
10147c478bdstevel@tonic-gate		} else {
10157c478bdstevel@tonic-gate			printf("Error talking to %s: ", ps->svc_name);
10167c478bdstevel@tonic-gate			rpcerr_msg(rpc_createerr.cf_stat);
10177c478bdstevel@tonic-gate			printf("\n");
10187c478bdstevel@tonic-gate			fflush(stdout);
10197c478bdstevel@tonic-gate			return (SSTAT_SYSTEM);
10207c478bdstevel@tonic-gate		}
10217c478bdstevel@tonic-gate	}
10227c478bdstevel@tonic-gate
10237c478bdstevel@tonic-gate	if (sysinfo(SI_HOSTNAME, my_name, sizeof (my_name)) == -1) {
10247c478bdstevel@tonic-gate		return (SSTAT_RSCRC);
10257c478bdstevel@tonic-gate	}
10267c478bdstevel@tonic-gate
10277c478bdstevel@tonic-gate	if (!oldxfr) {
10287c478bdstevel@tonic-gate		req.ypxfr_domain = domain;
10297c478bdstevel@tonic-gate		req.ypxfr_map = map;
10307c478bdstevel@tonic-gate		req.ypxfr_ordernum = 0;
10317c478bdstevel@tonic-gate		req.ypxfr_owner = my_name;
10327c478bdstevel@tonic-gate		req.name = ps->svc_name;
10337c478bdstevel@tonic-gate		/*
10347c478bdstevel@tonic-gate		 * the creation of field req.name, instead of ypreq_xfr (old)
10357c478bdstevel@tonic-gate		 * req.port, does not make any sense. it doesn't give any
10367c478bdstevel@tonic-gate		 * information to receiving ypserv except its own name !!
10377c478bdstevel@tonic-gate		 * new ypserv duplicates work for YPPROC_XFR and YPPROC_NEWXFR
10387c478bdstevel@tonic-gate		 */
10397c478bdstevel@tonic-gate		req.transid = ps->xactid;
10407c478bdstevel@tonic-gate		req.proto = program;
10417c478bdstevel@tonic-gate		s = (enum clnt_stat) clnt_call(ps->domb.dom_client,
1042b892d00vt		    YPPROC_NEWXFR, (xdrproc_t)xdr_ypreq_newxfr, (caddr_t)&req,
1043b892d00vt		    xdr_void, 0, timeout);
10447c478bdstevel@tonic-gate	}
10457c478bdstevel@tonic-gate
10467c478bdstevel@tonic-gate	clnt_geterr(ps->domb.dom_client, &rpcerr);
10477c478bdstevel@tonic-gate
10487c478bdstevel@tonic-gate	if (s == RPC_PROCUNAVAIL) {
10497c478bdstevel@tonic-gate		oldreq.ypxfr_domain = domain;
10507c478bdstevel@tonic-gate		oldreq.ypxfr_map = map;
10517c478bdstevel@tonic-gate		oldreq.ypxfr_ordernum = 0;
10527c478bdstevel@tonic-gate		oldreq.ypxfr_owner = my_name;
10537c478bdstevel@tonic-gate		oldreq.transid = ps->xactid;
10547c478bdstevel@tonic-gate		oldreq.proto = program;
10557c478bdstevel@tonic-gate		oldreq.port = 0;
10567c478bdstevel@tonic-gate		s = (enum clnt_stat) clnt_call(ps->domb.dom_client,
1057b892d00vt		    YPPROC_XFR, (xdrproc_t)xdr_ypreq_xfr, (caddr_t)&oldreq,
1058b892d00vt		    xdr_void, 0, timeout);
10597c478bdstevel@tonic-gate		clnt_geterr(ps->domb.dom_client, &rpcerr);
10607c478bdstevel@tonic-gate	}
10617c478bdstevel@tonic-gate
10627c478bdstevel@tonic-gate	clnt_destroy(ps->domb.dom_client);
10637c478bdstevel@tonic-gate
10647c478bdstevel@tonic-gate	if (s == RPC_SUCCESS) {
10657c478bdstevel@tonic-gate		return (SSTAT_CALLED);
10667c478bdstevel@tonic-gate	} else {
10677c478bdstevel@tonic-gate		*err = (long)rpcerr.re_status;
10687c478bdstevel@tonic-gate		return (SSTAT_RPC);
10697c478bdstevel@tonic-gate	}
10707c478bdstevel@tonic-gate	/*NOTREACHED*/
10717c478bdstevel@tonic-gate}
10727c478bdstevel@tonic-gate
10737c478bdstevel@tonic-gate/*
10747c478bdstevel@tonic-gate * FUNCTION:    is_yptol_mode();
10757c478bdstevel@tonic-gate *
10767c478bdstevel@tonic-gate * DESCRIPTION: Determines if we should run in N2L or traditional mode based
10777c478bdstevel@tonic-gate *              on the presence of the N2L mapping file.
10787c478bdstevel@tonic-gate *
10797c478bdstevel@tonic-gate *		This is a copy of a function from libnisdb. If more than this
10807c478bdstevel@tonic-gate *		one function become required it may be worth linking the
10817c478bdstevel@tonic-gate *		entire lib.
10827c478bdstevel@tonic-gate *
10837c478bdstevel@tonic-gate * INPUTS:      Nothing
10847c478bdstevel@tonic-gate *
10857c478bdstevel@tonic-gate * OUTPUTS:     TRUE = Run in N2L mode
10867c478bdstevel@tonic-gate *              FALSE = Run in traditional mode.
10877c478bdstevel@tonic-gate */
10887c478bdstevel@tonic-gatebool_t
10897c478bdstevel@tonic-gateis_yptol_mode()
10907c478bdstevel@tonic-gate{
10917c478bdstevel@tonic-gate	struct stat filestat;
10927c478bdstevel@tonic-gate
10937c478bdstevel@tonic-gate	if (stat(NTOL_MAP_FILE, &filestat) != -1)
10947c478bdstevel@tonic-gate		return (TRUE);
10957c478bdstevel@tonic-gate
10967c478bdstevel@tonic-gate	return (FALSE);
10977c478bdstevel@tonic-gate}
1098