xref: /onnv-gate/usr/src/ucbcmd/shutdown/shutdown.c (revision 523:4aeaed772941)
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
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
230Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
300Sstevel@tonic-gate /*
310Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
320Sstevel@tonic-gate  * The Regents of the University of California
330Sstevel@tonic-gate  * All Rights Reserved
340Sstevel@tonic-gate  *
350Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
360Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
370Sstevel@tonic-gate  * contributors.
380Sstevel@tonic-gate  */
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
410Sstevel@tonic-gate 
420Sstevel@tonic-gate #include <stdio.h>
430Sstevel@tonic-gate #include <ctype.h>
440Sstevel@tonic-gate #include <setjmp.h>
450Sstevel@tonic-gate #include <utmpx.h>
460Sstevel@tonic-gate #include <pwd.h>
470Sstevel@tonic-gate #include <time.h>
480Sstevel@tonic-gate #include <sys/time.h>
490Sstevel@tonic-gate #include <sys/resource.h>
500Sstevel@tonic-gate #include <sys/param.h>
510Sstevel@tonic-gate #include <sys/types.h>
520Sstevel@tonic-gate #include <sys/errno.h>
530Sstevel@tonic-gate #include <rpc/rpc.h>
540Sstevel@tonic-gate #include <rpc/pmap_clnt.h>
550Sstevel@tonic-gate #include <rpcsvc/mount.h>
560Sstevel@tonic-gate #include <rpcsvc/rwall.h>
570Sstevel@tonic-gate #include <sys/socket.h>
580Sstevel@tonic-gate #include <netinet/in.h>
590Sstevel@tonic-gate #include <netdb.h>
600Sstevel@tonic-gate #include <locale.h>
610Sstevel@tonic-gate #include <sys/syslog.h>
620Sstevel@tonic-gate #include <zone.h>
630Sstevel@tonic-gate #include <signal.h>
640Sstevel@tonic-gate 
650Sstevel@tonic-gate /*
660Sstevel@tonic-gate  *	/usr/etc/shutdown when [messages]
670Sstevel@tonic-gate  *
680Sstevel@tonic-gate  *	allow super users to tell users and remind users
690Sstevel@tonic-gate  *	of iminent shutdown of unix
700Sstevel@tonic-gate  *	and shut it down automatically
710Sstevel@tonic-gate  *	and even reboot or halt the machine if they desire
720Sstevel@tonic-gate  */
730Sstevel@tonic-gate 
740Sstevel@tonic-gate #define	EPATH	"PATH=/usr/ucb:/usr/bin:/usr/sbin:"
750Sstevel@tonic-gate #define	REBOOT	"/usr/sbin/reboot"
760Sstevel@tonic-gate #define	HALT	"/usr/sbin/halt"
770Sstevel@tonic-gate #define	MAXINTS 20
780Sstevel@tonic-gate #define	HOURS	*3600
790Sstevel@tonic-gate #define	MINUTES	*60
800Sstevel@tonic-gate #define	SECONDS
810Sstevel@tonic-gate #define	NLOG		600		/* no of bytes possible for message */
820Sstevel@tonic-gate #define	NOLOGTIME	5 MINUTES
830Sstevel@tonic-gate #define	IGNOREUSER	"sleeper"
840Sstevel@tonic-gate 
850Sstevel@tonic-gate struct hostlist {
860Sstevel@tonic-gate     char *host;
870Sstevel@tonic-gate     struct hostlist *nxt;
880Sstevel@tonic-gate } *hostlist;
890Sstevel@tonic-gate 
900Sstevel@tonic-gate char	hostname[MAXHOSTNAMELEN];
910Sstevel@tonic-gate char	mbuf[BUFSIZ];
920Sstevel@tonic-gate 
930Sstevel@tonic-gate extern	char *malloc();
940Sstevel@tonic-gate 
950Sstevel@tonic-gate extern	char *ctime();
960Sstevel@tonic-gate extern	struct tm *localtime();
970Sstevel@tonic-gate 
980Sstevel@tonic-gate extern	char *strcpy();
990Sstevel@tonic-gate extern	char *strncat();
1000Sstevel@tonic-gate extern	off_t lseek();
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate struct	utmpx *utmpx;
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate int	sint;
1050Sstevel@tonic-gate int	stogo;
1060Sstevel@tonic-gate char	tpath[] =	"/dev/";
1070Sstevel@tonic-gate int	nlflag = 1;		/* nolog yet to be done */
1080Sstevel@tonic-gate int	killflg = 1;
1090Sstevel@tonic-gate int	doreboot = 0;
1100Sstevel@tonic-gate int	halt = 0;
1110Sstevel@tonic-gate int	fast = 0;
1120Sstevel@tonic-gate char	*nosync = NULL;
1130Sstevel@tonic-gate char	nosyncflag[] = "-n";
1140Sstevel@tonic-gate char	term[sizeof tpath + sizeof (utmpx->ut_line)];
1150Sstevel@tonic-gate char	tbuf[BUFSIZ];
1160Sstevel@tonic-gate char    nolog1[] = "\n\nNO LOGINS: System going down at %5.5s\n\n";
1170Sstevel@tonic-gate char	mesg[NLOG+1];
1180Sstevel@tonic-gate #ifdef	DEBUG
1190Sstevel@tonic-gate char	fastboot[] = "fastboot";
1200Sstevel@tonic-gate #else
1210Sstevel@tonic-gate char	fastboot[] = "/fastboot";
1220Sstevel@tonic-gate #endif
1230Sstevel@tonic-gate char    nologin[] = "/etc/nologin";
1240Sstevel@tonic-gate time_t	nowtime;
1250Sstevel@tonic-gate jmp_buf	alarmbuf;
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate struct interval {
1280Sstevel@tonic-gate 	int stogo;
1290Sstevel@tonic-gate 	int sint;
1300Sstevel@tonic-gate } interval[] = {
1310Sstevel@tonic-gate 	4 HOURS,	1 HOURS,
1320Sstevel@tonic-gate 	2 HOURS,	30 MINUTES,
1330Sstevel@tonic-gate 	1 HOURS,	15 MINUTES,
1340Sstevel@tonic-gate 	30 MINUTES,	10 MINUTES,
1350Sstevel@tonic-gate 	15 MINUTES,	5 MINUTES,
1360Sstevel@tonic-gate 	10 MINUTES,	5 MINUTES,
1370Sstevel@tonic-gate 	5 MINUTES,	3 MINUTES,
1380Sstevel@tonic-gate 	2 MINUTES,	1 MINUTES,
1390Sstevel@tonic-gate 	1 MINUTES,	30 SECONDS,
1400Sstevel@tonic-gate 	0 SECONDS,	0 SECONDS
1410Sstevel@tonic-gate };
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate char	*msg1 = "shutdown: '%c' - unknown flag\n";
1440Sstevel@tonic-gate char	*msg2 = "Usage: shutdown [ -krhfn ] shutdowntime [ message ]\n";
1450Sstevel@tonic-gate char	*msg3 = "Usage: shutdown [ -krhfn ] shutdowntime [ message ]";
1460Sstevel@tonic-gate char	*msg4 = "Usage: shutdown [ -krhfn ] shutdowntime [ message ]\n";
1470Sstevel@tonic-gate char	*msg5 = "Usage: shutdown [ -krhfn ] shutdowntime [ message ]";
1480Sstevel@tonic-gate char	*msg6 = "\n\007\007System shutdown time has arrived\007\007\n";
1490Sstevel@tonic-gate char	*msg7 = "but you'll have to do it yourself\n";
1500Sstevel@tonic-gate char	*msg8 = "but you'll have to do it yourself";
1510Sstevel@tonic-gate char	*msg9 = "-l (without fsck's)\n";
1520Sstevel@tonic-gate char	*msg10 = "-l %s\n";
1530Sstevel@tonic-gate char	*msg11 = " (without fsck's)\n";
1540Sstevel@tonic-gate char	*msg12 = "That must be tomorrow\nCan't you wait till then?\n";
1550Sstevel@tonic-gate char	*msg13 = "That must be tomorrow";
1560Sstevel@tonic-gate char	*msg14 = "Can't you wait till then?";
1570Sstevel@tonic-gate char	*msg15 = "\007\007\t*** %sSystem shutdown message from %s@%s ***\r\n\n";
1580Sstevel@tonic-gate char	*msg16 = "System going down at %5.5s\r\n";
1590Sstevel@tonic-gate char	*msg17 = "System going down in %d minute%s\r\n";
1600Sstevel@tonic-gate char	*msg18 = "System going down in %d second%s\r\n";
1610Sstevel@tonic-gate char	*msg19 = "System going down IMMEDIATELY\r\n";
1620Sstevel@tonic-gate char	*msg20 = "Can't get PID for init\n";
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate char *shutter, *getlogin();
1650Sstevel@tonic-gate 
166*523Sbasabi static void timeout(void);
167*523Sbasabi static void gethostlist(void);
168*523Sbasabi static void finish(char *, char *, int);
169*523Sbasabi static void nolog(time_t);
170*523Sbasabi static void rprintf(char *, char *);
171*523Sbasabi static void rwarn(char *, time_t, time_t, char *, int);
172*523Sbasabi static void doitfast(void);
173*523Sbasabi static void warn(FILE *, time_t, time_t, char *, int);
174*523Sbasabi static time_t getsdt(char *);
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate pid_t
get_initpid(void)177*523Sbasabi get_initpid(void)
1780Sstevel@tonic-gate {
1790Sstevel@tonic-gate 	pid_t init_pid;
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	if (zone_getattr(getzoneid(), ZONE_ATTR_INITPID, &init_pid,
1820Sstevel@tonic-gate 	    sizeof (init_pid)) != sizeof (init_pid)) {
1830Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(msg20));
1840Sstevel@tonic-gate 		exit(1);
1850Sstevel@tonic-gate 	}
1860Sstevel@tonic-gate 	return (init_pid);
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate int
main(int argc,char ** argv)1900Sstevel@tonic-gate main(int argc, char **argv)
1910Sstevel@tonic-gate {
1920Sstevel@tonic-gate 	int i;
1930Sstevel@tonic-gate 	char *f;
1940Sstevel@tonic-gate 	char *ts;
1950Sstevel@tonic-gate 	time_t sdt;
1960Sstevel@tonic-gate 	int h, m;
1970Sstevel@tonic-gate 	int first;
1980Sstevel@tonic-gate 	void finish_sig();
1990Sstevel@tonic-gate 	FILE *termf;
2000Sstevel@tonic-gate 	struct passwd *pw, *getpwuid();
2010Sstevel@tonic-gate 	extern char *strcat();
2020Sstevel@tonic-gate 	extern uid_t geteuid();
2030Sstevel@tonic-gate 	struct hostlist *hl;
2040Sstevel@tonic-gate 	char *shutdown_program;
2050Sstevel@tonic-gate 	char *shutdown_action;
2060Sstevel@tonic-gate 	int fd;
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
2110Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
2120Sstevel@tonic-gate #endif
2130Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	audit_shutdown_setup(argc, argv);
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 	shutter = getlogin();
2180Sstevel@tonic-gate 	if (shutter == 0 && (pw = getpwuid(getuid())))
2190Sstevel@tonic-gate 		shutter = pw->pw_name;
2200Sstevel@tonic-gate 	if (shutter == 0)
2210Sstevel@tonic-gate 		shutter = "???";
2220Sstevel@tonic-gate 	(void) gethostname(hostname, sizeof (hostname));
2230Sstevel@tonic-gate 	openlog("shutdown", 0, LOG_AUTH);
2240Sstevel@tonic-gate 	argc--, argv++;
2250Sstevel@tonic-gate 	while (argc > 0 && (f = argv[0], *f++ == '-')) {
2260Sstevel@tonic-gate 		while (i = *f++) {
2270Sstevel@tonic-gate 			switch (i) {
2280Sstevel@tonic-gate 				case 'k':
2290Sstevel@tonic-gate 					killflg = 0;
2300Sstevel@tonic-gate 					continue;
2310Sstevel@tonic-gate 				case 'n':
2320Sstevel@tonic-gate 					nosync = nosyncflag;
2330Sstevel@tonic-gate 					continue;
2340Sstevel@tonic-gate 				case 'f':
2350Sstevel@tonic-gate 					fast = 1;
2360Sstevel@tonic-gate 					continue;
2370Sstevel@tonic-gate 				case 'r':
2380Sstevel@tonic-gate 					doreboot = 1;
2390Sstevel@tonic-gate 					continue;
2400Sstevel@tonic-gate 				case 'h':
2410Sstevel@tonic-gate 					halt = 1;
2420Sstevel@tonic-gate 					continue;
2430Sstevel@tonic-gate 				default:
2440Sstevel@tonic-gate 					(void) fprintf(stderr, gettext(msg1),
2450Sstevel@tonic-gate 									i);
2460Sstevel@tonic-gate 					(void) fprintf(stderr, gettext(msg2));
2470Sstevel@tonic-gate 					finish(gettext(msg3), "", 1);
2480Sstevel@tonic-gate 			}
2490Sstevel@tonic-gate 		}
2500Sstevel@tonic-gate 		argc--, argv++;
2510Sstevel@tonic-gate 	}
2520Sstevel@tonic-gate 	if (argc < 1) {
2530Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(msg4));
2540Sstevel@tonic-gate 		finish(gettext(msg5), "", 1);
2550Sstevel@tonic-gate 	}
2560Sstevel@tonic-gate 	if (doreboot && halt) {
2570Sstevel@tonic-gate 		(void) fprintf(stderr,
2580Sstevel@tonic-gate 		    gettext("shutdown: Incompatible switches '-r' & '-h'\n"));
2590Sstevel@tonic-gate 		finish(gettext("shutdown: Incompatible switches '-r' & '-h'"),
2600Sstevel@tonic-gate 		    "", 1);
2610Sstevel@tonic-gate 	}
2620Sstevel@tonic-gate 	if (fast && (nosync == nosyncflag)) {
2630Sstevel@tonic-gate 		(void) fprintf(stderr,
2640Sstevel@tonic-gate 		    gettext("shutdown: Incompatible switches '-f' & '-n'\n"));
2650Sstevel@tonic-gate 		finish(gettext("shutdown: Incompatible switches '-f' & '-n'"),
2660Sstevel@tonic-gate 		    "", 1);
2670Sstevel@tonic-gate 	}
2680Sstevel@tonic-gate 	if (geteuid()) {
2690Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("shutdown: NOT super-user\n"));
2700Sstevel@tonic-gate 		finish(gettext("shutdown: NOT super-user"), "", 1);
2710Sstevel@tonic-gate 	}
2720Sstevel@tonic-gate 	gethostlist();
2730Sstevel@tonic-gate 	nowtime = time((time_t *)NULL);
2740Sstevel@tonic-gate 	sdt = getsdt(argv[0]);
2750Sstevel@tonic-gate 	argc--, argv++;
2760Sstevel@tonic-gate 	mesg[0] = '\0';
2770Sstevel@tonic-gate 	i = 0;
2780Sstevel@tonic-gate 	while (argc-- > 0) {
2790Sstevel@tonic-gate 		if (i + strlen(*argv) > NLOG)
2800Sstevel@tonic-gate 			break;	/* no more room for the message */
2810Sstevel@tonic-gate 		i += strlen(*argv) + 1;
2820Sstevel@tonic-gate 		(void) strcat(mesg, *argv++);
2830Sstevel@tonic-gate 		(void) strcat(mesg, " ");
2840Sstevel@tonic-gate 	}
2850Sstevel@tonic-gate 	if (i != 0)
2860Sstevel@tonic-gate 		mesg[i - 1] = '\0';	/* remove trailing blank */
2870Sstevel@tonic-gate 	m = ((stogo = sdt - nowtime) + 30)/60;
2880Sstevel@tonic-gate 	h = m/60;
2890Sstevel@tonic-gate 	m %= 60;
2900Sstevel@tonic-gate 	ts = ctime(&sdt);
2910Sstevel@tonic-gate 	(void) printf(gettext("Shutdown at %5.5s (in "), ts+11);
2920Sstevel@tonic-gate 	if (h > 0)
2930Sstevel@tonic-gate 		(void) printf("%d hour%s ", h, h != 1 ? "s" : "");
2940Sstevel@tonic-gate 	(void) printf("%d minute%s) ", m, m != 1 ? "s" : "");
2950Sstevel@tonic-gate #ifndef DEBUG
2960Sstevel@tonic-gate 	(void) signal(SIGHUP, SIG_IGN);
2970Sstevel@tonic-gate 	(void) signal(SIGQUIT, SIG_IGN);
2980Sstevel@tonic-gate 	(void) signal(SIGINT, SIG_IGN);
2990Sstevel@tonic-gate #endif
3000Sstevel@tonic-gate 	(void) signal(SIGTTOU, SIG_IGN);
3010Sstevel@tonic-gate 	(void) signal(SIGINT, finish_sig);
302*523Sbasabi 	(void) signal(SIGALRM, (void(*)())timeout);
3030Sstevel@tonic-gate 	(void) setpriority(PRIO_PROCESS, 0, PRIO_MIN);
3040Sstevel@tonic-gate 	(void) fflush(stdout);
3050Sstevel@tonic-gate #ifndef DEBUG
3060Sstevel@tonic-gate 	if (i = fork()) {
3070Sstevel@tonic-gate 		(void) printf(gettext("[pid %d]\n"), i);
3080Sstevel@tonic-gate 		exit(0);
3090Sstevel@tonic-gate 	}
3100Sstevel@tonic-gate #else
3110Sstevel@tonic-gate 	(void) putc('\n', stdout);
3120Sstevel@tonic-gate #endif
3130Sstevel@tonic-gate 	sint = 1 HOURS;
3140Sstevel@tonic-gate 	f = "";
3150Sstevel@tonic-gate 	first = 1;
3160Sstevel@tonic-gate 	if (doreboot) {
3170Sstevel@tonic-gate 		shutdown_program = REBOOT;
3180Sstevel@tonic-gate 		shutdown_action = "reboot";
3190Sstevel@tonic-gate 	} else if (halt) {
3200Sstevel@tonic-gate 		shutdown_program = HALT;
3210Sstevel@tonic-gate 		shutdown_action = "halt";
3220Sstevel@tonic-gate 	} else {
3230Sstevel@tonic-gate 		shutdown_program = NULL;
3240Sstevel@tonic-gate 		shutdown_action = "shutdown";
3250Sstevel@tonic-gate 	}
3260Sstevel@tonic-gate 	for (;;) {
3270Sstevel@tonic-gate 		for (i = 0; stogo <= interval[i].stogo && interval[i].sint; i++)
3280Sstevel@tonic-gate 			sint = interval[i].sint;
3290Sstevel@tonic-gate 		if (stogo > 0 && (stogo-sint) < interval[i].stogo)
3300Sstevel@tonic-gate 			sint = stogo - interval[i].stogo;
3310Sstevel@tonic-gate 		if (stogo <= NOLOGTIME && nlflag) {
3320Sstevel@tonic-gate 			nlflag = 0;
3330Sstevel@tonic-gate 			nolog(sdt);
3340Sstevel@tonic-gate 		}
3350Sstevel@tonic-gate 		if (sint >= stogo || sint == 0)
3360Sstevel@tonic-gate 			f = "FINAL ";
3370Sstevel@tonic-gate 		nowtime = time((time_t *)NULL);
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 		setutxent();
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 		while ((utmpx = getutxent()) != NULL) {
3420Sstevel@tonic-gate 		    if (utmpx->ut_name[0] &&
3430Sstevel@tonic-gate 			strncmp(utmpx->ut_name, IGNOREUSER,
3440Sstevel@tonic-gate 			    sizeof (utmpx->ut_name))) {
3450Sstevel@tonic-gate 			/*
3460Sstevel@tonic-gate 			 * don't write to pty's unless they're rlogin sessions
3470Sstevel@tonic-gate 			 */
3480Sstevel@tonic-gate 			if (utmpx->ut_type != USER_PROCESS &&
3490Sstevel@tonic-gate 			    utmpx->ut_user[0] != '\0')
3500Sstevel@tonic-gate 				continue;
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 			if (setjmp(alarmbuf))
3530Sstevel@tonic-gate 				continue;
3540Sstevel@tonic-gate 			(void) strcpy(term, tpath);
3550Sstevel@tonic-gate 			(void) strncat(term, utmpx->ut_line,
3560Sstevel@tonic-gate 			    sizeof (utmpx->ut_line));
3570Sstevel@tonic-gate 			(void) alarm(5);
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate 			/* check if device is really a tty */
3600Sstevel@tonic-gate 			if ((fd = open(term, O_WRONLY|O_NOCTTY)) == -1) {
3610Sstevel@tonic-gate 				fprintf(stderr, gettext("Cannot open %s.\n"),
3620Sstevel@tonic-gate 				    term);
3630Sstevel@tonic-gate 				(void) alarm(0);
3640Sstevel@tonic-gate 				continue;
3650Sstevel@tonic-gate 			} else {
3660Sstevel@tonic-gate 			    if (!isatty(fd)) {
3670Sstevel@tonic-gate 				fprintf(stderr,
3680Sstevel@tonic-gate 				    gettext("%.*s in utmpx is not a tty\n"),
3690Sstevel@tonic-gate 				    sizeof (utmpx->ut_line), utmpx->ut_line);
3700Sstevel@tonic-gate 				syslog(LOG_CRIT, "%.*s in utmpx is not "
3710Sstevel@tonic-gate 				    "a tty\n", sizeof (utmpx->ut_line),
3720Sstevel@tonic-gate 				    utmpx->ut_line);
3730Sstevel@tonic-gate 				close(fd);
3740Sstevel@tonic-gate 				(void) alarm(0);
3750Sstevel@tonic-gate 				continue;
3760Sstevel@tonic-gate 			    }
3770Sstevel@tonic-gate 			}
3780Sstevel@tonic-gate 			close(fd);
3790Sstevel@tonic-gate #ifdef DEBUG
3800Sstevel@tonic-gate 			if ((termf = stdout) != NULL)
3810Sstevel@tonic-gate #else
3820Sstevel@tonic-gate 			if ((termf = fopen(term, "w")) != NULL)
3830Sstevel@tonic-gate #endif
3840Sstevel@tonic-gate 			{
3850Sstevel@tonic-gate 				(void) alarm(0);
3860Sstevel@tonic-gate 				setbuf(termf, tbuf);
3870Sstevel@tonic-gate 				(void) fprintf(termf, "\n\r\n");
3880Sstevel@tonic-gate 				warn(termf, sdt, nowtime, f, first);
3890Sstevel@tonic-gate 				(void) alarm(5);
3900Sstevel@tonic-gate #ifdef DEBUG
3910Sstevel@tonic-gate 				(void) fflush(termf);
3920Sstevel@tonic-gate #else
3930Sstevel@tonic-gate 				(void) fclose(termf);
3940Sstevel@tonic-gate #endif
3950Sstevel@tonic-gate 				(void) alarm(0);
3960Sstevel@tonic-gate 			}
3970Sstevel@tonic-gate 		    }
3980Sstevel@tonic-gate 		}  /* while */
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 		endutxent();
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 		for (hl = hostlist; hl != NULL; hl = hl->nxt)
4030Sstevel@tonic-gate 			rwarn(hl->host, sdt, nowtime, f, first);
4040Sstevel@tonic-gate 		if (stogo <= 0) {
4050Sstevel@tonic-gate 			(void) printf(gettext(msg6));
4060Sstevel@tonic-gate 			if (*mesg)
4070Sstevel@tonic-gate 				syslog(LOG_CRIT, "%s by %s: %s",
4080Sstevel@tonic-gate 				    shutdown_action, shutter, mesg);
4090Sstevel@tonic-gate 			else
4100Sstevel@tonic-gate 				syslog(LOG_CRIT, "%s by %s",
4110Sstevel@tonic-gate 				    shutdown_action, shutter);
4120Sstevel@tonic-gate 			sleep(2);
4130Sstevel@tonic-gate 			(void) unlink(nologin);
4140Sstevel@tonic-gate 			if (!killflg) {
4150Sstevel@tonic-gate 				(void) printf(gettext(msg7));
4160Sstevel@tonic-gate 				finish(gettext(msg8), "", 0);
4170Sstevel@tonic-gate 			}
4180Sstevel@tonic-gate 			if (fast)
4190Sstevel@tonic-gate 				doitfast();
4200Sstevel@tonic-gate #ifndef DEBUG
4210Sstevel@tonic-gate 			(void) putenv(EPATH);
4220Sstevel@tonic-gate 			if (shutdown_program != NULL) {
4230Sstevel@tonic-gate 				audit_shutdown_success();
4240Sstevel@tonic-gate 				execlp(shutdown_program, shutdown_program,
4250Sstevel@tonic-gate 				    "-l", nosync, (char *)0);
4260Sstevel@tonic-gate 			} else {
4270Sstevel@tonic-gate 				if (geteuid() == 0) {
4280Sstevel@tonic-gate 					audit_shutdown_success();
4290Sstevel@tonic-gate 					sleep(5);
4300Sstevel@tonic-gate 				}
4310Sstevel@tonic-gate 				if (getzoneid() == GLOBAL_ZONEID) {
4320Sstevel@tonic-gate 					(void) system(
4330Sstevel@tonic-gate 					    "/sbin/bootadm -a update_all");
4340Sstevel@tonic-gate 				}
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 				(void) kill(get_initpid(), SIGINT); /* sync */
4370Sstevel@tonic-gate 				(void) kill(get_initpid(), SIGINT); /* sync */
4380Sstevel@tonic-gate 				sleep(20);
4390Sstevel@tonic-gate 			}
4400Sstevel@tonic-gate #else
4410Sstevel@tonic-gate 			if (shutdown_program) {
4420Sstevel@tonic-gate 				(void) printf("%s ", shutdown_program);
4430Sstevel@tonic-gate 				if (fast)
4440Sstevel@tonic-gate 					(void) printf(gettext(msg9));
4450Sstevel@tonic-gate 				else if (nosync != NULL)
4460Sstevel@tonic-gate 					(void) printf(gettext(msg10), nosync);
4470Sstevel@tonic-gate 				else
4480Sstevel@tonic-gate 					(void) printf(gettext("-l\n"));
4490Sstevel@tonic-gate 			} else {
4500Sstevel@tonic-gate 				(void) printf("/sbin/bootadm -a update_all");
4510Sstevel@tonic-gate 				(void) printf("kill -INT 1");
4520Sstevel@tonic-gate 				if (fast)
4530Sstevel@tonic-gate 					(void) printf(gettext(msg11));
4540Sstevel@tonic-gate 				else
4550Sstevel@tonic-gate 					(void) printf("\n");
4560Sstevel@tonic-gate 			}
4570Sstevel@tonic-gate #endif
4580Sstevel@tonic-gate 			finish("", "", 0);
4590Sstevel@tonic-gate 		}
4600Sstevel@tonic-gate 		stogo = sdt - time((time_t *)NULL);
4610Sstevel@tonic-gate 		if (stogo > 0 && sint > 0)
4620Sstevel@tonic-gate 			sleep((unsigned)(sint < stogo ? sint : stogo));
4630Sstevel@tonic-gate 		stogo -= sint;
4640Sstevel@tonic-gate 		first = 0;
4650Sstevel@tonic-gate 	}
4660Sstevel@tonic-gate 	/* NOTREACHED */
4670Sstevel@tonic-gate }
4680Sstevel@tonic-gate 
469*523Sbasabi static time_t
getsdt(char * s)470*523Sbasabi getsdt(char *s)
4710Sstevel@tonic-gate {
4720Sstevel@tonic-gate 	time_t t, t1, tim;
4730Sstevel@tonic-gate 	char c;
4740Sstevel@tonic-gate 	struct tm *lt;
4750Sstevel@tonic-gate 	int c_count;
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate 	if (strcmp(s, "now") == 0)
4780Sstevel@tonic-gate 		return (nowtime);
4790Sstevel@tonic-gate 	if (*s == '+') {
4800Sstevel@tonic-gate 		++s;
4810Sstevel@tonic-gate 		t = 0;
4820Sstevel@tonic-gate 		for (c_count = 1; ; c_count++) {
4830Sstevel@tonic-gate 			c = *s++;
4840Sstevel@tonic-gate 			if (!isdigit(c)) {
4850Sstevel@tonic-gate 					if (c_count == 1) {
4860Sstevel@tonic-gate 							goto badform;
4870Sstevel@tonic-gate 					} else {
4880Sstevel@tonic-gate 							break;
4890Sstevel@tonic-gate 					}
4900Sstevel@tonic-gate 			}
4910Sstevel@tonic-gate 			t = t * 10 + c - '0';
4920Sstevel@tonic-gate 		}
4930Sstevel@tonic-gate 		if (t <= 0)
4940Sstevel@tonic-gate 			t = 5;
4950Sstevel@tonic-gate 		t *= 60;
4960Sstevel@tonic-gate 		tim = time((time_t *)NULL) + t;
4970Sstevel@tonic-gate 		return (tim);
4980Sstevel@tonic-gate 	}
4990Sstevel@tonic-gate 	t = 0;
5000Sstevel@tonic-gate 	while (strlen(s) > 2 && isdigit(*s))
5010Sstevel@tonic-gate 		t = t * 10 + *s++ - '0';
5020Sstevel@tonic-gate 	if (*s == ':')
5030Sstevel@tonic-gate 		s++;
5040Sstevel@tonic-gate 	if (t > 23)
5050Sstevel@tonic-gate 		goto badform;
5060Sstevel@tonic-gate 	tim = t*60;
5070Sstevel@tonic-gate 	t = 0;
5080Sstevel@tonic-gate 	while (isdigit(*s))
5090Sstevel@tonic-gate 		t = t * 10 + *s++ - '0';
5100Sstevel@tonic-gate 	if (t > 59)
5110Sstevel@tonic-gate 		goto badform;
5120Sstevel@tonic-gate 	tim += t;
5130Sstevel@tonic-gate 	tim *= 60;
5140Sstevel@tonic-gate 	t1 = time((time_t *)NULL);
5150Sstevel@tonic-gate 	lt = localtime(&t1);
5160Sstevel@tonic-gate 	t = lt->tm_sec + lt->tm_min*60 + lt->tm_hour*3600;
5170Sstevel@tonic-gate 	if (tim < t || tim >= (24*3600)) {
5180Sstevel@tonic-gate 		/* before now or after midnight */
5190Sstevel@tonic-gate 		(void) printf(gettext(msg12));
5200Sstevel@tonic-gate 		finish(gettext(msg13), gettext(msg14), 0);
5210Sstevel@tonic-gate 	}
5220Sstevel@tonic-gate 	return (t1 + tim - t);
5230Sstevel@tonic-gate badform:
5240Sstevel@tonic-gate 	(void) printf(gettext("Bad time format\n"));
5250Sstevel@tonic-gate 	finish(gettext("Bad time format"), "", 0);
526*523Sbasabi 	return (0);
527*523Sbasabi 	/* NOTREACHED */
5280Sstevel@tonic-gate }
5290Sstevel@tonic-gate 
530*523Sbasabi static void
warn(FILE * termf,time_t sdt,time_t now,char * type,int first)531*523Sbasabi warn(FILE *termf, time_t sdt, time_t now, char *type, int first)
5320Sstevel@tonic-gate {
5330Sstevel@tonic-gate 	char *ts;
5340Sstevel@tonic-gate 	time_t delay = sdt - now;
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate 	if (delay > 8)
5370Sstevel@tonic-gate 		while (delay % 5)
5380Sstevel@tonic-gate 			delay++;
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate 	(void) fprintf(termf, gettext(msg15), type, shutter, hostname);
5410Sstevel@tonic-gate 
5420Sstevel@tonic-gate 	ts = ctime(&sdt);
5430Sstevel@tonic-gate 	if (delay > 10 MINUTES)
5440Sstevel@tonic-gate 		(void) fprintf(termf, gettext(msg16), ts+11);
5450Sstevel@tonic-gate 	else if (delay > 95 SECONDS) {
5460Sstevel@tonic-gate 		(void) fprintf(termf, gettext(msg17), (delay+30)/60,
5470Sstevel@tonic-gate 						(delay+30)/60 != 1 ? "s" : "");
5480Sstevel@tonic-gate 	} else if (delay > 0) {
5490Sstevel@tonic-gate 		(void) fprintf(termf, gettext(msg18), delay,
5500Sstevel@tonic-gate 							delay != 1 ? "s" : "");
5510Sstevel@tonic-gate 	} else
5520Sstevel@tonic-gate 		(void) fprintf(termf, gettext(msg19));
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 	if (first || sdt - now > 1 MINUTES) {
5550Sstevel@tonic-gate 		if (*mesg)
5560Sstevel@tonic-gate 			(void) fprintf(termf, "\t...%s\r\n", mesg);
5570Sstevel@tonic-gate 	}
5580Sstevel@tonic-gate }
5590Sstevel@tonic-gate 
560*523Sbasabi static void
doitfast(void)561*523Sbasabi doitfast(void)
5620Sstevel@tonic-gate {
5630Sstevel@tonic-gate 	FILE *fastd;
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate 	if ((fastd = fopen(fastboot, "w")) != NULL) {
5660Sstevel@tonic-gate 		(void) putc('\n', fastd);
5670Sstevel@tonic-gate 		(void) fclose(fastd);
5680Sstevel@tonic-gate 	}
5690Sstevel@tonic-gate }
5700Sstevel@tonic-gate 
571*523Sbasabi static void
rwarn(char * host,time_t sdt,time_t now,char * type,int first)572*523Sbasabi rwarn(char *host, time_t sdt, time_t now, char *type, int first)
5730Sstevel@tonic-gate {
5740Sstevel@tonic-gate 	char *ts;
5750Sstevel@tonic-gate 	time_t delay = sdt - now;
5760Sstevel@tonic-gate 	char *bufp;
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate 	if (delay > 8)
5790Sstevel@tonic-gate 		while (delay % 5)
5800Sstevel@tonic-gate 			delay++;
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate 	(void) sprintf(mbuf,
5830Sstevel@tonic-gate 	    "\007\007\t*** %sShutdown message for %s from %s@%s ***\r\n\n",
5840Sstevel@tonic-gate 		type, hostname, shutter, hostname);
5850Sstevel@tonic-gate 	ts = ctime(&sdt);
5860Sstevel@tonic-gate 	bufp = mbuf + strlen(mbuf);
5870Sstevel@tonic-gate 	if (delay > 10 MINUTES) {
5880Sstevel@tonic-gate 		(void) sprintf(bufp, "%s going down at %5.5s\r\n", hostname,
5890Sstevel@tonic-gate 		    ts+11);
5900Sstevel@tonic-gate 	} else if (delay > 95 SECONDS) {
5910Sstevel@tonic-gate 		(void) sprintf(bufp, "%s going down in %d minute%s\r\n",
5920Sstevel@tonic-gate 		    hostname, (delay+30)/60, (delay+30)/60 != 1 ? "s" : "");
5930Sstevel@tonic-gate 	} else if (delay > 0) {
5940Sstevel@tonic-gate 		(void) sprintf(bufp, "%s going down in %d second%s\r\n",
5950Sstevel@tonic-gate 		    hostname, delay, delay != 1 ? "s" : "");
5960Sstevel@tonic-gate 	} else {
5970Sstevel@tonic-gate 		(void) sprintf(bufp, "%s going down IMMEDIATELY\r\n",
5980Sstevel@tonic-gate 		    hostname);
5990Sstevel@tonic-gate 	}
6000Sstevel@tonic-gate 	bufp = mbuf + strlen(mbuf);
6010Sstevel@tonic-gate 	if (first || sdt - now > 1 MINUTES) {
6020Sstevel@tonic-gate 		if (*mesg)
6030Sstevel@tonic-gate 			(void) sprintf(bufp, "\t...%s\r\n", mesg);
6040Sstevel@tonic-gate 	}
6050Sstevel@tonic-gate 	rprintf(host, mbuf);
6060Sstevel@tonic-gate }
6070Sstevel@tonic-gate 
608*523Sbasabi static void
rprintf(char * host,char * bufp)609*523Sbasabi rprintf(char *host, char *bufp)
6100Sstevel@tonic-gate {
6110Sstevel@tonic-gate 	int err;
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate #ifdef DEBUG
6140Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("about to call %s\n"), host);
6150Sstevel@tonic-gate #endif
6160Sstevel@tonic-gate 	if (err = callrpcfast(host, (rpcprog_t)WALLPROG, (rpcvers_t)WALLVERS,
6170Sstevel@tonic-gate 	    (rpcproc_t)WALLPROC_WALL, xdr_dirpath, (char *)&bufp, xdr_void,
6180Sstevel@tonic-gate 	    (char *)NULL)) {
6190Sstevel@tonic-gate #ifdef DEBUG
6200Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("couldn't make rpc call: "));
6210Sstevel@tonic-gate 		clnt_perrno(err);
6220Sstevel@tonic-gate 		(void) fprintf(stderr, "\n");
6230Sstevel@tonic-gate #endif
6240Sstevel@tonic-gate 	    }
6250Sstevel@tonic-gate }
6260Sstevel@tonic-gate 
627*523Sbasabi static void
nolog(time_t sdt)628*523Sbasabi nolog(time_t sdt)
6290Sstevel@tonic-gate {
6300Sstevel@tonic-gate 	FILE *nologf;
6310Sstevel@tonic-gate 
6320Sstevel@tonic-gate 	(void) unlink(nologin);			/* in case linked to std file */
6330Sstevel@tonic-gate 	if ((nologf = fopen(nologin, "w")) != NULL) {
6340Sstevel@tonic-gate 		(void) fprintf(nologf, nolog1, (ctime(&sdt)) + 11);
6350Sstevel@tonic-gate 		if (*mesg)
6360Sstevel@tonic-gate 			(void) fprintf(nologf, "\t%s\n", mesg);
6370Sstevel@tonic-gate 		(void) fclose(nologf);
6380Sstevel@tonic-gate 	}
6390Sstevel@tonic-gate }
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate void
finish_sig(void)642*523Sbasabi finish_sig(void)
6430Sstevel@tonic-gate {
6440Sstevel@tonic-gate 	finish("SIGINT", "", 1);
6450Sstevel@tonic-gate }
6460Sstevel@tonic-gate 
647*523Sbasabi static void
finish(char * s1,char * s2,int exitcode)648*523Sbasabi finish(char *s1, char *s2, int exitcode)
6490Sstevel@tonic-gate {
6500Sstevel@tonic-gate 	(void) signal(SIGINT, SIG_IGN);
6510Sstevel@tonic-gate 	exit(exitcode);
6520Sstevel@tonic-gate }
6530Sstevel@tonic-gate 
654*523Sbasabi static void
timeout(void)655*523Sbasabi timeout(void)
6560Sstevel@tonic-gate {
6570Sstevel@tonic-gate 	(void) signal(SIGALRM, (void(*)())timeout);
6580Sstevel@tonic-gate 	longjmp(alarmbuf, 1);
6590Sstevel@tonic-gate }
6600Sstevel@tonic-gate 
661*523Sbasabi static void
gethostlist(void)662*523Sbasabi gethostlist(void)
6630Sstevel@tonic-gate {
6640Sstevel@tonic-gate 	int s;
6650Sstevel@tonic-gate 	struct mountbody *ml;
6660Sstevel@tonic-gate 	struct hostlist *hl;
6670Sstevel@tonic-gate 	struct sockaddr_in addr;
6680Sstevel@tonic-gate 	CLIENT *cl;
6690Sstevel@tonic-gate 	static struct timeval TIMEOUT = { 25, 0 };
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate 	/*
6720Sstevel@tonic-gate 	 * check for portmapper
6730Sstevel@tonic-gate 	 */
6740Sstevel@tonic-gate 	get_myaddress(&addr);
6750Sstevel@tonic-gate 	s = socket(AF_INET, SOCK_STREAM, 0);
6760Sstevel@tonic-gate 	if (s < 0)
6770Sstevel@tonic-gate 		return;
6780Sstevel@tonic-gate 	if (connect(s, (struct sockaddr *)&addr, sizeof (addr)) < 0)
6790Sstevel@tonic-gate 		return;
6800Sstevel@tonic-gate 	(void) close(s);
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 	/*
6830Sstevel@tonic-gate 	 * First try tcp, then drop back to udp if
6840Sstevel@tonic-gate 	 * tcp is unavailable (an old version of mountd perhaps)
6850Sstevel@tonic-gate 	 * Using tcp is preferred because it can handle
6860Sstevel@tonic-gate 	 * arbitrarily long export lists.
6870Sstevel@tonic-gate 	 */
6880Sstevel@tonic-gate 	cl = clnt_create(hostname, (ulong_t)MOUNTPROG, (ulong_t)MOUNTVERS,
6890Sstevel@tonic-gate 	    "tcp");
6900Sstevel@tonic-gate 	if (cl == NULL) {
6910Sstevel@tonic-gate 		cl = clnt_create(hostname, (ulong_t)MOUNTPROG,
6920Sstevel@tonic-gate 		    (ulong_t)MOUNTVERS, "udp");
6930Sstevel@tonic-gate 		if (cl == NULL) {
6940Sstevel@tonic-gate 			if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED) {
6950Sstevel@tonic-gate 				clnt_pcreateerror("shutdown warning");
6960Sstevel@tonic-gate 			}
6970Sstevel@tonic-gate 			return;
6980Sstevel@tonic-gate 		}
6990Sstevel@tonic-gate 	}
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate 	ml = NULL;
7020Sstevel@tonic-gate 	if (clnt_call(cl, MOUNTPROC_DUMP,
7030Sstevel@tonic-gate 	    xdr_void, 0, xdr_mountlist, (char *)&ml, TIMEOUT) != RPC_SUCCESS) {
7040Sstevel@tonic-gate 		clnt_perror(cl, "shutdown warning");
7050Sstevel@tonic-gate 		return;
7060Sstevel@tonic-gate 	}
7070Sstevel@tonic-gate 	for (; ml != NULL; ml = ml->ml_next) {
7080Sstevel@tonic-gate 		for (hl = hostlist; hl != NULL; hl = hl->nxt)
7090Sstevel@tonic-gate 			if (strcmp(ml->ml_hostname, hl->host) == 0)
7100Sstevel@tonic-gate 				goto again;
7110Sstevel@tonic-gate 		hl = (struct hostlist *)malloc(sizeof (struct hostlist));
7120Sstevel@tonic-gate 		hl->host = ml->ml_hostname;
7130Sstevel@tonic-gate 		hl->nxt = hostlist;
7140Sstevel@tonic-gate 		hostlist = hl;
7150Sstevel@tonic-gate 	    again:;
7160Sstevel@tonic-gate 	}
7170Sstevel@tonic-gate }
7180Sstevel@tonic-gate 
7190Sstevel@tonic-gate /*
7200Sstevel@tonic-gate  * Don't want to wait for usual portmapper timeout you get with
7210Sstevel@tonic-gate  * callrpc or clnt_call, so use rmtcall instead.  Use timeout
7220Sstevel@tonic-gate  * of 8 secs, based on the per try timeout of 3 secs for rmtcall
7230Sstevel@tonic-gate  */
724*523Sbasabi int
callrpcfast(char * host,rpcprog_t prognum,rpcprog_t versnum,rpcprog_t procnum,xdrproc_t inproc,xdrproc_t outproc,char * in,char * out)725*523Sbasabi callrpcfast(char *host, rpcprog_t prognum, rpcprog_t versnum,
726*523Sbasabi     rpcprog_t procnum, xdrproc_t inproc, xdrproc_t outproc,
727*523Sbasabi     char *in, char *out)
7280Sstevel@tonic-gate {
7290Sstevel@tonic-gate 	struct sockaddr_in server_addr;
7300Sstevel@tonic-gate 	struct hostent *hp;
7310Sstevel@tonic-gate 	struct timeval rpctimeout;
7320Sstevel@tonic-gate 	rpcport_t port;
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 	if ((hp = gethostbyname(host)) == NULL)
7350Sstevel@tonic-gate 		return ((int)RPC_UNKNOWNHOST);
7360Sstevel@tonic-gate 	bcopy(hp->h_addr, (char *)&server_addr.sin_addr, hp->h_length);
7370Sstevel@tonic-gate 	server_addr.sin_family = AF_INET;
7380Sstevel@tonic-gate 	server_addr.sin_port =  0;
7390Sstevel@tonic-gate 	rpctimeout.tv_sec = 8;
7400Sstevel@tonic-gate 	rpctimeout.tv_usec = 0;
7410Sstevel@tonic-gate 	return ((int)pmap_rmtcall(&server_addr, prognum, versnum, procnum,
7420Sstevel@tonic-gate 	    inproc, in, outproc, out, rpctimeout, &port));
7430Sstevel@tonic-gate }
744