xref: /titanic_50/usr/src/cmd/rexd/rpc.rexd.c (revision 16ab6e0b56ccd36f9a870ff0b87e64c55599a6f0)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * rexd - a remote execution daemon based on SUN Remote Procedure Calls
247c478bd9Sstevel@tonic-gate  *
25*16ab6e0bSsm26363  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
267c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include <errno.h>
327c478bd9Sstevel@tonic-gate #include <netdb.h>
337c478bd9Sstevel@tonic-gate #include <signal.h>
347c478bd9Sstevel@tonic-gate #include <stdio.h>
357c478bd9Sstevel@tonic-gate #include <stdlib.h>
367c478bd9Sstevel@tonic-gate #include <string.h>
377c478bd9Sstevel@tonic-gate #include <unistd.h>
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #include <netinet/in.h>
407c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
417c478bd9Sstevel@tonic-gate #include <rpc/svc_soc.h>
427c478bd9Sstevel@tonic-gate #include <rpc/key_prot.h>
437c478bd9Sstevel@tonic-gate #include <sys/fcntl.h>
447c478bd9Sstevel@tonic-gate #include <sys/ioctl.h>
457c478bd9Sstevel@tonic-gate #include <sys/param.h>
467c478bd9Sstevel@tonic-gate #include <sys/socket.h>
477c478bd9Sstevel@tonic-gate #include <sys/sockio.h>
487c478bd9Sstevel@tonic-gate #include <sys/mntent.h>
497c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
507c478bd9Sstevel@tonic-gate #include <sys/stat.h>
517c478bd9Sstevel@tonic-gate #include <sys/time.h>
527c478bd9Sstevel@tonic-gate #include <wait.h>
537c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate #include <sys/ttold.h>
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate #include "rex.h"
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate #include <security/pam_appl.h>
607c478bd9Sstevel@tonic-gate #include <stropts.h>
617c478bd9Sstevel@tonic-gate #include <sys/stream.h>
627c478bd9Sstevel@tonic-gate /*	#include <sys/termios.h>	XXX	*/
637c478bd9Sstevel@tonic-gate #include <sys/ttcompat.h>
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate #include <bsm/audit.h>
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate /* #define	stderr	stdout */		/* XXX		*/
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate #define	ListnerTimeout 300	/* seconds listner stays alive */
707c478bd9Sstevel@tonic-gate #define	WaitLimit 10		/* seconds to wait after io is closed */
717c478bd9Sstevel@tonic-gate #define	MOUNTED "/etc/mnttab"
727c478bd9Sstevel@tonic-gate #define	TempDir "/tmp_rex"	/* directory to hold temp mounts */
737c478bd9Sstevel@tonic-gate static	char TempName[] = "/tmp_rex/rexdXXXXXX";
747c478bd9Sstevel@tonic-gate 				/* name template for temp mount points */
757c478bd9Sstevel@tonic-gate #define	TempMatch 13		/* unique prefix of above */
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate SVCXPRT	*ListnerTransp;		/* non-null means still a listner */
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate static	char **Argv;		/* saved argument vector (for ps) */
807c478bd9Sstevel@tonic-gate static char *LastArgv;		/* saved end-of-argument vector */
817c478bd9Sstevel@tonic-gate int OutputSocket;		/* socket for stop/cont notification */
827c478bd9Sstevel@tonic-gate int MySocket;			/* transport socket */
837c478bd9Sstevel@tonic-gate int HasHelper = 0;		/* must kill helpers (interactive mode) */
847c478bd9Sstevel@tonic-gate int DesOnly  =  0;		/* unix credentials too weak */
857c478bd9Sstevel@tonic-gate int confd;			/* console fd */
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate int	Debug = 0;
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate pam_handle_t *pamh;		/* PAM handle */
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate time_t time_now;
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate extern int Master;		/* half of the pty */
947c478bd9Sstevel@tonic-gate extern char **environ;
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate int child = 0;			/* pid of the executed process */
977c478bd9Sstevel@tonic-gate int ChildStatus = 0;		/* saved return status of child */
987c478bd9Sstevel@tonic-gate int ChildDied = 0;		/* true when above is valid */
997c478bd9Sstevel@tonic-gate char nfsdir[MAXPATHLEN];	/* file system we mounted */
1007c478bd9Sstevel@tonic-gate char *tmpdir;			/* where above is mounted, NULL if none */
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate extern	void	rex_cleanup(void);
1037c478bd9Sstevel@tonic-gate extern	int	ValidUser(char *host, uid_t uid, gid_t gid,
1047c478bd9Sstevel@tonic-gate 			char *error, char *shell,
1057c478bd9Sstevel@tonic-gate 			char *dir, struct rex_start *rst);
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate extern void audit_rexd_fail(char *, char *, char *, uid_t, gid_t,
1087c478bd9Sstevel@tonic-gate 				char *, char **);
1097c478bd9Sstevel@tonic-gate extern void audit_rexd_success(char *, char *, uid_t, gid_t,
1107c478bd9Sstevel@tonic-gate 				char *, char **);
1117c478bd9Sstevel@tonic-gate extern void audit_rexd_setup();
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate extern int audit_settid(int);
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate /* process rex requests */
1167c478bd9Sstevel@tonic-gate void		dorex(struct svc_req *rqstp, SVCXPRT *transp);
1177c478bd9Sstevel@tonic-gate void		ListnerTimer(int);		/* destroy listener	*/
1187c478bd9Sstevel@tonic-gate void		CatchChild(int);		/* handle child signals	*/
1197c478bd9Sstevel@tonic-gate void		oob(int);			/* out of band signals	*/
1207c478bd9Sstevel@tonic-gate void		sigwinch(int);	/* window change signals -- dummy */
1217c478bd9Sstevel@tonic-gate FILE		*setmntent(char *fname, char *flag);
1227c478bd9Sstevel@tonic-gate extern void	HelperRead(pollfd_t *fdp, int, int *);
1237c478bd9Sstevel@tonic-gate 
124*16ab6e0bSsm26363 int
main(int argc,char ** argv)125*16ab6e0bSsm26363 main(int argc, char **argv)
1267c478bd9Sstevel@tonic-gate {
1277c478bd9Sstevel@tonic-gate 	/*
1287c478bd9Sstevel@tonic-gate 	 * the server is a typical RPC daemon, except that we only
1297c478bd9Sstevel@tonic-gate 	 * accept TCP connections.
1307c478bd9Sstevel@tonic-gate 	 */
1317c478bd9Sstevel@tonic-gate 	int pollretval;
1327c478bd9Sstevel@tonic-gate 	int npollfds = 0;
1337c478bd9Sstevel@tonic-gate 	pollfd_t *pollset = NULL;
1347c478bd9Sstevel@tonic-gate 	struct sockaddr_in addr;
1357c478bd9Sstevel@tonic-gate 	int maxrecsz = RPC_MAXDATASIZE;
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	audit_rexd_setup();	/* BSM */
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	/*
1407c478bd9Sstevel@tonic-gate 	 * Remember the start and extent of argv for setproctitle().
1417c478bd9Sstevel@tonic-gate 	 * Open the console for error printouts, but don't let it be
1427c478bd9Sstevel@tonic-gate 	 * our controlling terminal.
1437c478bd9Sstevel@tonic-gate 	 */
1447c478bd9Sstevel@tonic-gate 	if (argc > 1) {
1457c478bd9Sstevel@tonic-gate 		if (strcmp("-s", argv[1]) == 0)
1467c478bd9Sstevel@tonic-gate 			DesOnly = 1;
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 		if (strcmp("-d", argv[1]) == 0)
1497c478bd9Sstevel@tonic-gate 			Debug = 1;
1507c478bd9Sstevel@tonic-gate 	}
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 	if (argc > 2) {
1537c478bd9Sstevel@tonic-gate 		if (strcmp("-s", argv[2]) == 0)
1547c478bd9Sstevel@tonic-gate 			DesOnly = 1;
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 		if (strcmp("-d", argv[2]) == 0)
1577c478bd9Sstevel@tonic-gate 			Debug = 1;
1587c478bd9Sstevel@tonic-gate 	}
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	/*
1617c478bd9Sstevel@tonic-gate 	 * argv start and extent for setproctitle()
1627c478bd9Sstevel@tonic-gate 	 */
1637c478bd9Sstevel@tonic-gate 	Argv = argv;
1647c478bd9Sstevel@tonic-gate 	if (argc > 0)
1657c478bd9Sstevel@tonic-gate 		LastArgv = argv[argc-1] + strlen(argv[argc-1]);
1667c478bd9Sstevel@tonic-gate 	else
1677c478bd9Sstevel@tonic-gate 		LastArgv = NULL;
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	/*
1707c478bd9Sstevel@tonic-gate 	 * console open for errors w/o being the controlling terminal
1717c478bd9Sstevel@tonic-gate 	 */
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	if ((confd = open("/dev/console", 1)) > 0) {
1747c478bd9Sstevel@tonic-gate 		close(1);
1757c478bd9Sstevel@tonic-gate 		close(2);
1767c478bd9Sstevel@tonic-gate 		confd = dup2(confd, 1); /* console fd copied to stdout */
1777c478bd9Sstevel@tonic-gate 		dup(1);		/* console fd copied to stderr */
1787c478bd9Sstevel@tonic-gate 	}
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	setsid();		/* get rid of controlling terminal	*/
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	/*
1837c478bd9Sstevel@tonic-gate 	 * setup signals
1847c478bd9Sstevel@tonic-gate 	 */
1857c478bd9Sstevel@tonic-gate 	sigset(SIGCHLD, CatchChild);
1867c478bd9Sstevel@tonic-gate 	sigset(SIGPIPE, SIG_IGN);
1877c478bd9Sstevel@tonic-gate 	sigset(SIGALRM, ListnerTimer);
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	/*
1907c478bd9Sstevel@tonic-gate 	 * Enable non-blocking mode and maximum record size checks for
1917c478bd9Sstevel@tonic-gate 	 * connection oriented transports.
1927c478bd9Sstevel@tonic-gate 	 */
1937c478bd9Sstevel@tonic-gate 	if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrecsz)) {
1947c478bd9Sstevel@tonic-gate 		fprintf(stderr, "rexd: unable to set RPC max record size\n");
1957c478bd9Sstevel@tonic-gate 	}
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	/*
1987c478bd9Sstevel@tonic-gate 	 * determine how we started to see if we are already in the background
1997c478bd9Sstevel@tonic-gate 	 * and get appropriately registered with rpcbind (portmapper)
2007c478bd9Sstevel@tonic-gate 	 */
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	if (isfrominetd(0)) {
2037c478bd9Sstevel@tonic-gate 		/*
2047c478bd9Sstevel@tonic-gate 		 * Started from inetd: use fd 0 as socket
2057c478bd9Sstevel@tonic-gate 		 */
2067c478bd9Sstevel@tonic-gate 		if (Debug)
2077c478bd9Sstevel@tonic-gate 			printf("Started from inetd\n");
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 		if ((ListnerTransp = svctcp_create(0, 0, 0)) == NULL) {
2107c478bd9Sstevel@tonic-gate 			fprintf(stderr, "rexd: svctcp_create error\n");
2117c478bd9Sstevel@tonic-gate 			exit(1);
2127c478bd9Sstevel@tonic-gate 		}
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 		if (!svc_register(ListnerTransp, REXPROG, REXVERS, dorex, 0)) {
2157c478bd9Sstevel@tonic-gate 			fprintf(stderr, "rexd: service register error\n");
2167c478bd9Sstevel@tonic-gate 			exit(1);
2177c478bd9Sstevel@tonic-gate 		}
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 		alarm(ListnerTimeout);
2207c478bd9Sstevel@tonic-gate 	} else {
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 		if (Debug)
2237c478bd9Sstevel@tonic-gate 			printf("started from shell\n");
2247c478bd9Sstevel@tonic-gate 		if (!Debug) {
2257c478bd9Sstevel@tonic-gate 			/*
2267c478bd9Sstevel@tonic-gate 			 * Started from shell, background
2277c478bd9Sstevel@tonic-gate 			 * thyself and run forever.
2287c478bd9Sstevel@tonic-gate 			 */
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 			int pid = fork();
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 			if (pid < 0) { /* fork error	*/
2337c478bd9Sstevel@tonic-gate 				perror("rpc.rexd: can't fork");
2347c478bd9Sstevel@tonic-gate 				exit(1);
2357c478bd9Sstevel@tonic-gate 			}
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 			if (pid) { /* parent terminates	*/
2387c478bd9Sstevel@tonic-gate 				exit(0);
2397c478bd9Sstevel@tonic-gate 			}
2407c478bd9Sstevel@tonic-gate 		}
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 		/*
2437c478bd9Sstevel@tonic-gate 		 * child process continues to establish connections
2447c478bd9Sstevel@tonic-gate 		 */
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 		if (Debug)
2477c478bd9Sstevel@tonic-gate 			printf("before svctcp_create() call\n");
2487c478bd9Sstevel@tonic-gate 		if ((ListnerTransp = svctcp_create(RPC_ANYSOCK, 0, 0))
2497c478bd9Sstevel@tonic-gate 		    == NULL) {
2507c478bd9Sstevel@tonic-gate 			fprintf(stderr, "rexd: svctcp_create: error\n");
2517c478bd9Sstevel@tonic-gate 			exit(1);
2527c478bd9Sstevel@tonic-gate 		}
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 		pmap_unset(REXPROG, REXVERS);
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 		if (!svc_register(ListnerTransp, REXPROG, REXVERS,
2577c478bd9Sstevel@tonic-gate 				dorex, IPPROTO_TCP)) {
2587c478bd9Sstevel@tonic-gate 			fprintf(stderr, "rexd: service rpc register: error\n");
2597c478bd9Sstevel@tonic-gate 			exit(1);
2607c478bd9Sstevel@tonic-gate 		}
2617c478bd9Sstevel@tonic-gate 	}
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 	/*
2647c478bd9Sstevel@tonic-gate 	 * Create a private temporary directory to hold rexd's mounts
2657c478bd9Sstevel@tonic-gate 	 */
2667c478bd9Sstevel@tonic-gate 	if (mkdir(TempDir, 0777) < 0)
2677c478bd9Sstevel@tonic-gate 		if (errno != EEXIST) {
2687c478bd9Sstevel@tonic-gate 			perror("rexd: mkdir");
2697c478bd9Sstevel@tonic-gate 			fprintf(stderr,
2707c478bd9Sstevel@tonic-gate 				"rexd: can't create temp directory %s\n",
2717c478bd9Sstevel@tonic-gate 				TempDir);
2727c478bd9Sstevel@tonic-gate 			exit(1);
2737c478bd9Sstevel@tonic-gate 		}
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	if (Debug)
2767c478bd9Sstevel@tonic-gate 		printf("created temporary directory\n");
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	/*
2807c478bd9Sstevel@tonic-gate 	 * normally we would call svc_run() at this point, but we need to be
2817c478bd9Sstevel@tonic-gate 	 * informed of when the RPC connection is broken, in case the other
2827c478bd9Sstevel@tonic-gate 	 * side crashes.
2837c478bd9Sstevel@tonic-gate 	 */
2847c478bd9Sstevel@tonic-gate 	while (TRUE) {
2857c478bd9Sstevel@tonic-gate 		if (Debug)
2867c478bd9Sstevel@tonic-gate 			printf("Entered While loop\n");
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 		if (MySocket) {
2897c478bd9Sstevel@tonic-gate 			int i;
2907c478bd9Sstevel@tonic-gate 			char *waste;
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 			/* try to find MySocket in the pollfd set */
2937c478bd9Sstevel@tonic-gate 			for (i = 0; i < svc_max_pollfd; i++)
2947c478bd9Sstevel@tonic-gate 				if (svc_pollfd[i].fd == MySocket)
2957c478bd9Sstevel@tonic-gate 					break;
2967c478bd9Sstevel@tonic-gate 			/*
2977c478bd9Sstevel@tonic-gate 			 * If we didn't find it, the connection died for
2987c478bd9Sstevel@tonic-gate 			 * some random reason, e.g. client crashed.
2997c478bd9Sstevel@tonic-gate 			 */
3007c478bd9Sstevel@tonic-gate 			if (i == svc_max_pollfd) {
3017c478bd9Sstevel@tonic-gate 				if (Debug)
3027c478bd9Sstevel@tonic-gate 					printf("Connection died\n");
3037c478bd9Sstevel@tonic-gate 				(void) rex_wait(&waste);
3047c478bd9Sstevel@tonic-gate 				rex_cleanup();
3057c478bd9Sstevel@tonic-gate 				exit(1);
3067c478bd9Sstevel@tonic-gate 			}
3077c478bd9Sstevel@tonic-gate 		}
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 		/*
3107c478bd9Sstevel@tonic-gate 		 * Get existing array of pollfd's, should really compress
3117c478bd9Sstevel@tonic-gate 		 * this but it shouldn't get very large (or sparse).
3127c478bd9Sstevel@tonic-gate 		 */
3137c478bd9Sstevel@tonic-gate 		if (npollfds != svc_max_pollfd) {
3147c478bd9Sstevel@tonic-gate 			pollset = realloc(pollset,
3157c478bd9Sstevel@tonic-gate 					sizeof (pollfd_t) * svc_max_pollfd);
3167c478bd9Sstevel@tonic-gate 			npollfds = svc_max_pollfd;
3177c478bd9Sstevel@tonic-gate 		}
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 		if (npollfds == 0)
3207c478bd9Sstevel@tonic-gate 			break;	/* None waiting, hence return */
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 		(void) memcpy(pollset, svc_pollfd,
3237c478bd9Sstevel@tonic-gate 					sizeof (pollfd_t) * svc_max_pollfd);
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate 		if (Debug)
3267c478bd9Sstevel@tonic-gate 			printf("Before select readfds\n");
3277c478bd9Sstevel@tonic-gate 		switch (pollretval = poll(pollset, npollfds, -1)) {
3287c478bd9Sstevel@tonic-gate 		case -1:
3297c478bd9Sstevel@tonic-gate 			if (Debug)
3307c478bd9Sstevel@tonic-gate 				printf("Poll failed\n");
3317c478bd9Sstevel@tonic-gate 			if (errno == EINTR)
3327c478bd9Sstevel@tonic-gate 				continue;
3337c478bd9Sstevel@tonic-gate 			perror("rexd: poll failed");
3347c478bd9Sstevel@tonic-gate 			exit(1);
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 		case 0:
3377c478bd9Sstevel@tonic-gate 			if (Debug)
3387c478bd9Sstevel@tonic-gate 				printf("Poll returned zero\n");
3397c478bd9Sstevel@tonic-gate 			fprintf(stderr, "rexd: poll returned zero\r\n");
3407c478bd9Sstevel@tonic-gate 			continue;
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 		default:
3437c478bd9Sstevel@tonic-gate 			if (Debug)
3447c478bd9Sstevel@tonic-gate 				printf("Before HelperRead\n");
3457c478bd9Sstevel@tonic-gate 			if (HasHelper)
3467c478bd9Sstevel@tonic-gate 				HelperRead(pollset, npollfds, &pollretval);
3477c478bd9Sstevel@tonic-gate 			if (Debug)
3487c478bd9Sstevel@tonic-gate 				printf("After HelperRead\n");
3497c478bd9Sstevel@tonic-gate 			time_now = time((time_t *)0);
3507c478bd9Sstevel@tonic-gate 			if (Debug)
3517c478bd9Sstevel@tonic-gate 				printf("before svc_getreq_poll\n");
3527c478bd9Sstevel@tonic-gate 			svc_getreq_poll(pollset, pollretval);
3537c478bd9Sstevel@tonic-gate 		}
3547c478bd9Sstevel@tonic-gate 		if (Debug)
3557c478bd9Sstevel@tonic-gate 			printf("After switch\n");
3567c478bd9Sstevel@tonic-gate 	}
357*16ab6e0bSsm26363 	return (0);
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate /*
3617c478bd9Sstevel@tonic-gate  * This function gets called after the listner has timed out waiting
3627c478bd9Sstevel@tonic-gate  * for any new connections coming in.
3637c478bd9Sstevel@tonic-gate  */
3647c478bd9Sstevel@tonic-gate void
ListnerTimer(int junk)3657c478bd9Sstevel@tonic-gate ListnerTimer(int junk)
3667c478bd9Sstevel@tonic-gate {
3677c478bd9Sstevel@tonic-gate 	/*
3687c478bd9Sstevel@tonic-gate 	 * svc_destroy not done here due to problems with M_ERROR
3697c478bd9Sstevel@tonic-gate 	 * on stream head and inetd
3707c478bd9Sstevel@tonic-gate 	 */
3717c478bd9Sstevel@tonic-gate 	exit(0);
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate struct authunix_parms
authdes_to_unix(des_cred)3757c478bd9Sstevel@tonic-gate *authdes_to_unix(des_cred)
3767c478bd9Sstevel@tonic-gate struct authdes_cred *des_cred;
3777c478bd9Sstevel@tonic-gate {
3787c478bd9Sstevel@tonic-gate 	struct authunix_parms *unix_cred;
3797c478bd9Sstevel@tonic-gate 	static struct authunix_parms au;
3807c478bd9Sstevel@tonic-gate 	static uint_t    stuff[32];
3817c478bd9Sstevel@tonic-gate 	char publickey[HEXKEYBYTES+1];
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	unix_cred = &au;
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	unix_cred->aup_gids = (gid_t *)stuff;
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	unix_cred->aup_machname = "";
3897c478bd9Sstevel@tonic-gate 	if (getpublickey(des_cred->adc_fullname.name, publickey) == 0)
3907c478bd9Sstevel@tonic-gate 		return (NULL);
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	if (netname2user(des_cred->adc_fullname.name,
3937c478bd9Sstevel@tonic-gate 			&(unix_cred->aup_uid),
3947c478bd9Sstevel@tonic-gate 			&(unix_cred->aup_gid),
3957c478bd9Sstevel@tonic-gate 			(int *)&(unix_cred->aup_len),
3967c478bd9Sstevel@tonic-gate 			unix_cred->aup_gids) == FALSE)
3977c478bd9Sstevel@tonic-gate 		return (NULL);
3987c478bd9Sstevel@tonic-gate 	else
3997c478bd9Sstevel@tonic-gate 		return (unix_cred);
4007c478bd9Sstevel@tonic-gate }
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate /*
4037c478bd9Sstevel@tonic-gate  * dorex - handle one of the rex procedure calls, dispatching to the
4047c478bd9Sstevel@tonic-gate  *	correct function.
4057c478bd9Sstevel@tonic-gate  */
4067c478bd9Sstevel@tonic-gate void
dorex(rqstp,transp)4077c478bd9Sstevel@tonic-gate dorex(rqstp, transp)
4087c478bd9Sstevel@tonic-gate struct svc_req *rqstp;
4097c478bd9Sstevel@tonic-gate SVCXPRT *transp;
4107c478bd9Sstevel@tonic-gate {
4117c478bd9Sstevel@tonic-gate 	struct rex_start *rst;
4127c478bd9Sstevel@tonic-gate 	struct rex_result result;
4137c478bd9Sstevel@tonic-gate 	struct authunix_parms *unix_cred;
4147c478bd9Sstevel@tonic-gate 	struct sockaddr_in *calleraddr;
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 	if (ListnerTransp) {
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 		/*
4207c478bd9Sstevel@tonic-gate 		 * First call - fork a server for this connection
4217c478bd9Sstevel@tonic-gate 		 */
4227c478bd9Sstevel@tonic-gate 		int fd, pid, count;
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 		for (count = 0; (pid = fork()) < 0; count++) {
4257c478bd9Sstevel@tonic-gate 			if (count > 4)
4267c478bd9Sstevel@tonic-gate 				{
4277c478bd9Sstevel@tonic-gate 					perror("rexd: cannot fork");
4287c478bd9Sstevel@tonic-gate 					break;
4297c478bd9Sstevel@tonic-gate 				}
4307c478bd9Sstevel@tonic-gate 			sleep(5);
4317c478bd9Sstevel@tonic-gate 		}
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 		if (pid != 0) {
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 			/*
4367c478bd9Sstevel@tonic-gate 			 * Parent - return to service loop to accept further
4377c478bd9Sstevel@tonic-gate 			 * connections.
4387c478bd9Sstevel@tonic-gate 			 */
4397c478bd9Sstevel@tonic-gate 			alarm(ListnerTimeout);
4407c478bd9Sstevel@tonic-gate 			svc_destroy(transp);
4417c478bd9Sstevel@tonic-gate 			return;
4427c478bd9Sstevel@tonic-gate 		}
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 		/*
4457c478bd9Sstevel@tonic-gate 		 * child - close listner transport to avoid confusion
4467c478bd9Sstevel@tonic-gate 		 * Also need to close all other service transports
4477c478bd9Sstevel@tonic-gate 		 * besides the one we are interested in.
4487c478bd9Sstevel@tonic-gate 		 * Save ours so that we know when it goes away.
4497c478bd9Sstevel@tonic-gate 		 */
4507c478bd9Sstevel@tonic-gate 		if (Debug)
4517c478bd9Sstevel@tonic-gate 			printf("child server process\n");
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 		alarm(0);
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 		if (transp != ListnerTransp) {
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 			close(ListnerTransp->xp_sock);
4607c478bd9Sstevel@tonic-gate 			xprt_unregister(ListnerTransp);
4617c478bd9Sstevel@tonic-gate 		}
4627c478bd9Sstevel@tonic-gate 		ListnerTransp = NULL;
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 		MySocket = transp->xp_sock;
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 		/* temp workaround to restore sanity in TLI state */
4677c478bd9Sstevel@tonic-gate 		if (transp->xp_sock != 0)
4687c478bd9Sstevel@tonic-gate 			t_close(0); /* opened in parent possibly by inetd */
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 		/*
4717c478bd9Sstevel@tonic-gate 		 * XXX: svc_pollfd[] is a read-only structure. This
4727c478bd9Sstevel@tonic-gate 		 * appears to be dead code, which should be removed.
4737c478bd9Sstevel@tonic-gate 		 * However, until it can be clearly understood, leaving
4747c478bd9Sstevel@tonic-gate 		 * in.
4757c478bd9Sstevel@tonic-gate 		 */
4767c478bd9Sstevel@tonic-gate 		for (fd = 1; fd < svc_max_pollfd; fd++) {
4777c478bd9Sstevel@tonic-gate 			if (fd != transp->xp_sock && svc_pollfd[fd].fd == fd) {
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 				printf("close of fd %d\n", fd);
4807c478bd9Sstevel@tonic-gate 				close(fd);
4817c478bd9Sstevel@tonic-gate 				svc_pollfd[fd].fd = -1;
4827c478bd9Sstevel@tonic-gate 				svc_pollfd[fd].events = 0;
4837c478bd9Sstevel@tonic-gate 				svc_pollfd[fd].revents = 0;
4847c478bd9Sstevel@tonic-gate 			}
4857c478bd9Sstevel@tonic-gate 		}
4867c478bd9Sstevel@tonic-gate 	}
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	/*
4897c478bd9Sstevel@tonic-gate 	 * execute the requested prodcedure
4907c478bd9Sstevel@tonic-gate 	 */
4917c478bd9Sstevel@tonic-gate 	switch (rqstp->rq_proc)	{
4927c478bd9Sstevel@tonic-gate 	case NULLPROC:
4937c478bd9Sstevel@tonic-gate 		if (Debug)	/*	XXX	*/
4947c478bd9Sstevel@tonic-gate 			printf("dorex: call to NULLPROC\n");
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 		if (svc_sendreply(transp, xdr_void, 0) == FALSE) {
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 			fprintf(stderr, "rexd: nullproc err");
4997c478bd9Sstevel@tonic-gate 			exit(1);
5007c478bd9Sstevel@tonic-gate 		}
5017c478bd9Sstevel@tonic-gate 		return;
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 	case REXPROC_START:
5047c478bd9Sstevel@tonic-gate 		if (Debug)	/*	XXX	*/
5057c478bd9Sstevel@tonic-gate 			printf("dorex: call to REXPROC_START\n");
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 		rst = (struct rex_start *)malloc(sizeof (struct rex_start));
5097c478bd9Sstevel@tonic-gate 		memset((char *)rst, '\0', sizeof (*rst));
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 		if (svc_getargs(transp, xdr_rex_start, (char *)rst) == FALSE) {
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 			svcerr_decode(transp);
5147c478bd9Sstevel@tonic-gate 			exit(1);
5157c478bd9Sstevel@tonic-gate 		}
5167c478bd9Sstevel@tonic-gate 		if (Debug)
5177c478bd9Sstevel@tonic-gate 			printf("svc_getargs: suceeded\n");
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 		if (rqstp->rq_cred.oa_flavor == AUTH_DES) {
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 			unix_cred = authdes_to_unix(rqstp->rq_clntcred);
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 		} else if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 			if (DesOnly) {
5267c478bd9Sstevel@tonic-gate 				fprintf(stderr,
5277c478bd9Sstevel@tonic-gate 					"Unix too weak auth(DesOnly)!\n");
5287c478bd9Sstevel@tonic-gate 				unix_cred = NULL;
5297c478bd9Sstevel@tonic-gate 			} else
5307c478bd9Sstevel@tonic-gate 				unix_cred =
5317c478bd9Sstevel@tonic-gate 				(struct authunix_parms *)rqstp->rq_clntcred;
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 		} else {
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Unknown weak auth!\n");
5367c478bd9Sstevel@tonic-gate 			svcerr_weakauth(transp);
5377c478bd9Sstevel@tonic-gate 			sleep(5);
5387c478bd9Sstevel@tonic-gate 			exit(1);
5397c478bd9Sstevel@tonic-gate 		}
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 		if (unix_cred == NULL) {
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 			svcerr_weakauth(transp);
5447c478bd9Sstevel@tonic-gate 			sleep(5);
5457c478bd9Sstevel@tonic-gate 			exit(1);
5467c478bd9Sstevel@tonic-gate 		}
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 		calleraddr = svc_getcaller(transp);
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 		result.rlt_stat = (int)rex_startup(rst,
5517c478bd9Sstevel@tonic-gate 						unix_cred,
5527c478bd9Sstevel@tonic-gate 						(char **)&result.rlt_message,
5537c478bd9Sstevel@tonic-gate 						calleraddr);
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 		if (Debug)
5567c478bd9Sstevel@tonic-gate 			printf("rex_startup: completed\n");
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 		if (svc_sendreply(transp, xdr_rex_result, (char *)&result)
5597c478bd9Sstevel@tonic-gate 		    == FALSE) {
5607c478bd9Sstevel@tonic-gate 			fprintf(stderr, "rexd: reply failed\n");
5617c478bd9Sstevel@tonic-gate 			rex_cleanup();
5627c478bd9Sstevel@tonic-gate 			exit(1);
5637c478bd9Sstevel@tonic-gate 		}
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 		if (Debug)
5667c478bd9Sstevel@tonic-gate 			printf("svc_sendreply: suceeded\n");
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 		if (result.rlt_stat) {
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate 			rex_cleanup();
5717c478bd9Sstevel@tonic-gate 			exit(0);
5727c478bd9Sstevel@tonic-gate 		}
5737c478bd9Sstevel@tonic-gate 		return;
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 	case REXPROC_MODES:
5767c478bd9Sstevel@tonic-gate 		{
5777c478bd9Sstevel@tonic-gate 			struct rex_ttymode mode;
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 			if (Debug) /*	XXX	*/
5807c478bd9Sstevel@tonic-gate 				printf("dorex: call to REXPROC_MODES\n");
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 			if (svc_getargs(transp, xdr_rex_ttymode,
5837c478bd9Sstevel@tonic-gate 					(char *)&mode) == FALSE) {
5847c478bd9Sstevel@tonic-gate 				svcerr_decode(transp);
5857c478bd9Sstevel@tonic-gate 				exit(1);
5867c478bd9Sstevel@tonic-gate 			}
5877c478bd9Sstevel@tonic-gate 			if (Debug)
5887c478bd9Sstevel@tonic-gate 				printf("svc_getargs succ REXPROC_MODES call\n");
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 			SetPtyMode(&mode); /* XXX	Fix?	*/
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 			if (svc_sendreply(transp, xdr_void, 0) == FALSE) {
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 				fprintf(stderr, "rexd: mode reply failed");
5957c478bd9Sstevel@tonic-gate 				exit(1);
5967c478bd9Sstevel@tonic-gate 			}
5977c478bd9Sstevel@tonic-gate 		}
5987c478bd9Sstevel@tonic-gate 		return;
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 	case REXPROC_WINCH: /* XXX	Fix?	*/
6017c478bd9Sstevel@tonic-gate 		{
6027c478bd9Sstevel@tonic-gate 			struct rex_ttysize size;
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 			if (Debug) /*	XXX	*/
6057c478bd9Sstevel@tonic-gate 				printf("dorex: call to REXPROC_WINCH\n");
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 			if (svc_getargs(transp, xdr_rex_ttysize, (char *)&size)
6087c478bd9Sstevel@tonic-gate 			    == FALSE) {
6097c478bd9Sstevel@tonic-gate 				svcerr_decode(transp);
6107c478bd9Sstevel@tonic-gate 				exit(1);
6117c478bd9Sstevel@tonic-gate 			}
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 			SetPtySize(&size);
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 			if (svc_sendreply(transp, xdr_void, 0) == FALSE) {
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 				fprintf(stderr,
6187c478bd9Sstevel@tonic-gate 					"rexd: window change reply failed");
6197c478bd9Sstevel@tonic-gate 				exit(1);
6207c478bd9Sstevel@tonic-gate 			}
6217c478bd9Sstevel@tonic-gate 		}
6227c478bd9Sstevel@tonic-gate 		return;
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 	case REXPROC_SIGNAL:
6257c478bd9Sstevel@tonic-gate 		{
6267c478bd9Sstevel@tonic-gate 			int sigNumber;
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate 			if (Debug) /*	XXX	*/
6297c478bd9Sstevel@tonic-gate 				printf("dorex: call to REXPROC_SIGNAL\n");
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 			if (svc_getargs(transp, xdr_int,
6327c478bd9Sstevel@tonic-gate 					(char *)&sigNumber) == FALSE) {
6337c478bd9Sstevel@tonic-gate 				svcerr_decode(transp);
6347c478bd9Sstevel@tonic-gate 				exit(1);
6357c478bd9Sstevel@tonic-gate 			}
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 			SendSignal(sigNumber);
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 			if (svc_sendreply(transp, xdr_void, 0) == FALSE) {
6407c478bd9Sstevel@tonic-gate 				fprintf(stderr, "rexd: signal reply failed");
6417c478bd9Sstevel@tonic-gate 				exit(1);
6427c478bd9Sstevel@tonic-gate 			}
6437c478bd9Sstevel@tonic-gate 		}
6447c478bd9Sstevel@tonic-gate 		return;
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 	case REXPROC_WAIT:
6477c478bd9Sstevel@tonic-gate 		if (Debug)	/*	XXX	*/
6487c478bd9Sstevel@tonic-gate 			printf("dorex: call to REXPROC_WAIT\n");
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate 		result.rlt_stat = rex_wait(&result.rlt_message);
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 		if (svc_sendreply(transp, xdr_rex_result, (char *)&result)
6537c478bd9Sstevel@tonic-gate 		    == FALSE) {
6547c478bd9Sstevel@tonic-gate 			fprintf(stderr, "rexd: reply failed\n");
6557c478bd9Sstevel@tonic-gate 			exit(1);
6567c478bd9Sstevel@tonic-gate 		}
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 		rex_cleanup();
6597c478bd9Sstevel@tonic-gate 		exit(0);
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
6627c478bd9Sstevel@tonic-gate 	default:
6637c478bd9Sstevel@tonic-gate 		if (Debug)
6647c478bd9Sstevel@tonic-gate 			printf("dorex: call to bad process!\n");
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 		svcerr_noproc(transp);
6677c478bd9Sstevel@tonic-gate 		exit(1);
6687c478bd9Sstevel@tonic-gate 	}
6697c478bd9Sstevel@tonic-gate }
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate /*
6727c478bd9Sstevel@tonic-gate  * signal handler for SIGCHLD - called when user process dies or is stopped
6737c478bd9Sstevel@tonic-gate  */
6747c478bd9Sstevel@tonic-gate void
CatchChild(int junk)6757c478bd9Sstevel@tonic-gate CatchChild(int junk)
6767c478bd9Sstevel@tonic-gate {
6777c478bd9Sstevel@tonic-gate 	pid_t	pid;
6787c478bd9Sstevel@tonic-gate 	int	status;
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate 	if (Debug)
6817c478bd9Sstevel@tonic-gate 		printf("Enter Catchild\n");
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate 	while ((pid = waitpid((pid_t)-1, &status, WNOHANG|WUNTRACED)) > 0) {
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate 		if (Debug) printf("After waitpid\n");
6867c478bd9Sstevel@tonic-gate 		if (pid == child) {
6877c478bd9Sstevel@tonic-gate 			if (Debug)
6887c478bd9Sstevel@tonic-gate 				printf("pid==child\n");
6897c478bd9Sstevel@tonic-gate 			if (WIFSTOPPED(status)) {
6907c478bd9Sstevel@tonic-gate 				sigset_t nullsigset;
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate 				if (Debug)
6937c478bd9Sstevel@tonic-gate 					printf("WIFSTOPPED\n");
6947c478bd9Sstevel@tonic-gate 				/* tell remote client to stop */
6957c478bd9Sstevel@tonic-gate 				send(OutputSocket, "", 1, MSG_OOB);
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate 				sigemptyset(&nullsigset);
6987c478bd9Sstevel@tonic-gate 				/* port of BSD sigpause(0); */
6997c478bd9Sstevel@tonic-gate 				sigsuspend(&nullsigset);
7007c478bd9Sstevel@tonic-gate 				/* restart child */
7017c478bd9Sstevel@tonic-gate 				/* killpg() of SunOS 4.1.1 */
7027c478bd9Sstevel@tonic-gate 				kill((-child), SIGCONT);
7037c478bd9Sstevel@tonic-gate 				return;
7047c478bd9Sstevel@tonic-gate 			}
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 			/*
7077c478bd9Sstevel@tonic-gate 			 * XXX this probably does not cover all interesting
7087c478bd9Sstevel@tonic-gate 			 * exit cases hence reread the man page to determine
7097c478bd9Sstevel@tonic-gate 			 * if we need more data or more test cases
7107c478bd9Sstevel@tonic-gate 			 */
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 			ChildStatus = status;
7137c478bd9Sstevel@tonic-gate 			ChildDied = 1;
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate 			if (HasHelper && svc_pollfd[Master].fd == -1) {
7167c478bd9Sstevel@tonic-gate 				if (Debug)
7177c478bd9Sstevel@tonic-gate 					printf("Within If HasHelper\n");
7187c478bd9Sstevel@tonic-gate 				KillHelper(child);
7197c478bd9Sstevel@tonic-gate 				HasHelper = 0;
7207c478bd9Sstevel@tonic-gate 			}
7217c478bd9Sstevel@tonic-gate 		}
7227c478bd9Sstevel@tonic-gate 	}
7237c478bd9Sstevel@tonic-gate }
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate /*
7267c478bd9Sstevel@tonic-gate  * oob -- called when we should restart the stopped child.
7277c478bd9Sstevel@tonic-gate  */
7287c478bd9Sstevel@tonic-gate void
oob(int junk)7297c478bd9Sstevel@tonic-gate oob(int junk)
7307c478bd9Sstevel@tonic-gate {
7317c478bd9Sstevel@tonic-gate 	int atmark;
7327c478bd9Sstevel@tonic-gate 	char waste[BUFSIZ], mark;
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate 	for (;;) {
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate 		if (ioctl(OutputSocket, SIOCATMARK, &atmark) < 0) {
7377c478bd9Sstevel@tonic-gate 			perror("ioctl");
7387c478bd9Sstevel@tonic-gate 			break;
7397c478bd9Sstevel@tonic-gate 		}
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate 		if (atmark)
7427c478bd9Sstevel@tonic-gate 			break;
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 		(void) read(OutputSocket, waste, sizeof (waste));
7457c478bd9Sstevel@tonic-gate 	}
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate 	(void) recv(OutputSocket, &mark, 1, MSG_OOB);
7487c478bd9Sstevel@tonic-gate }
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate /*
7517c478bd9Sstevel@tonic-gate  * rex_wait - wait for command to finish, unmount the file system,
7527c478bd9Sstevel@tonic-gate  * and return the exit status.
7537c478bd9Sstevel@tonic-gate  * message gets an optional string error message.
7547c478bd9Sstevel@tonic-gate  */
7557c478bd9Sstevel@tonic-gate int
rex_wait(message)7567c478bd9Sstevel@tonic-gate rex_wait(message)
7577c478bd9Sstevel@tonic-gate char **message;
7587c478bd9Sstevel@tonic-gate {
7597c478bd9Sstevel@tonic-gate 	static char error[1024];
7607c478bd9Sstevel@tonic-gate 	int count;
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate 	*message = error;
7637c478bd9Sstevel@tonic-gate 	strcpy(error, "");
7647c478bd9Sstevel@tonic-gate 	if (child == 0) {
7657c478bd9Sstevel@tonic-gate 		errprintf(error, "No process to wait for!\n");
7667c478bd9Sstevel@tonic-gate 		rex_cleanup();
7677c478bd9Sstevel@tonic-gate 		return (1);
7687c478bd9Sstevel@tonic-gate 	}
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate 	kill(child, SIGHUP);
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate 	for (count = 0; !ChildDied && count < WaitLimit; count++)
7737c478bd9Sstevel@tonic-gate 		sleep(1);
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate 	if (ChildStatus & 0xFF)
7767c478bd9Sstevel@tonic-gate 		return (ChildStatus);
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	return (ChildStatus >> 8);
7797c478bd9Sstevel@tonic-gate }
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate /*
7837c478bd9Sstevel@tonic-gate  * cleanup - unmount and remove our temporary directory
7847c478bd9Sstevel@tonic-gate  */
7857c478bd9Sstevel@tonic-gate void
rex_cleanup()7867c478bd9Sstevel@tonic-gate rex_cleanup()
7877c478bd9Sstevel@tonic-gate {
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate 	if (tmpdir) {
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate 		if (child && !ChildDied) {
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 			fprintf(stderr,
7947c478bd9Sstevel@tonic-gate 				"rexd: child killed to unmount %s\r\n",
7957c478bd9Sstevel@tonic-gate 				nfsdir);
7967c478bd9Sstevel@tonic-gate 			kill(child, SIGKILL);
7977c478bd9Sstevel@tonic-gate 		}
7987c478bd9Sstevel@tonic-gate 		chdir("/");
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate 		if (nfsdir[0] && umount_nfs(nfsdir, tmpdir))
8017c478bd9Sstevel@tonic-gate 			fprintf(stderr, "rexd: couldn't umount %s from %s\r\n",
8027c478bd9Sstevel@tonic-gate 				nfsdir,
8037c478bd9Sstevel@tonic-gate 				tmpdir);
8047c478bd9Sstevel@tonic-gate 		if (rmdir(tmpdir) < 0)
8057c478bd9Sstevel@tonic-gate 			if (errno != EBUSY)
8067c478bd9Sstevel@tonic-gate 				perror("rmdir");
8077c478bd9Sstevel@tonic-gate 		tmpdir = NULL;
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 	}
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate 	if (Debug)
8127c478bd9Sstevel@tonic-gate 		printf("rex_cleaup: HasHelper=%d\n", HasHelper);
8137c478bd9Sstevel@tonic-gate 	if (HasHelper)
8147c478bd9Sstevel@tonic-gate 		KillHelper(child);
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 	HasHelper = 0;
8177c478bd9Sstevel@tonic-gate }
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate /*
8217c478bd9Sstevel@tonic-gate  * This function does the server work to get a command executed
8227c478bd9Sstevel@tonic-gate  * Returns 0 if OK, nonzero if error
8237c478bd9Sstevel@tonic-gate  */
8247c478bd9Sstevel@tonic-gate int
rex_startup(rst,ucred,message,calleraddr)8257c478bd9Sstevel@tonic-gate rex_startup(rst, ucred, message, calleraddr)
8267c478bd9Sstevel@tonic-gate struct rex_start *rst;
8277c478bd9Sstevel@tonic-gate struct authunix_parms *ucred;
8287c478bd9Sstevel@tonic-gate char **message;
8297c478bd9Sstevel@tonic-gate struct sockaddr_in *calleraddr;
8307c478bd9Sstevel@tonic-gate {
8317c478bd9Sstevel@tonic-gate 	char hostname[255];
8327c478bd9Sstevel@tonic-gate 	char *p, *wdhost, *fsname, *subdir;
8337c478bd9Sstevel@tonic-gate 	char dirbuf[1024];
8347c478bd9Sstevel@tonic-gate 	static char error[1024];
8357c478bd9Sstevel@tonic-gate 	char defaultShell[1024]; /* command executed if none given */
8367c478bd9Sstevel@tonic-gate 	char defaultDir[1024];	/* directory used if none given */
8377c478bd9Sstevel@tonic-gate 	int len;
8387c478bd9Sstevel@tonic-gate 	int fd0, fd1, fd2;
8397c478bd9Sstevel@tonic-gate 	extern pam_handle_t *pamh;
8407c478bd9Sstevel@tonic-gate 	char *user = NULL;
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate 	if (Debug)
8437c478bd9Sstevel@tonic-gate 		printf("Beginning of Rex_Startup\n");
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate 	if (child) {		/* already started */
8467c478bd9Sstevel@tonic-gate 		if (Debug)
8477c478bd9Sstevel@tonic-gate 			printf("Killing \"child\" process\n");
8487c478bd9Sstevel@tonic-gate 		kill((-child), SIGKILL); /* killpg() of SunOS 4.1.1 */
8497c478bd9Sstevel@tonic-gate 		return (1);
8507c478bd9Sstevel@tonic-gate 	}
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate 
8537c478bd9Sstevel@tonic-gate 	*message = error;
8547c478bd9Sstevel@tonic-gate 	(void) strcpy(error, "");
8557c478bd9Sstevel@tonic-gate /*	sigset(SIGCHLD, CatchChild); */
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate 	if (ValidUser(ucred->aup_machname,
8597c478bd9Sstevel@tonic-gate 		(uid_t)ucred->aup_uid,
8607c478bd9Sstevel@tonic-gate 		(gid_t)ucred->aup_gid,
8617c478bd9Sstevel@tonic-gate 		error,
8627c478bd9Sstevel@tonic-gate 		defaultShell, defaultDir, rst))
8637c478bd9Sstevel@tonic-gate 		return (1);
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate 	if (rst->rst_fsname && strlen(rst->rst_fsname)) {
8667c478bd9Sstevel@tonic-gate 		fsname = rst->rst_fsname;
8677c478bd9Sstevel@tonic-gate 		subdir = rst->rst_dirwithin;
8687c478bd9Sstevel@tonic-gate 		wdhost = rst->rst_host;
8697c478bd9Sstevel@tonic-gate 	} else {
8707c478bd9Sstevel@tonic-gate 		fsname = defaultDir;
8717c478bd9Sstevel@tonic-gate 		subdir = "";
8727c478bd9Sstevel@tonic-gate 		wdhost = hostname;
8737c478bd9Sstevel@tonic-gate 	}
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate 	sysinfo(SI_HOSTNAME, hostname, 255);
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate 	if (Debug)
8787c478bd9Sstevel@tonic-gate 		printf("rexd: errno %d after gethostname\n", errno);
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate 	if (Debug) {
8817c478bd9Sstevel@tonic-gate 		printf("rex_startup on host %s:\nrequests fsname=%s",
8827c478bd9Sstevel@tonic-gate 			hostname, fsname);
8837c478bd9Sstevel@tonic-gate 		printf("\t\tsubdir=%s\t\twdhost=%s\n", subdir, wdhost);
8847c478bd9Sstevel@tonic-gate 	}
8857c478bd9Sstevel@tonic-gate 	if (strcmp(wdhost, hostname) == 0) {
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 		/*
8887c478bd9Sstevel@tonic-gate 		 * The requested directory is local to our machine,
8897c478bd9Sstevel@tonic-gate 		 * so just change to it.
8907c478bd9Sstevel@tonic-gate 		 */
8917c478bd9Sstevel@tonic-gate 		strcpy(dirbuf, fsname);
8927c478bd9Sstevel@tonic-gate 	} else {
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate 		static char wanted[1024];
8957c478bd9Sstevel@tonic-gate 		static char mountedon[1024];
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 		strcpy(wanted, wdhost);
8987c478bd9Sstevel@tonic-gate 		strcat(wanted, ":");
8997c478bd9Sstevel@tonic-gate 		strcat(wanted, fsname);
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate 		if (AlreadyMounted(wanted, mountedon)) {
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate 			if (Debug)
9047c478bd9Sstevel@tonic-gate 				printf("AlreadyMounted (%d)\n", errno);
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 			/*
9077c478bd9Sstevel@tonic-gate 			 * The requested directory is already mounted.  If the
9087c478bd9Sstevel@tonic-gate 			 * mount is not by another rexd, just change to it.
9097c478bd9Sstevel@tonic-gate 			 * Otherwise, mount it again.  If just changing to
9107c478bd9Sstevel@tonic-gate 			 * the mounted directy, be careful. It might be mounted
9117c478bd9Sstevel@tonic-gate 			 * in a different place.
9127c478bd9Sstevel@tonic-gate 			 * (dirbuf is modified in place!)
9137c478bd9Sstevel@tonic-gate 			 */
9147c478bd9Sstevel@tonic-gate 			if (strncmp(mountedon, TempName, TempMatch) == 0) {
9157c478bd9Sstevel@tonic-gate 				tmpdir = mktemp(TempName);
9167c478bd9Sstevel@tonic-gate 				/*
9177c478bd9Sstevel@tonic-gate 				 * XXX errno is set to ENOENT on success
9187c478bd9Sstevel@tonic-gate 				 * of mktemp because of accesss checks for file
9197c478bd9Sstevel@tonic-gate 				 */
9207c478bd9Sstevel@tonic-gate 				if (errno == ENOENT)
9217c478bd9Sstevel@tonic-gate 					errno = 0;
9227c478bd9Sstevel@tonic-gate 
9237c478bd9Sstevel@tonic-gate 				if (mkdir(tmpdir, 0777)) {
9247c478bd9Sstevel@tonic-gate 					perror("Already Mounted");
9257c478bd9Sstevel@tonic-gate 					if (pamh) {
9267c478bd9Sstevel@tonic-gate 						pam_end(pamh, PAM_ABORT);
9277c478bd9Sstevel@tonic-gate 						pamh = NULL;
9287c478bd9Sstevel@tonic-gate 					}
9297c478bd9Sstevel@tonic-gate 					return (1);
9307c478bd9Sstevel@tonic-gate 				}
9317c478bd9Sstevel@tonic-gate 
9327c478bd9Sstevel@tonic-gate 				if (Debug)
9337c478bd9Sstevel@tonic-gate 					printf("created %s (%d)\n",
9347c478bd9Sstevel@tonic-gate 						tmpdir, errno);
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate 				strcpy(nfsdir, wanted);
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate 				if (mount_nfs(wanted, tmpdir, error)) {
9397c478bd9Sstevel@tonic-gate 					if (Debug)
9407c478bd9Sstevel@tonic-gate 					printf("mount_nfs:error return\n");
9417c478bd9Sstevel@tonic-gate 					if (pamh) {
9427c478bd9Sstevel@tonic-gate 						pam_end(pamh, PAM_ABORT);
9437c478bd9Sstevel@tonic-gate 						pamh = NULL;
9447c478bd9Sstevel@tonic-gate 					}
9457c478bd9Sstevel@tonic-gate 					return (1);
9467c478bd9Sstevel@tonic-gate 				}
9477c478bd9Sstevel@tonic-gate 				if (Debug)
9487c478bd9Sstevel@tonic-gate 					printf("mount_nfs: success return\n");
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate 				strcpy(dirbuf, tmpdir);
9517c478bd9Sstevel@tonic-gate 
9527c478bd9Sstevel@tonic-gate 			} else
9537c478bd9Sstevel@tonic-gate 				strcpy(dirbuf, mountedon);
9547c478bd9Sstevel@tonic-gate 
9557c478bd9Sstevel@tonic-gate 		} else {
9567c478bd9Sstevel@tonic-gate 			if (Debug)
9577c478bd9Sstevel@tonic-gate 				printf("not AlreadyMounted (%d)\n", errno);
9587c478bd9Sstevel@tonic-gate 			/*
9597c478bd9Sstevel@tonic-gate 			 * The requested directory is not mounted anywhere,
9607c478bd9Sstevel@tonic-gate 			 * so try to mount our own copy of it.  We set nfsdir
9617c478bd9Sstevel@tonic-gate 			 * so that it gets unmounted later, and tmpdir so that
9627c478bd9Sstevel@tonic-gate 			 * it also gets removed when we are done.
9637c478bd9Sstevel@tonic-gate 			 */
9647c478bd9Sstevel@tonic-gate 			tmpdir = mktemp(TempName);
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate 			/*
9677c478bd9Sstevel@tonic-gate 			 * XXX errno is set to ENOENT on success of mktemp
9687c478bd9Sstevel@tonic-gate 			 * becuase of accesss checks for file
9697c478bd9Sstevel@tonic-gate 			 */
9707c478bd9Sstevel@tonic-gate 			if (errno == ENOENT)
9717c478bd9Sstevel@tonic-gate 				errno = 0;
9727c478bd9Sstevel@tonic-gate 			if (mkdir(tmpdir, 0777)) {
9737c478bd9Sstevel@tonic-gate 				perror("Not Already Mounted");
9747c478bd9Sstevel@tonic-gate 				if (pamh) {
9757c478bd9Sstevel@tonic-gate 					pam_end(pamh, PAM_ABORT);
9767c478bd9Sstevel@tonic-gate 					pamh = NULL;
9777c478bd9Sstevel@tonic-gate 				}
9787c478bd9Sstevel@tonic-gate 				return (1);
9797c478bd9Sstevel@tonic-gate 			}
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate 			if (Debug)
9827c478bd9Sstevel@tonic-gate 				printf("created %s (%d)\n", tmpdir, errno);
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 			strcpy(nfsdir, wanted);
9857c478bd9Sstevel@tonic-gate 
9867c478bd9Sstevel@tonic-gate 			if (mount_nfs(wanted, tmpdir, error)) {
9877c478bd9Sstevel@tonic-gate 				if (Debug)
9887c478bd9Sstevel@tonic-gate 					printf("mount_nfs:error return\n");
9897c478bd9Sstevel@tonic-gate 				if (pamh) {
9907c478bd9Sstevel@tonic-gate 					pam_end(pamh, PAM_ABORT);
9917c478bd9Sstevel@tonic-gate 					pamh = NULL;
9927c478bd9Sstevel@tonic-gate 				}
9937c478bd9Sstevel@tonic-gate 				return (1);
9947c478bd9Sstevel@tonic-gate 			}
9957c478bd9Sstevel@tonic-gate 			if (Debug)
9967c478bd9Sstevel@tonic-gate 				printf("mount_nfs: success return\n");
9977c478bd9Sstevel@tonic-gate 			strcpy(dirbuf, tmpdir);
9987c478bd9Sstevel@tonic-gate 		}
9997c478bd9Sstevel@tonic-gate 	}
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate 	/*
10027c478bd9Sstevel@tonic-gate 	 * "dirbuf" now contains the local mount point, so just tack on
10037c478bd9Sstevel@tonic-gate 	 * the subdirectory to get the pathname to which we "chdir"
10047c478bd9Sstevel@tonic-gate 	 */
10057c478bd9Sstevel@tonic-gate 	strcat(dirbuf, subdir);
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate 
10087c478bd9Sstevel@tonic-gate 	fd0 = socket(AF_INET, SOCK_STREAM, 0);
10097c478bd9Sstevel@tonic-gate 	if (Debug)
10107c478bd9Sstevel@tonic-gate 		printf("Before doconnect\n");
10117c478bd9Sstevel@tonic-gate 	fd0 = doconnect(calleraddr, rst->rst_port0, fd0);
10127c478bd9Sstevel@tonic-gate 	OutputSocket = fd0;
10137c478bd9Sstevel@tonic-gate 
10147c478bd9Sstevel@tonic-gate 	/*
10157c478bd9Sstevel@tonic-gate 	 * Arrange for fd0 to send the SIGURG signal when out-of-band data
10167c478bd9Sstevel@tonic-gate 	 * arrives, which indicates that we should send the stopped child a
10177c478bd9Sstevel@tonic-gate 	 * SIGCONT signal so that we can resume work.
10187c478bd9Sstevel@tonic-gate 	 */
10197c478bd9Sstevel@tonic-gate 	(void) fcntl(fd0, F_SETOWN, getpid());
10207c478bd9Sstevel@tonic-gate 	/*	ioctl(fd0, SIOCSPGRP, ?X?); */
10217c478bd9Sstevel@tonic-gate 	sigset(SIGURG, oob);
10227c478bd9Sstevel@tonic-gate 
10237c478bd9Sstevel@tonic-gate 	if (Debug)
10247c478bd9Sstevel@tonic-gate 		printf("Before \"use same port\"\n");
10257c478bd9Sstevel@tonic-gate 	if (rst->rst_port0 == rst->rst_port1) {
10267c478bd9Sstevel@tonic-gate 		/*
10277c478bd9Sstevel@tonic-gate 		 * use the same connection for both stdin and stdout
10287c478bd9Sstevel@tonic-gate 		 */
10297c478bd9Sstevel@tonic-gate 		fd1 = fd0;
10307c478bd9Sstevel@tonic-gate 	}
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate 	if (rst->rst_flags & REX_INTERACTIVE) {
10337c478bd9Sstevel@tonic-gate 		/*
10347c478bd9Sstevel@tonic-gate 		 * allocate a pseudo-terminal if necessary
10357c478bd9Sstevel@tonic-gate 		 */
10367c478bd9Sstevel@tonic-gate 		if (Debug)
10377c478bd9Sstevel@tonic-gate 			printf("Before AllocatePty call\n");
10387c478bd9Sstevel@tonic-gate 
10397c478bd9Sstevel@tonic-gate 		/* AllocatePty has grantpt() call which has bug */
10407c478bd9Sstevel@tonic-gate 		/* Hence clear SIGCHLD handler setting */
10417c478bd9Sstevel@tonic-gate 		sigset(SIGCHLD, SIG_DFL);
10427c478bd9Sstevel@tonic-gate 		if (AllocatePty(fd0, fd1)) {
10437c478bd9Sstevel@tonic-gate 			errprintf(error, "rexd: cannot allocate a pty\n");
10447c478bd9Sstevel@tonic-gate 			if (pamh) {
10457c478bd9Sstevel@tonic-gate 				pam_end(pamh, PAM_ABORT);
10467c478bd9Sstevel@tonic-gate 				pamh = NULL;
10477c478bd9Sstevel@tonic-gate 			}
10487c478bd9Sstevel@tonic-gate 			return (1);
10497c478bd9Sstevel@tonic-gate 		}
10507c478bd9Sstevel@tonic-gate 		HasHelper = 1;
10517c478bd9Sstevel@tonic-gate 	}
10527c478bd9Sstevel@tonic-gate 	/*
10537c478bd9Sstevel@tonic-gate 	 * this sigset()call moved to after AllocatePty() call
10547c478bd9Sstevel@tonic-gate 	 * because a bug in waitpid() inside grantpt()
10557c478bd9Sstevel@tonic-gate 	 * causes CatchChild() to be invoked.
10567c478bd9Sstevel@tonic-gate 	 */
10577c478bd9Sstevel@tonic-gate 
10587c478bd9Sstevel@tonic-gate 	sigset(SIGCHLD, CatchChild);
10597c478bd9Sstevel@tonic-gate 
10607c478bd9Sstevel@tonic-gate 	if (rst->rst_flags & REX_INTERACTIVE) {
10617c478bd9Sstevel@tonic-gate 		sigset(SIGWINCH, sigwinch); /* a dummy signal handler */
10627c478bd9Sstevel@tonic-gate 		/* block the sigpause until signal in */
10637c478bd9Sstevel@tonic-gate 		/* child releases the signal */
10647c478bd9Sstevel@tonic-gate 		sighold(SIGWINCH);
10657c478bd9Sstevel@tonic-gate 	}
10667c478bd9Sstevel@tonic-gate 
10677c478bd9Sstevel@tonic-gate 	if (Debug)
10687c478bd9Sstevel@tonic-gate 		printf("Before a \"child\" fork\n");
10697c478bd9Sstevel@tonic-gate 
10707c478bd9Sstevel@tonic-gate 	child = fork();
10717c478bd9Sstevel@tonic-gate 
10727c478bd9Sstevel@tonic-gate 	if (child < 0) {
10737c478bd9Sstevel@tonic-gate 		errprintf(error, "rexd: can't fork\n");
10747c478bd9Sstevel@tonic-gate 		if (pamh) {
10757c478bd9Sstevel@tonic-gate 			pam_end(pamh, PAM_ABORT);
10767c478bd9Sstevel@tonic-gate 			pamh = NULL;
10777c478bd9Sstevel@tonic-gate 		}
10787c478bd9Sstevel@tonic-gate 		return (1);
10797c478bd9Sstevel@tonic-gate 	}
10807c478bd9Sstevel@tonic-gate 
10817c478bd9Sstevel@tonic-gate 	if (child) {
10827c478bd9Sstevel@tonic-gate 		/*
10837c478bd9Sstevel@tonic-gate 		 * parent rexd: close network connections if needed,
10847c478bd9Sstevel@tonic-gate 		 * then return to the main loop.
10857c478bd9Sstevel@tonic-gate 		 */
10867c478bd9Sstevel@tonic-gate 		if ((rst->rst_flags & REX_INTERACTIVE) == 0) {
10877c478bd9Sstevel@tonic-gate 			close(fd0);
10887c478bd9Sstevel@tonic-gate 			close(fd1);
10897c478bd9Sstevel@tonic-gate 		}
10907c478bd9Sstevel@tonic-gate 		if (Debug)
10917c478bd9Sstevel@tonic-gate 			printf("Parent ret to main loop, child does startup\n");
10927c478bd9Sstevel@tonic-gate 		if (pamh) {
10937c478bd9Sstevel@tonic-gate 			pam_end(pamh, PAM_SUCCESS);
10947c478bd9Sstevel@tonic-gate 			pamh = NULL;
10957c478bd9Sstevel@tonic-gate 		}
10967c478bd9Sstevel@tonic-gate 		return (0);
10977c478bd9Sstevel@tonic-gate 	}
10987c478bd9Sstevel@tonic-gate 
10997c478bd9Sstevel@tonic-gate 	/* child rexd */
11007c478bd9Sstevel@tonic-gate 
11017c478bd9Sstevel@tonic-gate 	if (Debug)
11027c478bd9Sstevel@tonic-gate 		printf("Child rexd\n");
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate 	/* setpgrp(0, 0) */
11057c478bd9Sstevel@tonic-gate 	setsid();		/* make session leader */
11067c478bd9Sstevel@tonic-gate 
11077c478bd9Sstevel@tonic-gate 	if (Debug)
11087c478bd9Sstevel@tonic-gate 		printf("After setsid\n");
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate 	if (rst->rst_flags & REX_INTERACTIVE) {
11117c478bd9Sstevel@tonic-gate 		if (Debug)
11127c478bd9Sstevel@tonic-gate 			printf("Before OpenPtySlave\n");
11137c478bd9Sstevel@tonic-gate 		/* reopen slave so that child has controlling tty */
11147c478bd9Sstevel@tonic-gate 		OpenPtySlave();
11157c478bd9Sstevel@tonic-gate 		if (Debug)
11167c478bd9Sstevel@tonic-gate 			printf("After OpenPtySlave\n");
11177c478bd9Sstevel@tonic-gate 	}
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate 	if (rst->rst_port0 != rst->rst_port1) {
11207c478bd9Sstevel@tonic-gate 
11217c478bd9Sstevel@tonic-gate 		if (Debug)
11227c478bd9Sstevel@tonic-gate 			printf("rst_port0 != rst_port1\n"); /*	XXX	*/
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate 		fd1 = socket(AF_INET, SOCK_STREAM, 0);
11257c478bd9Sstevel@tonic-gate 		shutdown(fd0, 1); /* 1=>further sends disallowed */
11267c478bd9Sstevel@tonic-gate 		fd1 = doconnect(calleraddr, rst->rst_port1, fd1);
11277c478bd9Sstevel@tonic-gate 		shutdown(fd1, 0); /* 0=>further receives disallowed */
11287c478bd9Sstevel@tonic-gate 	}
11297c478bd9Sstevel@tonic-gate 
11307c478bd9Sstevel@tonic-gate 	if (rst->rst_port1 == rst->rst_port2) {
11317c478bd9Sstevel@tonic-gate 		if (Debug)
11327c478bd9Sstevel@tonic-gate 			printf("rst_port1 == rst_port2\n"); /*	XXX	*/
11337c478bd9Sstevel@tonic-gate 
11347c478bd9Sstevel@tonic-gate 		/*
11357c478bd9Sstevel@tonic-gate 		 * Use the same connection for both stdout and stderr
11367c478bd9Sstevel@tonic-gate 		 */
11377c478bd9Sstevel@tonic-gate 		fd2 = fd1;
11387c478bd9Sstevel@tonic-gate 	} else {
11397c478bd9Sstevel@tonic-gate 		if (Debug)
11407c478bd9Sstevel@tonic-gate 			printf("rst_port1 != rst_port2\n"); /*	XXX	*/
11417c478bd9Sstevel@tonic-gate 
11427c478bd9Sstevel@tonic-gate 		fd2 = socket(AF_INET, SOCK_STREAM, 0);
11437c478bd9Sstevel@tonic-gate 		fd2 = doconnect(calleraddr, rst->rst_port2, fd2);
11447c478bd9Sstevel@tonic-gate 		shutdown(fd2, 0); /* 0=>further receives disallowed */
11457c478bd9Sstevel@tonic-gate 	}
11467c478bd9Sstevel@tonic-gate 
11477c478bd9Sstevel@tonic-gate 	if (rst->rst_flags & REX_INTERACTIVE) {
11487c478bd9Sstevel@tonic-gate 
11497c478bd9Sstevel@tonic-gate 		/*
11507c478bd9Sstevel@tonic-gate 		 * use ptys instead of sockets in interactive mode
11517c478bd9Sstevel@tonic-gate 		 */
11527c478bd9Sstevel@tonic-gate 		DoHelper(&fd0, &fd1, &fd2);
11537c478bd9Sstevel@tonic-gate 		LoginUser();
11547c478bd9Sstevel@tonic-gate 	}
11557c478bd9Sstevel@tonic-gate 
11567c478bd9Sstevel@tonic-gate 	dup2(fd0, 0);
11577c478bd9Sstevel@tonic-gate 	dup2(fd1, 1);
11587c478bd9Sstevel@tonic-gate 	dup2(fd2, 2);
11597c478bd9Sstevel@tonic-gate 
11607c478bd9Sstevel@tonic-gate 	/* setup terminal ID (use read file descriptor) */
11617c478bd9Sstevel@tonic-gate 	if (audit_settid(fd0) != 0) {
11627c478bd9Sstevel@tonic-gate 		errprintf("cannot set audit characteristics\n");
11637c478bd9Sstevel@tonic-gate 		return (1);
11647c478bd9Sstevel@tonic-gate 	}
11657c478bd9Sstevel@tonic-gate 
11667c478bd9Sstevel@tonic-gate 	closefrom(3);
11677c478bd9Sstevel@tonic-gate 
11687c478bd9Sstevel@tonic-gate 	if (Debug)
11697c478bd9Sstevel@tonic-gate 		printf("After close-all-fds-loop-- errno=%d\n", errno);
11707c478bd9Sstevel@tonic-gate 
11717c478bd9Sstevel@tonic-gate 	environ = rst->rst_env;
11727c478bd9Sstevel@tonic-gate 
11737c478bd9Sstevel@tonic-gate 	if (pam_get_item(pamh, PAM_USER, (void **)&user) != PAM_SUCCESS) {
11747c478bd9Sstevel@tonic-gate 		audit_rexd_fail("user id is not valid",
11757c478bd9Sstevel@tonic-gate 				ucred->aup_machname,
11767c478bd9Sstevel@tonic-gate 				user,
11777c478bd9Sstevel@tonic-gate 				ucred->aup_uid,
11787c478bd9Sstevel@tonic-gate 				ucred->aup_gid,
11797c478bd9Sstevel@tonic-gate 				defaultShell,
11807c478bd9Sstevel@tonic-gate 				rst->rst_cmd);	    /* BSM */
11817c478bd9Sstevel@tonic-gate 		fprintf(stderr, "rexd: invalid uid/gid.\n");
11827c478bd9Sstevel@tonic-gate 		exit(1);
11837c478bd9Sstevel@tonic-gate 	}
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate 	/* set the real (and effective) GID */
11867c478bd9Sstevel@tonic-gate 	if (setgid(ucred->aup_gid) == -1) {
11877c478bd9Sstevel@tonic-gate 		fprintf(stderr, "rexd: invalid gid.\n");
11887c478bd9Sstevel@tonic-gate 		exit(1);
11897c478bd9Sstevel@tonic-gate 	}
11907c478bd9Sstevel@tonic-gate 	/* Set the supplementary group access list. */
11917c478bd9Sstevel@tonic-gate 	if (setgroups(ucred->aup_len, (gid_t *)ucred->aup_gids) == -1) {
11927c478bd9Sstevel@tonic-gate 		fprintf(stderr, "rexd: invalid group list.\n");
11937c478bd9Sstevel@tonic-gate 		exit(1);
11947c478bd9Sstevel@tonic-gate 	}
11957c478bd9Sstevel@tonic-gate 
11967c478bd9Sstevel@tonic-gate 	if (pam_setcred(pamh, PAM_ESTABLISH_CRED) != PAM_SUCCESS) {
11977c478bd9Sstevel@tonic-gate 		audit_rexd_fail("user id is not valid",
11987c478bd9Sstevel@tonic-gate 				ucred->aup_machname,
11997c478bd9Sstevel@tonic-gate 				user,
12007c478bd9Sstevel@tonic-gate 				ucred->aup_uid,
12017c478bd9Sstevel@tonic-gate 				ucred->aup_gid,
12027c478bd9Sstevel@tonic-gate 				defaultShell,
12037c478bd9Sstevel@tonic-gate 				rst->rst_cmd);	    /* BSM */
12047c478bd9Sstevel@tonic-gate 		fprintf(stderr, "rexd: invalid uid/gid.\n");
12057c478bd9Sstevel@tonic-gate 		exit(1);
12067c478bd9Sstevel@tonic-gate 	}
12077c478bd9Sstevel@tonic-gate 
12087c478bd9Sstevel@tonic-gate 	audit_rexd_success(ucred->aup_machname,
12097c478bd9Sstevel@tonic-gate 				user,
12107c478bd9Sstevel@tonic-gate 				ucred->aup_uid,
12117c478bd9Sstevel@tonic-gate 				ucred->aup_gid,
12127c478bd9Sstevel@tonic-gate 				defaultShell,
12137c478bd9Sstevel@tonic-gate 				rst->rst_cmd);	/* BSM */
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate 	/* set the real (and effective) UID */
12167c478bd9Sstevel@tonic-gate 	if (setuid(ucred->aup_uid) == -1) {
12177c478bd9Sstevel@tonic-gate 		fprintf(stderr, "rexd: invalid uid.\n");
12187c478bd9Sstevel@tonic-gate 		exit(1);
12197c478bd9Sstevel@tonic-gate 	}
12207c478bd9Sstevel@tonic-gate 
12217c478bd9Sstevel@tonic-gate 	if (pamh) {
12227c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_SUCCESS);
12237c478bd9Sstevel@tonic-gate 		pamh = NULL;
12247c478bd9Sstevel@tonic-gate 	}
12257c478bd9Sstevel@tonic-gate 
12267c478bd9Sstevel@tonic-gate 	if (Debug)	/*	XXX	*/
12277c478bd9Sstevel@tonic-gate 		fprintf(stderr, "uid %d gid %d (%d)\n",
12287c478bd9Sstevel@tonic-gate 			ucred->aup_uid, ucred->aup_gid, errno);
12297c478bd9Sstevel@tonic-gate 
12307c478bd9Sstevel@tonic-gate 	if (chdir(dirbuf)) {
12317c478bd9Sstevel@tonic-gate 		fprintf(stderr, "rexd: can't chdir to %s\n", dirbuf);
12327c478bd9Sstevel@tonic-gate 		exit(1);
12337c478bd9Sstevel@tonic-gate 	}
12347c478bd9Sstevel@tonic-gate 
12357c478bd9Sstevel@tonic-gate 	sigset(SIGINT, SIG_DFL);
12367c478bd9Sstevel@tonic-gate 	sigset(SIGHUP, SIG_DFL);
12377c478bd9Sstevel@tonic-gate 	sigset(SIGQUIT, SIG_DFL);
12387c478bd9Sstevel@tonic-gate 
12397c478bd9Sstevel@tonic-gate 	if (rst->rst_flags & REX_INTERACTIVE) {
12407c478bd9Sstevel@tonic-gate 		/* pause to sync with first SIGWINCH sent as part of */
12417c478bd9Sstevel@tonic-gate 		sigpause(SIGWINCH);
12427c478bd9Sstevel@tonic-gate 		/* protocol and handled by parent doing other rex primitves */
12437c478bd9Sstevel@tonic-gate 		sigrelse(SIGWINCH);
12447c478bd9Sstevel@tonic-gate 		sigset(SIGWINCH, SIG_DFL);
12457c478bd9Sstevel@tonic-gate 	}
12467c478bd9Sstevel@tonic-gate 
12477c478bd9Sstevel@tonic-gate 	if (rst->rst_cmd == (char **)NULL) {
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate 		/*
12507c478bd9Sstevel@tonic-gate 		 * Null command means execute the default shell for this user
12517c478bd9Sstevel@tonic-gate 		 */
12527c478bd9Sstevel@tonic-gate 		char *args[2];
12537c478bd9Sstevel@tonic-gate 
12547c478bd9Sstevel@tonic-gate 		args[0] = defaultShell;
12557c478bd9Sstevel@tonic-gate 		args[1] = NULL;
12567c478bd9Sstevel@tonic-gate 
12577c478bd9Sstevel@tonic-gate 		execvp(defaultShell, args);
12587c478bd9Sstevel@tonic-gate 
12597c478bd9Sstevel@tonic-gate 		fprintf(stderr, "rexd: can't exec shell %s\n", defaultShell);
12607c478bd9Sstevel@tonic-gate 		exit(1);
12617c478bd9Sstevel@tonic-gate 	}
12627c478bd9Sstevel@tonic-gate 
12637c478bd9Sstevel@tonic-gate 	if (Debug)
12647c478bd9Sstevel@tonic-gate 		for (len = 0; rst->rst_cmd[len] != (char *)NULL &&
12657c478bd9Sstevel@tonic-gate 			*rst->rst_cmd[len] != NULL; len++)
12667c478bd9Sstevel@tonic-gate 			printf("cmds: %s (%d)\n", rst->rst_cmd[len], errno);
12677c478bd9Sstevel@tonic-gate 
12687c478bd9Sstevel@tonic-gate 
12697c478bd9Sstevel@tonic-gate 	/*	XXX	*/
12707c478bd9Sstevel@tonic-gate 	if (Debug)
12717c478bd9Sstevel@tonic-gate 		for (len = 0; rst->rst_env[len] != (char *)NULL &&
12727c478bd9Sstevel@tonic-gate 			*rst->rst_env[len] != NULL; len++)
12737c478bd9Sstevel@tonic-gate 			printf("envs: %s\n", rst->rst_env[len]);
12747c478bd9Sstevel@tonic-gate 
12757c478bd9Sstevel@tonic-gate 
12767c478bd9Sstevel@tonic-gate 	execvp(rst->rst_cmd[0], rst->rst_cmd);
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate 	/*	XXX	get rid of errno in parens	*/
12797c478bd9Sstevel@tonic-gate 	fprintf(stderr, "rexd: can't exec %s (%d)\n", *rst->rst_cmd, errno);
12807c478bd9Sstevel@tonic-gate 	exit(1);
12817c478bd9Sstevel@tonic-gate }
12827c478bd9Sstevel@tonic-gate 
12837c478bd9Sstevel@tonic-gate /*
12847c478bd9Sstevel@tonic-gate  * Search the mount table to see if the given file system is already
12857c478bd9Sstevel@tonic-gate  * mounted.  If so, return the place that it is mounted on.
12867c478bd9Sstevel@tonic-gate  */
12877c478bd9Sstevel@tonic-gate int
AlreadyMounted(fsname,mountedon)12887c478bd9Sstevel@tonic-gate AlreadyMounted(fsname, mountedon)
12897c478bd9Sstevel@tonic-gate char *fsname;
12907c478bd9Sstevel@tonic-gate char *mountedon;
12917c478bd9Sstevel@tonic-gate {
12927c478bd9Sstevel@tonic-gate 	FILE		*table;
12937c478bd9Sstevel@tonic-gate 	struct mnttab	 mt;
12947c478bd9Sstevel@tonic-gate 
12957c478bd9Sstevel@tonic-gate 	table = setmntent(MOUNTED, "r");
12967c478bd9Sstevel@tonic-gate 	if (table == NULL)
12977c478bd9Sstevel@tonic-gate 		return (0);
12987c478bd9Sstevel@tonic-gate 
12997c478bd9Sstevel@tonic-gate 	while ((getmntent(table, &mt)) != (-1)) {
13007c478bd9Sstevel@tonic-gate 
13017c478bd9Sstevel@tonic-gate 		if (strcmp(mt.mnt_special, fsname) == 0) {
13027c478bd9Sstevel@tonic-gate 			strcpy(mountedon, mt.mnt_mountp);
13037c478bd9Sstevel@tonic-gate 			endmntent(table);
13047c478bd9Sstevel@tonic-gate 			return (1);
13057c478bd9Sstevel@tonic-gate 		}
13067c478bd9Sstevel@tonic-gate 	}
13077c478bd9Sstevel@tonic-gate 	endmntent(table);
13087c478bd9Sstevel@tonic-gate 
13097c478bd9Sstevel@tonic-gate 	return (0);
13107c478bd9Sstevel@tonic-gate }
13117c478bd9Sstevel@tonic-gate 
13127c478bd9Sstevel@tonic-gate 
13137c478bd9Sstevel@tonic-gate /*
13147c478bd9Sstevel@tonic-gate  * connect to the indicated IP address/port, and return the
13157c478bd9Sstevel@tonic-gate  * resulting file descriptor.
13167c478bd9Sstevel@tonic-gate  */
13177c478bd9Sstevel@tonic-gate int
doconnect(sin,port,fd)13187c478bd9Sstevel@tonic-gate doconnect(sin, port, fd)
13197c478bd9Sstevel@tonic-gate struct sockaddr_in *sin;
13207c478bd9Sstevel@tonic-gate short port;
13217c478bd9Sstevel@tonic-gate int fd;
13227c478bd9Sstevel@tonic-gate {
13237c478bd9Sstevel@tonic-gate 	sin->sin_port = ntohs(port);
13247c478bd9Sstevel@tonic-gate 
13257c478bd9Sstevel@tonic-gate 	if (connect(fd, (struct sockaddr *)sin, sizeof (*sin))) {
13267c478bd9Sstevel@tonic-gate 
13277c478bd9Sstevel@tonic-gate 		perror("rexd: connect");
13287c478bd9Sstevel@tonic-gate 		exit(1);
13297c478bd9Sstevel@tonic-gate 	}
13307c478bd9Sstevel@tonic-gate 
13317c478bd9Sstevel@tonic-gate 	return (fd);
13327c478bd9Sstevel@tonic-gate }
13337c478bd9Sstevel@tonic-gate 
13347c478bd9Sstevel@tonic-gate void
sigwinch(int junk)13357c478bd9Sstevel@tonic-gate sigwinch(int junk)
13367c478bd9Sstevel@tonic-gate {
13377c478bd9Sstevel@tonic-gate }
13387c478bd9Sstevel@tonic-gate 
13397c478bd9Sstevel@tonic-gate /*
13407c478bd9Sstevel@tonic-gate  *  SETPROCTITLE -- set the title of this process for "ps"
13417c478bd9Sstevel@tonic-gate  *
13427c478bd9Sstevel@tonic-gate  *	Does nothing if there were not enough arguments on the command
13437c478bd9Sstevel@tonic-gate  *	line for the information.
13447c478bd9Sstevel@tonic-gate  *
13457c478bd9Sstevel@tonic-gate  *	Side Effects:
13467c478bd9Sstevel@tonic-gate  *		Clobbers argv[] of our main procedure.
13477c478bd9Sstevel@tonic-gate  */
13487c478bd9Sstevel@tonic-gate void
setproctitle(user,host)13497c478bd9Sstevel@tonic-gate setproctitle(user, host)
13507c478bd9Sstevel@tonic-gate char *user, *host;
13517c478bd9Sstevel@tonic-gate {
13527c478bd9Sstevel@tonic-gate 	register char *tohere;
13537c478bd9Sstevel@tonic-gate 
13547c478bd9Sstevel@tonic-gate 	tohere = Argv[0];
13557c478bd9Sstevel@tonic-gate 	if ((int)(LastArgv == NULL) ||
13567c478bd9Sstevel@tonic-gate 	    (int)(strlen(user)+strlen(host)+3) >
13577c478bd9Sstevel@tonic-gate 	    (int)(LastArgv - tohere))
13587c478bd9Sstevel@tonic-gate 		return;
13597c478bd9Sstevel@tonic-gate 
13607c478bd9Sstevel@tonic-gate 	*tohere++ = '-';		/* So ps prints (rpc.rexd)	*/
13617c478bd9Sstevel@tonic-gate 	sprintf(tohere, "%s@%s", user, host);
13627c478bd9Sstevel@tonic-gate 	while (*tohere++)		/* Skip to end of printf output	*/
13637c478bd9Sstevel@tonic-gate 		;
13647c478bd9Sstevel@tonic-gate 	while (tohere < LastArgv)	/* Avoid confusing ps		*/
13657c478bd9Sstevel@tonic-gate 		*tohere++ = ' ';
13667c478bd9Sstevel@tonic-gate }
13677c478bd9Sstevel@tonic-gate 
13687c478bd9Sstevel@tonic-gate 
13697c478bd9Sstevel@tonic-gate /*
13707c478bd9Sstevel@tonic-gate  * Determine if started from inetd or not
13717c478bd9Sstevel@tonic-gate  */
13727c478bd9Sstevel@tonic-gate 
13737c478bd9Sstevel@tonic-gate int
isfrominetd(fd)13747c478bd9Sstevel@tonic-gate isfrominetd(fd)
13757c478bd9Sstevel@tonic-gate int fd;
13767c478bd9Sstevel@tonic-gate {
13777c478bd9Sstevel@tonic-gate 	/*
13787c478bd9Sstevel@tonic-gate 	 * If fd looks like a TLI endpoint, we assume
13797c478bd9Sstevel@tonic-gate 	 * that we were started by a port monitor. If
13807c478bd9Sstevel@tonic-gate 	 * t_getstate fails with TBADF, this is not a
13817c478bd9Sstevel@tonic-gate 	 * TLI endpoint.
13827c478bd9Sstevel@tonic-gate 	 */
13837c478bd9Sstevel@tonic-gate 	if (t_getstate(0) != -1 || t_errno != TBADF)
13847c478bd9Sstevel@tonic-gate 		return (1);
13857c478bd9Sstevel@tonic-gate 	return (0);
13867c478bd9Sstevel@tonic-gate }
1387