xref: /titanic_52/usr/src/cmd/rexd/unix_login.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 /*
23*16ab6e0bSsm26363  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #define	BSD_COMP
307c478bd9Sstevel@tonic-gate #include <errno.h>
317c478bd9Sstevel@tonic-gate #include <fcntl.h>
327c478bd9Sstevel@tonic-gate #include <pwd.h>
337c478bd9Sstevel@tonic-gate #include <signal.h>
347c478bd9Sstevel@tonic-gate #include <stdio.h>
357c478bd9Sstevel@tonic-gate #include <stdlib.h>
367c478bd9Sstevel@tonic-gate #include <unistd.h>
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #include <sac.h>		/* for SC_WILDC */
397c478bd9Sstevel@tonic-gate #include <utmpx.h>
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
427c478bd9Sstevel@tonic-gate #include <sys/file.h>
437c478bd9Sstevel@tonic-gate #include <sys/filio.h>
447c478bd9Sstevel@tonic-gate #include <sys/ioctl.h>
457c478bd9Sstevel@tonic-gate #include <sys/signal.h>
467c478bd9Sstevel@tonic-gate #include <sys/stat.h>
477c478bd9Sstevel@tonic-gate #include <sys/types.h>
487c478bd9Sstevel@tonic-gate #include <sys/wait.h>
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate /*
517c478bd9Sstevel@tonic-gate  * # include <sys/label.h>
527c478bd9Sstevel@tonic-gate  * # include <sys/audit.h>
537c478bd9Sstevel@tonic-gate  *
547c478bd9Sstevel@tonic-gate  *
557c478bd9Sstevel@tonic-gate  *
567c478bd9Sstevel@tonic-gate  * # include <pwdadj.h>
577c478bd9Sstevel@tonic-gate  */
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate #include <sys/ttold.h>
607c478bd9Sstevel@tonic-gate #include <stropts.h>
617c478bd9Sstevel@tonic-gate #include <sys/stream.h>
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate #include "rex.h"
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate #include <security/pam_appl.h>
687c478bd9Sstevel@tonic-gate pam_handle_t *pamh;
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate #define	NTTYDISC	2	/* New ttydiscipline: stolen from ttold.h */
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate /*
737c478bd9Sstevel@tonic-gate  * unix_login - hairy junk to simulate logins for Unix
747c478bd9Sstevel@tonic-gate  */
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate int	Master,	Slave;			/* sides of the pty */
777c478bd9Sstevel@tonic-gate int	Slave_is_closed_on_master_side;
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate static char	*slavename;
807c478bd9Sstevel@tonic-gate extern char *ptsname();
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate int	InputSocket,			/* Network sockets */
847c478bd9Sstevel@tonic-gate 	OutputSocket;
857c478bd9Sstevel@tonic-gate int	Helper1,			/* pids of the helpers */
867c478bd9Sstevel@tonic-gate 	Helper2;
877c478bd9Sstevel@tonic-gate char	UserName[256];			/* saves the user name for loging */
887c478bd9Sstevel@tonic-gate char	HostName[256];			/* saves the host name for loging */
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate static	int	TtySlot;		/* slot number in Utmpx */
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate /*
937c478bd9Sstevel@tonic-gate  * pseudo-xprts used to add pty fds to svc_pollfd[]. This allows the
947c478bd9Sstevel@tonic-gate  * polling for all i/o in one poll().
957c478bd9Sstevel@tonic-gate  */
967c478bd9Sstevel@tonic-gate SVCXPRT uxprt[2];
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate #define	INPUTSOCKET	0		/* InputSocket xprt */
997c478bd9Sstevel@tonic-gate #define	MASTER		1		/* Master xprt */
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate extern	int child;		/* pid of the executed process */
1037c478bd9Sstevel@tonic-gate extern	int ChildDied;		/* flag */
1047c478bd9Sstevel@tonic-gate extern	int HasHelper;		/* flag */
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate extern	void setproctitle(char *user, char *host);
1077c478bd9Sstevel@tonic-gate extern int Debug;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate extern void audit_rexd_fail(char *, char *, char *, uid_t, gid_t,
1107c478bd9Sstevel@tonic-gate 				char *, char **);
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate #define	bzero(s, n)	memset((s), 0, (n))
1137c478bd9Sstevel@tonic-gate #define	bcopy(a, b, c)	memcpy((b), (a), (c))
1147c478bd9Sstevel@tonic-gate 
115*16ab6e0bSsm26363 static void LogoutUser(void);
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate /*
1187c478bd9Sstevel@tonic-gate  * Check for user being able to run on this machine.
1197c478bd9Sstevel@tonic-gate  * returns 0 if OK, TRUE if problem, error message in "error"
1207c478bd9Sstevel@tonic-gate  * copies name of shell and home directory if user is valid.
1217c478bd9Sstevel@tonic-gate  */
1227c478bd9Sstevel@tonic-gate int
1237c478bd9Sstevel@tonic-gate ValidUser(host, uid, gid, error, shell, dir, rst)
1247c478bd9Sstevel@tonic-gate 	char *host;		/* passed in */
1257c478bd9Sstevel@tonic-gate 	uid_t uid;
1267c478bd9Sstevel@tonic-gate 	gid_t gid;
1277c478bd9Sstevel@tonic-gate 	char *error;		/* filled in on return */
1287c478bd9Sstevel@tonic-gate 	char *shell;		/* filled in on return */
1297c478bd9Sstevel@tonic-gate 	char *dir;		/* filled in on return */
1307c478bd9Sstevel@tonic-gate 	struct rex_start *rst;	/* passed in */
1317c478bd9Sstevel@tonic-gate {
1327c478bd9Sstevel@tonic-gate 	struct passwd *pw, *getpwuid();
1337c478bd9Sstevel@tonic-gate 	int v;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	pw = getpwuid(uid);
1367c478bd9Sstevel@tonic-gate 	if (pw == NULL || pw->pw_name == NULL)
1377c478bd9Sstevel@tonic-gate 	{
1387c478bd9Sstevel@tonic-gate 		errprintf(error, "rexd: User id %d not valid\n", uid);
1397c478bd9Sstevel@tonic-gate 		audit_rexd_fail("user id is not valid",
1407c478bd9Sstevel@tonic-gate 				host,
1417c478bd9Sstevel@tonic-gate 				NULL,
1427c478bd9Sstevel@tonic-gate 				uid,
1437c478bd9Sstevel@tonic-gate 				gid,
1447c478bd9Sstevel@tonic-gate 				NULL,
1457c478bd9Sstevel@tonic-gate 				rst->rst_cmd);	    /* BSM */
1467c478bd9Sstevel@tonic-gate 		return (1);
1477c478bd9Sstevel@tonic-gate 	}
1487c478bd9Sstevel@tonic-gate 	strncpy(UserName, pw->pw_name, sizeof (UserName) - 1);
1497c478bd9Sstevel@tonic-gate 	strncpy(HostName, host, sizeof (HostName) - 1);
1507c478bd9Sstevel@tonic-gate 	strcpy(shell, pw->pw_shell);
1517c478bd9Sstevel@tonic-gate 	strcpy(dir, pw->pw_dir);
1527c478bd9Sstevel@tonic-gate 	setproctitle(pw->pw_name, host);
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	if (pam_start("rexd", pw->pw_name, NULL, &pamh) != PAM_SUCCESS ||
1557c478bd9Sstevel@tonic-gate 	    pam_set_item(pamh, PAM_RHOST, host) != PAM_SUCCESS) {
1567c478bd9Sstevel@tonic-gate 		audit_rexd_fail("user id is not valid",
1577c478bd9Sstevel@tonic-gate 				host,
1587c478bd9Sstevel@tonic-gate 				pw->pw_name,
1597c478bd9Sstevel@tonic-gate 				uid,
1607c478bd9Sstevel@tonic-gate 				gid,
1617c478bd9Sstevel@tonic-gate 				shell,
1627c478bd9Sstevel@tonic-gate 				rst->rst_cmd);	    /* BSM */
1637c478bd9Sstevel@tonic-gate 		errprintf(error, "rexd: User id %d not valid\n", uid);
1647c478bd9Sstevel@tonic-gate 		if (pamh) {
1657c478bd9Sstevel@tonic-gate 			pam_end(pamh, PAM_ABORT);
1667c478bd9Sstevel@tonic-gate 			pamh = NULL;
1677c478bd9Sstevel@tonic-gate 		}
1687c478bd9Sstevel@tonic-gate 		return (1);
1697c478bd9Sstevel@tonic-gate 	}
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 	if ((v = pam_acct_mgmt(pamh, 0)) != PAM_SUCCESS) {
1727c478bd9Sstevel@tonic-gate 		switch (v) {
1737c478bd9Sstevel@tonic-gate 		case PAM_NEW_AUTHTOK_REQD:
1747c478bd9Sstevel@tonic-gate 			errprintf(error,
1757c478bd9Sstevel@tonic-gate 				"rexd: User id %d Password Expired\n", uid);
1767c478bd9Sstevel@tonic-gate 			break;
1777c478bd9Sstevel@tonic-gate 		case PAM_PERM_DENIED:
1787c478bd9Sstevel@tonic-gate 			errprintf(error,
1797c478bd9Sstevel@tonic-gate 				"rexd: User id %d Account Expired\n", uid);
1807c478bd9Sstevel@tonic-gate 			break;
1817c478bd9Sstevel@tonic-gate 		case PAM_AUTHTOK_EXPIRED:
1827c478bd9Sstevel@tonic-gate 			errprintf(error,
1837c478bd9Sstevel@tonic-gate 				"rexd: User id %d Password Expired\n", uid);
1847c478bd9Sstevel@tonic-gate 			break;
1857c478bd9Sstevel@tonic-gate 		default:
1867c478bd9Sstevel@tonic-gate 			errprintf(error,
1877c478bd9Sstevel@tonic-gate 				"rexd: User id %d not valid\n", uid);
1887c478bd9Sstevel@tonic-gate 			break;
1897c478bd9Sstevel@tonic-gate 		}
1907c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_ABORT);
1917c478bd9Sstevel@tonic-gate 		pamh = NULL;
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 		audit_rexd_fail("user account expired",
1947c478bd9Sstevel@tonic-gate 				host,
1957c478bd9Sstevel@tonic-gate 				pw->pw_name,
1967c478bd9Sstevel@tonic-gate 				uid,
1977c478bd9Sstevel@tonic-gate 				gid,
1987c478bd9Sstevel@tonic-gate 				shell,
1997c478bd9Sstevel@tonic-gate 				rst->rst_cmd);	    /* BSM */
2007c478bd9Sstevel@tonic-gate 		return (1);
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	return (0);
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate /*
2077c478bd9Sstevel@tonic-gate  * Add an audit record with argv that was pre-set, plus the given string
2087c478bd9Sstevel@tonic-gate  */
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate /*
2117c478bd9Sstevel@tonic-gate  * Allocate a pseudo-terminal
2127c478bd9Sstevel@tonic-gate  * sets the global variables Master and Slave.
2137c478bd9Sstevel@tonic-gate  * returns 1 on error, 0 if OK
2147c478bd9Sstevel@tonic-gate  */
2157c478bd9Sstevel@tonic-gate int
2167c478bd9Sstevel@tonic-gate AllocatePty(socket0, socket1)
2177c478bd9Sstevel@tonic-gate 	int socket0, socket1;
2187c478bd9Sstevel@tonic-gate {
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	int on = 1;
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	sigset(SIGHUP, SIG_IGN);
2237c478bd9Sstevel@tonic-gate 	sigset(SIGTTOU, SIG_IGN);
2247c478bd9Sstevel@tonic-gate 	sigset(SIGTTIN, SIG_IGN);
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	if ((Master = open("/dev/ptmx", O_RDWR)) == -1) {
2277c478bd9Sstevel@tonic-gate 	    if (Debug)
2287c478bd9Sstevel@tonic-gate 		    printf("open-ptmx-failure\n");
2297c478bd9Sstevel@tonic-gate 	    perror("AloocatePtyMaster fails");
2307c478bd9Sstevel@tonic-gate 	    return (1);		/* error could not open /dev/ptmx */
2317c478bd9Sstevel@tonic-gate 	}
2327c478bd9Sstevel@tonic-gate 	if (Debug)
2337c478bd9Sstevel@tonic-gate 	    printf("open-ptmx success Master =%d\n", Master);
2347c478bd9Sstevel@tonic-gate 	if (Debug)
2357c478bd9Sstevel@tonic-gate 	    printf("Before grantpt...Master=%d\n", Master);
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	if (grantpt(Master) == -1) {
2387c478bd9Sstevel@tonic-gate 	    perror("could not grant slave pty");
2397c478bd9Sstevel@tonic-gate 	    exit(1);
2407c478bd9Sstevel@tonic-gate 	}
2417c478bd9Sstevel@tonic-gate 	if (unlockpt(Master) == -1) {
2427c478bd9Sstevel@tonic-gate 	    perror("could not unlock slave pty");
2437c478bd9Sstevel@tonic-gate 	    exit(1);
2447c478bd9Sstevel@tonic-gate 	}
2457c478bd9Sstevel@tonic-gate 	if ((slavename = ptsname(Master)) == NULL) {
2467c478bd9Sstevel@tonic-gate 	    perror("could not enable slave pty");
2477c478bd9Sstevel@tonic-gate 	    exit(1);
2487c478bd9Sstevel@tonic-gate 	}
2497c478bd9Sstevel@tonic-gate 	if ((Slave = open(slavename, O_RDWR)) == -1) {
2507c478bd9Sstevel@tonic-gate 	    perror("could not open slave pty");
2517c478bd9Sstevel@tonic-gate 	    exit(1);
2527c478bd9Sstevel@tonic-gate 	}
2537c478bd9Sstevel@tonic-gate 	if (ioctl(Slave, I_PUSH, "ptem") == -1) {
2547c478bd9Sstevel@tonic-gate 	    perror("ioctl I_PUSH ptem");
2557c478bd9Sstevel@tonic-gate 	    exit(1);
2567c478bd9Sstevel@tonic-gate 	}
2577c478bd9Sstevel@tonic-gate 	if (ioctl(Slave, I_PUSH, "ldterm") == -1) {
2587c478bd9Sstevel@tonic-gate 	    perror("ioctl I_PUSH ldterm");
2597c478bd9Sstevel@tonic-gate 	    exit(1);
2607c478bd9Sstevel@tonic-gate 	}
2617c478bd9Sstevel@tonic-gate 	if (ioctl(Slave, I_PUSH, "ttcompat") == -1) {
2627c478bd9Sstevel@tonic-gate 	    perror("ioctl I_PUSH ttcompat");
2637c478bd9Sstevel@tonic-gate 	    exit(1);
2647c478bd9Sstevel@tonic-gate 	}
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	Slave_is_closed_on_master_side = FALSE;
2677c478bd9Sstevel@tonic-gate 	setsid(); /* get rid of controlling terminal */
2687c478bd9Sstevel@tonic-gate 	/* LoginUser(); */
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 	InputSocket = socket0;
2717c478bd9Sstevel@tonic-gate 	OutputSocket = socket1;
2727c478bd9Sstevel@tonic-gate 	ioctl(Master, FIONBIO, &on);
2737c478bd9Sstevel@tonic-gate 	uxprt[INPUTSOCKET].xp_fd = InputSocket;
2747c478bd9Sstevel@tonic-gate 	xprt_register(&uxprt[INPUTSOCKET]);
2757c478bd9Sstevel@tonic-gate 	uxprt[MASTER].xp_fd = Master;
2767c478bd9Sstevel@tonic-gate 	xprt_register(&uxprt[MASTER]);
2777c478bd9Sstevel@tonic-gate 	return (0);
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate void
2827c478bd9Sstevel@tonic-gate OpenPtySlave()
2837c478bd9Sstevel@tonic-gate {
2847c478bd9Sstevel@tonic-gate 	close(Slave);
2857c478bd9Sstevel@tonic-gate 	Slave = open(slavename, O_RDWR);
2867c478bd9Sstevel@tonic-gate 	if (Slave < 0) {
2877c478bd9Sstevel@tonic-gate 		perror(slavename);
2887c478bd9Sstevel@tonic-gate 		exit(1);
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	/*
2957c478bd9Sstevel@tonic-gate 	 * Special processing for interactive operation.
2967c478bd9Sstevel@tonic-gate 	 * Given pointers to three standard file descriptors,
2977c478bd9Sstevel@tonic-gate 	 * which get set to point to the pty.
2987c478bd9Sstevel@tonic-gate 	 */
2997c478bd9Sstevel@tonic-gate void
3007c478bd9Sstevel@tonic-gate DoHelper(pfd0, pfd1, pfd2)
3017c478bd9Sstevel@tonic-gate 	int *pfd0, *pfd1, *pfd2;
3027c478bd9Sstevel@tonic-gate {
3037c478bd9Sstevel@tonic-gate 	int pgrp;
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	sigset(SIGINT, SIG_IGN);
3077c478bd9Sstevel@tonic-gate 	close(Master);
3087c478bd9Sstevel@tonic-gate 	close(InputSocket);
3097c478bd9Sstevel@tonic-gate 	close(OutputSocket);
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	*pfd0 = Slave;
3127c478bd9Sstevel@tonic-gate 	*pfd1 = Slave;
3137c478bd9Sstevel@tonic-gate 	*pfd2 = Slave;
3147c478bd9Sstevel@tonic-gate }
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate /*
3187c478bd9Sstevel@tonic-gate  * destroy the helpers when the executing process dies
3197c478bd9Sstevel@tonic-gate  */
320*16ab6e0bSsm26363 void
321*16ab6e0bSsm26363 KillHelper(int grp)
3227c478bd9Sstevel@tonic-gate {
3237c478bd9Sstevel@tonic-gate 	if (Debug)
3247c478bd9Sstevel@tonic-gate 		printf("Enter KillHelper\n");
3257c478bd9Sstevel@tonic-gate 	close(Master);
3267c478bd9Sstevel@tonic-gate 	xprt_unregister(&uxprt[MASTER]);
3277c478bd9Sstevel@tonic-gate 	close(InputSocket);
3287c478bd9Sstevel@tonic-gate 	xprt_unregister(&uxprt[INPUTSOCKET]);
3297c478bd9Sstevel@tonic-gate 	close(OutputSocket);
3307c478bd9Sstevel@tonic-gate 	LogoutUser();
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	if (grp)
3337c478bd9Sstevel@tonic-gate 	    kill((-grp), SIGKILL);
3347c478bd9Sstevel@tonic-gate }
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate /*
3387c478bd9Sstevel@tonic-gate  * edit the Unix traditional data files that tell who is logged
3397c478bd9Sstevel@tonic-gate  * into "the system"
3407c478bd9Sstevel@tonic-gate  */
3417c478bd9Sstevel@tonic-gate unsigned char	utid[] = {'o', 'n', SC_WILDC, SC_WILDC};
3427c478bd9Sstevel@tonic-gate 
343*16ab6e0bSsm26363 void
344*16ab6e0bSsm26363 LoginUser(void)
3457c478bd9Sstevel@tonic-gate {
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	char *user;
3487c478bd9Sstevel@tonic-gate 	char *rhost;
3497c478bd9Sstevel@tonic-gate 	/* the next 4 variables are needed for utmpx mgmt */
3507c478bd9Sstevel@tonic-gate 	int		tmplen;
3517c478bd9Sstevel@tonic-gate 	struct utmpx	*u = NULL;
3527c478bd9Sstevel@tonic-gate 	struct utmpx	set_utmp;
3537c478bd9Sstevel@tonic-gate 	char		*ttyntail;
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	/* We're pretty drastic here, exiting if an error is detected */
3567c478bd9Sstevel@tonic-gate 	if (pam_set_item(pamh, PAM_TTY, slavename)	!= PAM_SUCCESS ||
3577c478bd9Sstevel@tonic-gate 	    pam_get_item(pamh, PAM_USER, (void **) &user) != PAM_SUCCESS ||
3587c478bd9Sstevel@tonic-gate 	    pam_get_item(pamh, PAM_RHOST, (void **) &rhost) != PAM_SUCCESS ||
3597c478bd9Sstevel@tonic-gate 	    pam_open_session(pamh, 0)			!= PAM_SUCCESS) {
3607c478bd9Sstevel@tonic-gate 		/*
3617c478bd9Sstevel@tonic-gate 		 * XXX should print something but for now we exit
3627c478bd9Sstevel@tonic-gate 		 */
3637c478bd9Sstevel@tonic-gate 		exit(1);
3647c478bd9Sstevel@tonic-gate 	}
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	(void) memset((void *)&set_utmp, 0, sizeof (set_utmp));
3677c478bd9Sstevel@tonic-gate 	(void) time(&set_utmp.ut_tv.tv_sec);
3687c478bd9Sstevel@tonic-gate 	set_utmp.ut_pid = getpid();
3697c478bd9Sstevel@tonic-gate 	if (rhost != NULL && rhost[0] != '\0') {
3707c478bd9Sstevel@tonic-gate 		(void) strcpy(set_utmp.ut_host, rhost);
3717c478bd9Sstevel@tonic-gate 		tmplen = strlen(rhost) + 1;
3727c478bd9Sstevel@tonic-gate 		if (tmplen < sizeof (set_utmp.ut_host))
3737c478bd9Sstevel@tonic-gate 			set_utmp.ut_syslen = tmplen;
3747c478bd9Sstevel@tonic-gate 		else
3757c478bd9Sstevel@tonic-gate 			set_utmp.ut_syslen = sizeof (set_utmp.ut_host);
3767c478bd9Sstevel@tonic-gate 	} else {
3777c478bd9Sstevel@tonic-gate 		(void) memset(set_utmp.ut_host, 0, sizeof (set_utmp.ut_host));
3787c478bd9Sstevel@tonic-gate 		set_utmp.ut_syslen = 0;
3797c478bd9Sstevel@tonic-gate 	}
3807c478bd9Sstevel@tonic-gate 	(void) strcpy(set_utmp.ut_user, user);
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	/*
3837c478bd9Sstevel@tonic-gate 	 * Copy in the name of the tty minus the "/dev/" if a /dev/ is
3847c478bd9Sstevel@tonic-gate 	 * in the path name.
3857c478bd9Sstevel@tonic-gate 	 */
3867c478bd9Sstevel@tonic-gate 	ttyntail = slavename;
3877c478bd9Sstevel@tonic-gate 	if (strstr(ttyntail, "/dev/") != 0)
3887c478bd9Sstevel@tonic-gate 		ttyntail = ttyntail + strlen("/dev/");
3897c478bd9Sstevel@tonic-gate 	(void) strcpy(set_utmp.ut_line, ttyntail);
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 	set_utmp.ut_type = USER_PROCESS;
3927c478bd9Sstevel@tonic-gate 	if (utid != NULL)
3937c478bd9Sstevel@tonic-gate 		(void) memcpy(set_utmp.ut_id, utid, sizeof (set_utmp.ut_id));
3947c478bd9Sstevel@tonic-gate 	/*
3957c478bd9Sstevel@tonic-gate 	 * Go through each entry one by one, looking only at INIT,
3967c478bd9Sstevel@tonic-gate 	 * LOGIN or USER Processes.  Use the entry found if flags == 0
3977c478bd9Sstevel@tonic-gate 	 * and the line name matches, or if the process ID matches if
3987c478bd9Sstevel@tonic-gate 	 * the UPDATE_ENTRY flag is set.  The UPDATE_ENTRY flag is mainly
3997c478bd9Sstevel@tonic-gate 	 * for login which normally only wants to update an entry if
4007c478bd9Sstevel@tonic-gate 	 * the pid fields matches.
4017c478bd9Sstevel@tonic-gate 	 */
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	if (u == (struct utmpx *)NULL) {
4047c478bd9Sstevel@tonic-gate 		(void) makeutx(&set_utmp);
4057c478bd9Sstevel@tonic-gate 	} else
4067c478bd9Sstevel@tonic-gate 		updwtmpx(WTMPX_FILE, &set_utmp);
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate /*
4117c478bd9Sstevel@tonic-gate  * edit the Unix traditional data files that tell who is logged
4127c478bd9Sstevel@tonic-gate  * into "the system".
4137c478bd9Sstevel@tonic-gate  */
414*16ab6e0bSsm26363 static void
415*16ab6e0bSsm26363 LogoutUser(void)
4167c478bd9Sstevel@tonic-gate {
4177c478bd9Sstevel@tonic-gate 	struct utmpx *up;
4187c478bd9Sstevel@tonic-gate 	struct utmpx ut;
4197c478bd9Sstevel@tonic-gate 	int pid;
4207c478bd9Sstevel@tonic-gate 	char user[sizeof (ut.ut_user) + 1];
4217c478bd9Sstevel@tonic-gate 	char ttyn[sizeof (ut.ut_line) + 1];
4227c478bd9Sstevel@tonic-gate 	char rhost[sizeof (ut.ut_host) + 1];
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	sighold(SIGCHLD);		/* no disruption during cleanup */
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 	if (pamh) {
4277c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_SUCCESS);
4287c478bd9Sstevel@tonic-gate 		pamh = NULL;
4297c478bd9Sstevel@tonic-gate 	}
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	/* BEGIN RESET UTMP */
4327c478bd9Sstevel@tonic-gate 	pid = child;
4337c478bd9Sstevel@tonic-gate 	setutxent();
4347c478bd9Sstevel@tonic-gate 	while (up = getutxent()) {
4357c478bd9Sstevel@tonic-gate 		if (up->ut_pid == pid) {
4367c478bd9Sstevel@tonic-gate 			if (up->ut_type == DEAD_PROCESS) {
4377c478bd9Sstevel@tonic-gate 				/*
4387c478bd9Sstevel@tonic-gate 				 * Cleaned up elsewhere.
4397c478bd9Sstevel@tonic-gate 				 */
4407c478bd9Sstevel@tonic-gate 				break;
4417c478bd9Sstevel@tonic-gate 			}
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 			strncpy(user, up->ut_user, sizeof (up->ut_user));
4447c478bd9Sstevel@tonic-gate 			user[sizeof (up->ut_user)] = '\0';
4457c478bd9Sstevel@tonic-gate 			strncpy(ttyn, up->ut_line, sizeof (up->ut_line));
4467c478bd9Sstevel@tonic-gate 			ttyn[sizeof (up->ut_line)] = '\0';
4477c478bd9Sstevel@tonic-gate 			strncpy(rhost, up->ut_host, sizeof (up->ut_host));
4487c478bd9Sstevel@tonic-gate 			rhost[sizeof (up->ut_host)] = '\0';
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate 			if ((pam_start("rexd", user, NULL, &pamh))
4517c478bd9Sstevel@tonic-gate 							== PAM_SUCCESS) {
4527c478bd9Sstevel@tonic-gate 				(void) pam_set_item(pamh, PAM_TTY, ttyn);
4537c478bd9Sstevel@tonic-gate 				(void) pam_set_item(pamh, PAM_RHOST, rhost);
4547c478bd9Sstevel@tonic-gate 				(void) pam_close_session(pamh, 0);
4557c478bd9Sstevel@tonic-gate 				(void) pam_end(pamh, PAM_SUCCESS);
4567c478bd9Sstevel@tonic-gate 				pamh = NULL;
4577c478bd9Sstevel@tonic-gate 			}
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 			up->ut_type = DEAD_PROCESS;
4607c478bd9Sstevel@tonic-gate 			up->ut_exit.e_termination = WTERMSIG(0);
4617c478bd9Sstevel@tonic-gate 			up->ut_exit.e_exit = WEXITSTATUS(0);
4627c478bd9Sstevel@tonic-gate 			(void) time(&up->ut_tv.tv_sec);
4637c478bd9Sstevel@tonic-gate 			if (modutx(up) == NULL) {
4647c478bd9Sstevel@tonic-gate 				/*
4657c478bd9Sstevel@tonic-gate 				 * Since modutx failed we'll
4667c478bd9Sstevel@tonic-gate 				 * write out the new entry
4677c478bd9Sstevel@tonic-gate 				 * ourselves.
4687c478bd9Sstevel@tonic-gate 				 */
4697c478bd9Sstevel@tonic-gate 				(void) pututxline(up);
4707c478bd9Sstevel@tonic-gate 				updwtmpx("wtmpx", up);
4717c478bd9Sstevel@tonic-gate 			}
4727c478bd9Sstevel@tonic-gate 			break;
4737c478bd9Sstevel@tonic-gate 		}
4747c478bd9Sstevel@tonic-gate 	}
4757c478bd9Sstevel@tonic-gate 	endutxent();
4767c478bd9Sstevel@tonic-gate 	/* END RESET UTMP */
4777c478bd9Sstevel@tonic-gate 	sigrelse(SIGCHLD);
4787c478bd9Sstevel@tonic-gate }
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate /*
4817c478bd9Sstevel@tonic-gate  * set the pty modes to the given values
4827c478bd9Sstevel@tonic-gate  */
483*16ab6e0bSsm26363 void
4847c478bd9Sstevel@tonic-gate SetPtyMode(mode)
4857c478bd9Sstevel@tonic-gate 	struct rex_ttymode *mode;
4867c478bd9Sstevel@tonic-gate {
4877c478bd9Sstevel@tonic-gate 	struct sgttyb svr4_sgttyb_var;
4887c478bd9Sstevel@tonic-gate 	int ldisc = NTTYDISC;
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 	if (Debug)
4917c478bd9Sstevel@tonic-gate 		printf("Enter SetPtyMode\n");
4927c478bd9Sstevel@tonic-gate 	if (Debug)
4937c478bd9Sstevel@tonic-gate 		printf("SetPtyMode:opened slave\n");
4947c478bd9Sstevel@tonic-gate 	ioctl(Slave, TIOCSETD, &ldisc);
4957c478bd9Sstevel@tonic-gate 	if (Debug)
4967c478bd9Sstevel@tonic-gate 		printf("SetPtyMode:Slave TIOCSETD done\n");
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	/*
4997c478bd9Sstevel@tonic-gate 	 * Copy from over-the-net(bsd) to SVR4 format
5007c478bd9Sstevel@tonic-gate 	 */
5017c478bd9Sstevel@tonic-gate 	svr4_sgttyb_var.sg_ispeed = mode->basic.sg_ispeed;
5027c478bd9Sstevel@tonic-gate 	svr4_sgttyb_var.sg_ospeed = mode->basic.sg_ospeed;
5037c478bd9Sstevel@tonic-gate 	svr4_sgttyb_var.sg_erase  = mode->basic.sg_erase;
5047c478bd9Sstevel@tonic-gate 	svr4_sgttyb_var.sg_kill = mode->basic.sg_kill;
5057c478bd9Sstevel@tonic-gate 	svr4_sgttyb_var.sg_flags = (int)mode->basic.sg_flags;
5067c478bd9Sstevel@tonic-gate 	/*
5077c478bd9Sstevel@tonic-gate 	 * Clear any possible sign extension caused by (int)
5087c478bd9Sstevel@tonic-gate 	 * typecast
5097c478bd9Sstevel@tonic-gate 	 */
5107c478bd9Sstevel@tonic-gate 	svr4_sgttyb_var.sg_flags &= 0xFFFF;
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	ioctl(Slave, TIOCSETN, &svr4_sgttyb_var);
5137c478bd9Sstevel@tonic-gate 	if (Debug)
5147c478bd9Sstevel@tonic-gate 		printf("SetPtyMode:Slave TIOCSETN done\n");
5157c478bd9Sstevel@tonic-gate 	ioctl(Slave, TIOCSETC, &mode->more);
5167c478bd9Sstevel@tonic-gate 	if (Debug)
5177c478bd9Sstevel@tonic-gate 		printf("SetPtyMode:Slave TIOCSETC done\n");
5187c478bd9Sstevel@tonic-gate 	ioctl(Slave, TIOCSLTC, &mode->yetmore);
5197c478bd9Sstevel@tonic-gate 	if (Debug)
5207c478bd9Sstevel@tonic-gate 		printf("SetPtyMode:Slave TIOCSLTC done\n");
5217c478bd9Sstevel@tonic-gate 	ioctl(Slave, TIOCLSET, &mode->andmore);
5227c478bd9Sstevel@tonic-gate 	if (Debug)
5237c478bd9Sstevel@tonic-gate 		printf("SetPtyMode:Slave TIOCSET done\n");
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	/* Opened in AllocPty for parent, still open in child */
5267c478bd9Sstevel@tonic-gate 	if (Slave_is_closed_on_master_side == FALSE) {
5277c478bd9Sstevel@tonic-gate 		close(Slave);
5287c478bd9Sstevel@tonic-gate 		Slave_is_closed_on_master_side = TRUE;
5297c478bd9Sstevel@tonic-gate 	}
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate /*
5337c478bd9Sstevel@tonic-gate  * set the pty window size to the given value
5347c478bd9Sstevel@tonic-gate  */
535*16ab6e0bSsm26363 void
536*16ab6e0bSsm26363 SetPtySize(struct rex_ttysize *sizep)
5377c478bd9Sstevel@tonic-gate {
5387c478bd9Sstevel@tonic-gate 	struct winsize newsize;
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 	/* if size has changed, this ioctl changes it */
5417c478bd9Sstevel@tonic-gate 	/* *and* sends SIGWINCH to process group */
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 	newsize.ws_row = (unsigned short) sizep->ts_lines;
5447c478bd9Sstevel@tonic-gate 	newsize.ws_col = (unsigned short) sizep->ts_cols;
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 	(void) ioctl(Master, TIOCSWINSZ, &newsize);
5477c478bd9Sstevel@tonic-gate 	if (Slave_is_closed_on_master_side == FALSE) {
5487c478bd9Sstevel@tonic-gate 		close(Slave);
5497c478bd9Sstevel@tonic-gate 		Slave_is_closed_on_master_side = TRUE;
5507c478bd9Sstevel@tonic-gate 	}
5517c478bd9Sstevel@tonic-gate }
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate /*
5557c478bd9Sstevel@tonic-gate  * send the given signal to the group controlling the terminal
5567c478bd9Sstevel@tonic-gate  */
557*16ab6e0bSsm26363 void
558*16ab6e0bSsm26363 SendSignal(int sig)
5597c478bd9Sstevel@tonic-gate {
5607c478bd9Sstevel@tonic-gate 	pid_t pgrp;
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate 	pgrp = getpgid(child);
5637c478bd9Sstevel@tonic-gate 	if (pgrp != (pid_t)-1)
5647c478bd9Sstevel@tonic-gate 		(void) kill((-pgrp), sig);
5657c478bd9Sstevel@tonic-gate }
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate /*
5687c478bd9Sstevel@tonic-gate  * called when the main select loop detects that we might want to
5697c478bd9Sstevel@tonic-gate  * read something.
5707c478bd9Sstevel@tonic-gate  */
5717c478bd9Sstevel@tonic-gate void
5727c478bd9Sstevel@tonic-gate HelperRead(pollfd_t *fdp, int nfds, int *pollretval)
5737c478bd9Sstevel@tonic-gate {
5747c478bd9Sstevel@tonic-gate 	char buf[128];
5757c478bd9Sstevel@tonic-gate 	int retval;
5767c478bd9Sstevel@tonic-gate 	extern int errno;
5777c478bd9Sstevel@tonic-gate 	int mask;
5787c478bd9Sstevel@tonic-gate 	int master = -1;
5797c478bd9Sstevel@tonic-gate 	int inputsocket = -1;
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 	/*
5827c478bd9Sstevel@tonic-gate 	 * fdp pollset may be compressed. Search for Master and
5837c478bd9Sstevel@tonic-gate 	 * InputSocket fds.
5847c478bd9Sstevel@tonic-gate 	 */
5857c478bd9Sstevel@tonic-gate 	int i;
5867c478bd9Sstevel@tonic-gate 	for (i = 0; i < nfds; i++) {
5877c478bd9Sstevel@tonic-gate 		if (fdp[i].fd == Master && fdp[i].revents != 0)
5887c478bd9Sstevel@tonic-gate 			master = i;
5897c478bd9Sstevel@tonic-gate 		if (fdp[i].fd == InputSocket && fdp[i].revents != 0)
5907c478bd9Sstevel@tonic-gate 			inputsocket = i;
5917c478bd9Sstevel@tonic-gate 	}
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate /*	mask = sigsetmask (sigmask (SIGCHLD));	*/
5947c478bd9Sstevel@tonic-gate 	mask = sighold(SIGCHLD);
5957c478bd9Sstevel@tonic-gate 	retval = 0;
5967c478bd9Sstevel@tonic-gate 	if (master != -1) {
5977c478bd9Sstevel@tonic-gate 		if (!(fdp[master].revents & (POLLERR | POLLHUP | POLLNVAL))) {
5987c478bd9Sstevel@tonic-gate 			retval = read(Master, buf, sizeof (buf));
5997c478bd9Sstevel@tonic-gate 			if (retval > 0) {
6007c478bd9Sstevel@tonic-gate 				(void) write(OutputSocket, buf, retval);
6017c478bd9Sstevel@tonic-gate 			} else {
6027c478bd9Sstevel@tonic-gate 				if (errno != EINTR && errno != EIO &&
6037c478bd9Sstevel@tonic-gate 				    errno != EWOULDBLOCK)
6047c478bd9Sstevel@tonic-gate 					perror("pty read");
6057c478bd9Sstevel@tonic-gate 				/* 1 => further sends disallowed */
6067c478bd9Sstevel@tonic-gate 				shutdown(OutputSocket, 1);
6077c478bd9Sstevel@tonic-gate 				xprt_unregister(&uxprt[MASTER]);
6087c478bd9Sstevel@tonic-gate 			}
6097c478bd9Sstevel@tonic-gate 		}
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 		/* clear this event for svc_getreq_poll */
6127c478bd9Sstevel@tonic-gate 		fdp[master].revents = 0;
6137c478bd9Sstevel@tonic-gate 		*pollretval = *pollretval - 1;
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 		if (retval <= 0 && ChildDied) {
6167c478bd9Sstevel@tonic-gate 			KillHelper(child);
6177c478bd9Sstevel@tonic-gate 			HasHelper = 0;
6187c478bd9Sstevel@tonic-gate 			if (inputsocket != -1) {
6197c478bd9Sstevel@tonic-gate 				fdp[inputsocket].revents = 0;
6207c478bd9Sstevel@tonic-gate 				*pollretval = *pollretval - 1;
6217c478bd9Sstevel@tonic-gate 			}
6227c478bd9Sstevel@tonic-gate 			goto done;
6237c478bd9Sstevel@tonic-gate 		}
6247c478bd9Sstevel@tonic-gate 	}
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 	if (inputsocket != -1) {
6277c478bd9Sstevel@tonic-gate 		if (!(fdp[inputsocket].revents & (POLLERR | POLLHUP |
6287c478bd9Sstevel@tonic-gate 							    POLLNVAL))) {
6297c478bd9Sstevel@tonic-gate 			retval = read(InputSocket, buf, sizeof (buf));
6307c478bd9Sstevel@tonic-gate 			if (retval > 0) {
6317c478bd9Sstevel@tonic-gate 				(void) write(Master, buf, retval);
6327c478bd9Sstevel@tonic-gate 			} else {
6337c478bd9Sstevel@tonic-gate 				if (errno != EINTR && errno != EWOULDBLOCK)
6347c478bd9Sstevel@tonic-gate 					perror("socket read");
6357c478bd9Sstevel@tonic-gate 				xprt_unregister(&uxprt[INPUTSOCKET]);
6367c478bd9Sstevel@tonic-gate 			}
6377c478bd9Sstevel@tonic-gate 		}
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 		/* clear this event for svc_getreq_poll */
6407c478bd9Sstevel@tonic-gate 		fdp[inputsocket].revents = 0;
6417c478bd9Sstevel@tonic-gate 		*pollretval = *pollretval - 1;
6427c478bd9Sstevel@tonic-gate 	}
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 	done:
6457c478bd9Sstevel@tonic-gate /*	sigsetmask (mask);	*/
6467c478bd9Sstevel@tonic-gate 	sigrelse(SIGCHLD);
6477c478bd9Sstevel@tonic-gate }
648