xref: /titanic_52/usr/src/cmd/rexd/unix_login.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 1998-1999,2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #define	BSD_COMP
30*7c478bd9Sstevel@tonic-gate #include <errno.h>
31*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
32*7c478bd9Sstevel@tonic-gate #include <pwd.h>
33*7c478bd9Sstevel@tonic-gate #include <signal.h>
34*7c478bd9Sstevel@tonic-gate #include <stdio.h>
35*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
36*7c478bd9Sstevel@tonic-gate #include <unistd.h>
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate #include <sac.h>		/* for SC_WILDC */
39*7c478bd9Sstevel@tonic-gate #include <utmpx.h>
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/filio.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/ioctl.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/signal.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/wait.h>
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate /*
51*7c478bd9Sstevel@tonic-gate  * # include <sys/label.h>
52*7c478bd9Sstevel@tonic-gate  * # include <sys/audit.h>
53*7c478bd9Sstevel@tonic-gate  *
54*7c478bd9Sstevel@tonic-gate  *
55*7c478bd9Sstevel@tonic-gate  *
56*7c478bd9Sstevel@tonic-gate  * # include <pwdadj.h>
57*7c478bd9Sstevel@tonic-gate  */
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate #include <sys/ttold.h>
60*7c478bd9Sstevel@tonic-gate #include <stropts.h>
61*7c478bd9Sstevel@tonic-gate #include <sys/stream.h>
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate #include "rex.h"
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate #include <security/pam_appl.h>
68*7c478bd9Sstevel@tonic-gate pam_handle_t *pamh;
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate #define	NTTYDISC	2	/* New ttydiscipline: stolen from ttold.h */
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate /*
73*7c478bd9Sstevel@tonic-gate  * unix_login - hairy junk to simulate logins for Unix
74*7c478bd9Sstevel@tonic-gate  */
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate int	Master,	Slave;			/* sides of the pty */
77*7c478bd9Sstevel@tonic-gate int	Slave_is_closed_on_master_side;
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate static char	*slavename;
80*7c478bd9Sstevel@tonic-gate extern char *ptsname();
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate int	InputSocket,			/* Network sockets */
84*7c478bd9Sstevel@tonic-gate 	OutputSocket;
85*7c478bd9Sstevel@tonic-gate int	Helper1,			/* pids of the helpers */
86*7c478bd9Sstevel@tonic-gate 	Helper2;
87*7c478bd9Sstevel@tonic-gate char	UserName[256];			/* saves the user name for loging */
88*7c478bd9Sstevel@tonic-gate char	HostName[256];			/* saves the host name for loging */
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate static	int	TtySlot;		/* slot number in Utmpx */
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate /*
93*7c478bd9Sstevel@tonic-gate  * pseudo-xprts used to add pty fds to svc_pollfd[]. This allows the
94*7c478bd9Sstevel@tonic-gate  * polling for all i/o in one poll().
95*7c478bd9Sstevel@tonic-gate  */
96*7c478bd9Sstevel@tonic-gate SVCXPRT uxprt[2];
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate #define	INPUTSOCKET	0		/* InputSocket xprt */
99*7c478bd9Sstevel@tonic-gate #define	MASTER		1		/* Master xprt */
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate extern	int child;		/* pid of the executed process */
103*7c478bd9Sstevel@tonic-gate extern	int ChildDied;		/* flag */
104*7c478bd9Sstevel@tonic-gate extern	int HasHelper;		/* flag */
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate extern	void setproctitle(char *user, char *host);
107*7c478bd9Sstevel@tonic-gate extern int Debug;
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate extern void audit_rexd_fail(char *, char *, char *, uid_t, gid_t,
110*7c478bd9Sstevel@tonic-gate 				char *, char **);
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate #define	bzero(s, n)	memset((s), 0, (n))
113*7c478bd9Sstevel@tonic-gate #define	bcopy(a, b, c)	memcpy((b), (a), (c))
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate /*
117*7c478bd9Sstevel@tonic-gate  * Check for user being able to run on this machine.
118*7c478bd9Sstevel@tonic-gate  * returns 0 if OK, TRUE if problem, error message in "error"
119*7c478bd9Sstevel@tonic-gate  * copies name of shell and home directory if user is valid.
120*7c478bd9Sstevel@tonic-gate  */
121*7c478bd9Sstevel@tonic-gate int
122*7c478bd9Sstevel@tonic-gate ValidUser(host, uid, gid, error, shell, dir, rst)
123*7c478bd9Sstevel@tonic-gate 	char *host;		/* passed in */
124*7c478bd9Sstevel@tonic-gate 	uid_t uid;
125*7c478bd9Sstevel@tonic-gate 	gid_t gid;
126*7c478bd9Sstevel@tonic-gate 	char *error;		/* filled in on return */
127*7c478bd9Sstevel@tonic-gate 	char *shell;		/* filled in on return */
128*7c478bd9Sstevel@tonic-gate 	char *dir;		/* filled in on return */
129*7c478bd9Sstevel@tonic-gate 	struct rex_start *rst;	/* passed in */
130*7c478bd9Sstevel@tonic-gate {
131*7c478bd9Sstevel@tonic-gate 	struct passwd *pw, *getpwuid();
132*7c478bd9Sstevel@tonic-gate 	int v;
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate 	pw = getpwuid(uid);
135*7c478bd9Sstevel@tonic-gate 	if (pw == NULL || pw->pw_name == NULL)
136*7c478bd9Sstevel@tonic-gate 	{
137*7c478bd9Sstevel@tonic-gate 		errprintf(error, "rexd: User id %d not valid\n", uid);
138*7c478bd9Sstevel@tonic-gate 		audit_rexd_fail("user id is not valid",
139*7c478bd9Sstevel@tonic-gate 				host,
140*7c478bd9Sstevel@tonic-gate 				NULL,
141*7c478bd9Sstevel@tonic-gate 				uid,
142*7c478bd9Sstevel@tonic-gate 				gid,
143*7c478bd9Sstevel@tonic-gate 				NULL,
144*7c478bd9Sstevel@tonic-gate 				rst->rst_cmd);	    /* BSM */
145*7c478bd9Sstevel@tonic-gate 		return (1);
146*7c478bd9Sstevel@tonic-gate 	}
147*7c478bd9Sstevel@tonic-gate 	strncpy(UserName, pw->pw_name, sizeof (UserName) - 1);
148*7c478bd9Sstevel@tonic-gate 	strncpy(HostName, host, sizeof (HostName) - 1);
149*7c478bd9Sstevel@tonic-gate 	strcpy(shell, pw->pw_shell);
150*7c478bd9Sstevel@tonic-gate 	strcpy(dir, pw->pw_dir);
151*7c478bd9Sstevel@tonic-gate 	setproctitle(pw->pw_name, host);
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	if (pam_start("rexd", pw->pw_name, NULL, &pamh) != PAM_SUCCESS ||
154*7c478bd9Sstevel@tonic-gate 	    pam_set_item(pamh, PAM_RHOST, host) != PAM_SUCCESS) {
155*7c478bd9Sstevel@tonic-gate 		audit_rexd_fail("user id is not valid",
156*7c478bd9Sstevel@tonic-gate 				host,
157*7c478bd9Sstevel@tonic-gate 				pw->pw_name,
158*7c478bd9Sstevel@tonic-gate 				uid,
159*7c478bd9Sstevel@tonic-gate 				gid,
160*7c478bd9Sstevel@tonic-gate 				shell,
161*7c478bd9Sstevel@tonic-gate 				rst->rst_cmd);	    /* BSM */
162*7c478bd9Sstevel@tonic-gate 		errprintf(error, "rexd: User id %d not valid\n", uid);
163*7c478bd9Sstevel@tonic-gate 		if (pamh) {
164*7c478bd9Sstevel@tonic-gate 			pam_end(pamh, PAM_ABORT);
165*7c478bd9Sstevel@tonic-gate 			pamh = NULL;
166*7c478bd9Sstevel@tonic-gate 		}
167*7c478bd9Sstevel@tonic-gate 		return (1);
168*7c478bd9Sstevel@tonic-gate 	}
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate 	if ((v = pam_acct_mgmt(pamh, 0)) != PAM_SUCCESS) {
171*7c478bd9Sstevel@tonic-gate 		switch (v) {
172*7c478bd9Sstevel@tonic-gate 		case PAM_NEW_AUTHTOK_REQD:
173*7c478bd9Sstevel@tonic-gate 			errprintf(error,
174*7c478bd9Sstevel@tonic-gate 				"rexd: User id %d Password Expired\n", uid);
175*7c478bd9Sstevel@tonic-gate 			break;
176*7c478bd9Sstevel@tonic-gate 		case PAM_PERM_DENIED:
177*7c478bd9Sstevel@tonic-gate 			errprintf(error,
178*7c478bd9Sstevel@tonic-gate 				"rexd: User id %d Account Expired\n", uid);
179*7c478bd9Sstevel@tonic-gate 			break;
180*7c478bd9Sstevel@tonic-gate 		case PAM_AUTHTOK_EXPIRED:
181*7c478bd9Sstevel@tonic-gate 			errprintf(error,
182*7c478bd9Sstevel@tonic-gate 				"rexd: User id %d Password Expired\n", uid);
183*7c478bd9Sstevel@tonic-gate 			break;
184*7c478bd9Sstevel@tonic-gate 		default:
185*7c478bd9Sstevel@tonic-gate 			errprintf(error,
186*7c478bd9Sstevel@tonic-gate 				"rexd: User id %d not valid\n", uid);
187*7c478bd9Sstevel@tonic-gate 			break;
188*7c478bd9Sstevel@tonic-gate 		}
189*7c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_ABORT);
190*7c478bd9Sstevel@tonic-gate 		pamh = NULL;
191*7c478bd9Sstevel@tonic-gate 
192*7c478bd9Sstevel@tonic-gate 		audit_rexd_fail("user account expired",
193*7c478bd9Sstevel@tonic-gate 				host,
194*7c478bd9Sstevel@tonic-gate 				pw->pw_name,
195*7c478bd9Sstevel@tonic-gate 				uid,
196*7c478bd9Sstevel@tonic-gate 				gid,
197*7c478bd9Sstevel@tonic-gate 				shell,
198*7c478bd9Sstevel@tonic-gate 				rst->rst_cmd);	    /* BSM */
199*7c478bd9Sstevel@tonic-gate 		return (1);
200*7c478bd9Sstevel@tonic-gate 	}
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	return (0);
203*7c478bd9Sstevel@tonic-gate }
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate /*
206*7c478bd9Sstevel@tonic-gate  * Add an audit record with argv that was pre-set, plus the given string
207*7c478bd9Sstevel@tonic-gate  */
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate /*
210*7c478bd9Sstevel@tonic-gate  * Allocate a pseudo-terminal
211*7c478bd9Sstevel@tonic-gate  * sets the global variables Master and Slave.
212*7c478bd9Sstevel@tonic-gate  * returns 1 on error, 0 if OK
213*7c478bd9Sstevel@tonic-gate  */
214*7c478bd9Sstevel@tonic-gate int
215*7c478bd9Sstevel@tonic-gate AllocatePty(socket0, socket1)
216*7c478bd9Sstevel@tonic-gate 	int socket0, socket1;
217*7c478bd9Sstevel@tonic-gate {
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 	int on = 1;
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate 	sigset(SIGHUP, SIG_IGN);
222*7c478bd9Sstevel@tonic-gate 	sigset(SIGTTOU, SIG_IGN);
223*7c478bd9Sstevel@tonic-gate 	sigset(SIGTTIN, SIG_IGN);
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	if ((Master = open("/dev/ptmx", O_RDWR)) == -1) {
226*7c478bd9Sstevel@tonic-gate 	    if (Debug)
227*7c478bd9Sstevel@tonic-gate 		    printf("open-ptmx-failure\n");
228*7c478bd9Sstevel@tonic-gate 	    perror("AloocatePtyMaster fails");
229*7c478bd9Sstevel@tonic-gate 	    return (1);		/* error could not open /dev/ptmx */
230*7c478bd9Sstevel@tonic-gate 	}
231*7c478bd9Sstevel@tonic-gate 	if (Debug)
232*7c478bd9Sstevel@tonic-gate 	    printf("open-ptmx success Master =%d\n", Master);
233*7c478bd9Sstevel@tonic-gate 	if (Debug)
234*7c478bd9Sstevel@tonic-gate 	    printf("Before grantpt...Master=%d\n", Master);
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate 	if (grantpt(Master) == -1) {
237*7c478bd9Sstevel@tonic-gate 	    perror("could not grant slave pty");
238*7c478bd9Sstevel@tonic-gate 	    exit(1);
239*7c478bd9Sstevel@tonic-gate 	}
240*7c478bd9Sstevel@tonic-gate 	if (unlockpt(Master) == -1) {
241*7c478bd9Sstevel@tonic-gate 	    perror("could not unlock slave pty");
242*7c478bd9Sstevel@tonic-gate 	    exit(1);
243*7c478bd9Sstevel@tonic-gate 	}
244*7c478bd9Sstevel@tonic-gate 	if ((slavename = ptsname(Master)) == NULL) {
245*7c478bd9Sstevel@tonic-gate 	    perror("could not enable slave pty");
246*7c478bd9Sstevel@tonic-gate 	    exit(1);
247*7c478bd9Sstevel@tonic-gate 	}
248*7c478bd9Sstevel@tonic-gate 	if ((Slave = open(slavename, O_RDWR)) == -1) {
249*7c478bd9Sstevel@tonic-gate 	    perror("could not open slave pty");
250*7c478bd9Sstevel@tonic-gate 	    exit(1);
251*7c478bd9Sstevel@tonic-gate 	}
252*7c478bd9Sstevel@tonic-gate 	if (ioctl(Slave, I_PUSH, "ptem") == -1) {
253*7c478bd9Sstevel@tonic-gate 	    perror("ioctl I_PUSH ptem");
254*7c478bd9Sstevel@tonic-gate 	    exit(1);
255*7c478bd9Sstevel@tonic-gate 	}
256*7c478bd9Sstevel@tonic-gate 	if (ioctl(Slave, I_PUSH, "ldterm") == -1) {
257*7c478bd9Sstevel@tonic-gate 	    perror("ioctl I_PUSH ldterm");
258*7c478bd9Sstevel@tonic-gate 	    exit(1);
259*7c478bd9Sstevel@tonic-gate 	}
260*7c478bd9Sstevel@tonic-gate 	if (ioctl(Slave, I_PUSH, "ttcompat") == -1) {
261*7c478bd9Sstevel@tonic-gate 	    perror("ioctl I_PUSH ttcompat");
262*7c478bd9Sstevel@tonic-gate 	    exit(1);
263*7c478bd9Sstevel@tonic-gate 	}
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 	Slave_is_closed_on_master_side = FALSE;
266*7c478bd9Sstevel@tonic-gate 	setsid(); /* get rid of controlling terminal */
267*7c478bd9Sstevel@tonic-gate 	/* LoginUser(); */
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate 	InputSocket = socket0;
270*7c478bd9Sstevel@tonic-gate 	OutputSocket = socket1;
271*7c478bd9Sstevel@tonic-gate 	ioctl(Master, FIONBIO, &on);
272*7c478bd9Sstevel@tonic-gate 	uxprt[INPUTSOCKET].xp_fd = InputSocket;
273*7c478bd9Sstevel@tonic-gate 	xprt_register(&uxprt[INPUTSOCKET]);
274*7c478bd9Sstevel@tonic-gate 	uxprt[MASTER].xp_fd = Master;
275*7c478bd9Sstevel@tonic-gate 	xprt_register(&uxprt[MASTER]);
276*7c478bd9Sstevel@tonic-gate 	return (0);
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate }
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate void
281*7c478bd9Sstevel@tonic-gate OpenPtySlave()
282*7c478bd9Sstevel@tonic-gate {
283*7c478bd9Sstevel@tonic-gate 	close(Slave);
284*7c478bd9Sstevel@tonic-gate 	Slave = open(slavename, O_RDWR);
285*7c478bd9Sstevel@tonic-gate 	if (Slave < 0) {
286*7c478bd9Sstevel@tonic-gate 		perror(slavename);
287*7c478bd9Sstevel@tonic-gate 		exit(1);
288*7c478bd9Sstevel@tonic-gate 	}
289*7c478bd9Sstevel@tonic-gate }
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 	/*
294*7c478bd9Sstevel@tonic-gate 	 * Special processing for interactive operation.
295*7c478bd9Sstevel@tonic-gate 	 * Given pointers to three standard file descriptors,
296*7c478bd9Sstevel@tonic-gate 	 * which get set to point to the pty.
297*7c478bd9Sstevel@tonic-gate 	 */
298*7c478bd9Sstevel@tonic-gate void
299*7c478bd9Sstevel@tonic-gate DoHelper(pfd0, pfd1, pfd2)
300*7c478bd9Sstevel@tonic-gate 	int *pfd0, *pfd1, *pfd2;
301*7c478bd9Sstevel@tonic-gate {
302*7c478bd9Sstevel@tonic-gate 	int pgrp;
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate 	sigset(SIGINT, SIG_IGN);
306*7c478bd9Sstevel@tonic-gate 	close(Master);
307*7c478bd9Sstevel@tonic-gate 	close(InputSocket);
308*7c478bd9Sstevel@tonic-gate 	close(OutputSocket);
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 	*pfd0 = Slave;
311*7c478bd9Sstevel@tonic-gate 	*pfd1 = Slave;
312*7c478bd9Sstevel@tonic-gate 	*pfd2 = Slave;
313*7c478bd9Sstevel@tonic-gate }
314*7c478bd9Sstevel@tonic-gate 
315*7c478bd9Sstevel@tonic-gate 
316*7c478bd9Sstevel@tonic-gate /*
317*7c478bd9Sstevel@tonic-gate  * destroy the helpers when the executing process dies
318*7c478bd9Sstevel@tonic-gate  */
319*7c478bd9Sstevel@tonic-gate KillHelper(grp)
320*7c478bd9Sstevel@tonic-gate 	int grp;
321*7c478bd9Sstevel@tonic-gate {
322*7c478bd9Sstevel@tonic-gate 	if (Debug)
323*7c478bd9Sstevel@tonic-gate 		printf("Enter KillHelper\n");
324*7c478bd9Sstevel@tonic-gate 	close(Master);
325*7c478bd9Sstevel@tonic-gate 	xprt_unregister(&uxprt[MASTER]);
326*7c478bd9Sstevel@tonic-gate 	close(InputSocket);
327*7c478bd9Sstevel@tonic-gate 	xprt_unregister(&uxprt[INPUTSOCKET]);
328*7c478bd9Sstevel@tonic-gate 	close(OutputSocket);
329*7c478bd9Sstevel@tonic-gate 	LogoutUser();
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate 	if (grp)
332*7c478bd9Sstevel@tonic-gate 	    kill((-grp), SIGKILL);
333*7c478bd9Sstevel@tonic-gate }
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate /*
337*7c478bd9Sstevel@tonic-gate  * edit the Unix traditional data files that tell who is logged
338*7c478bd9Sstevel@tonic-gate  * into "the system"
339*7c478bd9Sstevel@tonic-gate  */
340*7c478bd9Sstevel@tonic-gate unsigned char	utid[] = {'o', 'n', SC_WILDC, SC_WILDC};
341*7c478bd9Sstevel@tonic-gate 
342*7c478bd9Sstevel@tonic-gate LoginUser()
343*7c478bd9Sstevel@tonic-gate {
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate 	char *user;
346*7c478bd9Sstevel@tonic-gate 	char *rhost;
347*7c478bd9Sstevel@tonic-gate 	/* the next 4 variables are needed for utmpx mgmt */
348*7c478bd9Sstevel@tonic-gate 	int		tmplen;
349*7c478bd9Sstevel@tonic-gate 	struct utmpx	*u = NULL;
350*7c478bd9Sstevel@tonic-gate 	struct utmpx	set_utmp;
351*7c478bd9Sstevel@tonic-gate 	char		*ttyntail;
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate 	/* We're pretty drastic here, exiting if an error is detected */
354*7c478bd9Sstevel@tonic-gate 	if (pam_set_item(pamh, PAM_TTY, slavename)	!= PAM_SUCCESS ||
355*7c478bd9Sstevel@tonic-gate 	    pam_get_item(pamh, PAM_USER, (void **) &user) != PAM_SUCCESS ||
356*7c478bd9Sstevel@tonic-gate 	    pam_get_item(pamh, PAM_RHOST, (void **) &rhost) != PAM_SUCCESS ||
357*7c478bd9Sstevel@tonic-gate 	    pam_open_session(pamh, 0)			!= PAM_SUCCESS) {
358*7c478bd9Sstevel@tonic-gate 		/*
359*7c478bd9Sstevel@tonic-gate 		 * XXX should print something but for now we exit
360*7c478bd9Sstevel@tonic-gate 		 */
361*7c478bd9Sstevel@tonic-gate 		exit(1);
362*7c478bd9Sstevel@tonic-gate 	}
363*7c478bd9Sstevel@tonic-gate 
364*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&set_utmp, 0, sizeof (set_utmp));
365*7c478bd9Sstevel@tonic-gate 	(void) time(&set_utmp.ut_tv.tv_sec);
366*7c478bd9Sstevel@tonic-gate 	set_utmp.ut_pid = getpid();
367*7c478bd9Sstevel@tonic-gate 	if (rhost != NULL && rhost[0] != '\0') {
368*7c478bd9Sstevel@tonic-gate 		(void) strcpy(set_utmp.ut_host, rhost);
369*7c478bd9Sstevel@tonic-gate 		tmplen = strlen(rhost) + 1;
370*7c478bd9Sstevel@tonic-gate 		if (tmplen < sizeof (set_utmp.ut_host))
371*7c478bd9Sstevel@tonic-gate 			set_utmp.ut_syslen = tmplen;
372*7c478bd9Sstevel@tonic-gate 		else
373*7c478bd9Sstevel@tonic-gate 			set_utmp.ut_syslen = sizeof (set_utmp.ut_host);
374*7c478bd9Sstevel@tonic-gate 	} else {
375*7c478bd9Sstevel@tonic-gate 		(void) memset(set_utmp.ut_host, 0, sizeof (set_utmp.ut_host));
376*7c478bd9Sstevel@tonic-gate 		set_utmp.ut_syslen = 0;
377*7c478bd9Sstevel@tonic-gate 	}
378*7c478bd9Sstevel@tonic-gate 	(void) strcpy(set_utmp.ut_user, user);
379*7c478bd9Sstevel@tonic-gate 
380*7c478bd9Sstevel@tonic-gate 	/*
381*7c478bd9Sstevel@tonic-gate 	 * Copy in the name of the tty minus the "/dev/" if a /dev/ is
382*7c478bd9Sstevel@tonic-gate 	 * in the path name.
383*7c478bd9Sstevel@tonic-gate 	 */
384*7c478bd9Sstevel@tonic-gate 	ttyntail = slavename;
385*7c478bd9Sstevel@tonic-gate 	if (strstr(ttyntail, "/dev/") != 0)
386*7c478bd9Sstevel@tonic-gate 		ttyntail = ttyntail + strlen("/dev/");
387*7c478bd9Sstevel@tonic-gate 	(void) strcpy(set_utmp.ut_line, ttyntail);
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate 	set_utmp.ut_type = USER_PROCESS;
390*7c478bd9Sstevel@tonic-gate 	if (utid != NULL)
391*7c478bd9Sstevel@tonic-gate 		(void) memcpy(set_utmp.ut_id, utid, sizeof (set_utmp.ut_id));
392*7c478bd9Sstevel@tonic-gate 	/*
393*7c478bd9Sstevel@tonic-gate 	 * Go through each entry one by one, looking only at INIT,
394*7c478bd9Sstevel@tonic-gate 	 * LOGIN or USER Processes.  Use the entry found if flags == 0
395*7c478bd9Sstevel@tonic-gate 	 * and the line name matches, or if the process ID matches if
396*7c478bd9Sstevel@tonic-gate 	 * the UPDATE_ENTRY flag is set.  The UPDATE_ENTRY flag is mainly
397*7c478bd9Sstevel@tonic-gate 	 * for login which normally only wants to update an entry if
398*7c478bd9Sstevel@tonic-gate 	 * the pid fields matches.
399*7c478bd9Sstevel@tonic-gate 	 */
400*7c478bd9Sstevel@tonic-gate 
401*7c478bd9Sstevel@tonic-gate 	if (u == (struct utmpx *)NULL) {
402*7c478bd9Sstevel@tonic-gate 		(void) makeutx(&set_utmp);
403*7c478bd9Sstevel@tonic-gate 	} else
404*7c478bd9Sstevel@tonic-gate 		updwtmpx(WTMPX_FILE, &set_utmp);
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate }
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate /*
409*7c478bd9Sstevel@tonic-gate  * edit the Unix traditional data files that tell who is logged
410*7c478bd9Sstevel@tonic-gate  * into "the system".
411*7c478bd9Sstevel@tonic-gate  */
412*7c478bd9Sstevel@tonic-gate 
413*7c478bd9Sstevel@tonic-gate LogoutUser()
414*7c478bd9Sstevel@tonic-gate {
415*7c478bd9Sstevel@tonic-gate 	struct utmpx *up;
416*7c478bd9Sstevel@tonic-gate 	struct utmpx ut;
417*7c478bd9Sstevel@tonic-gate 	int pid;
418*7c478bd9Sstevel@tonic-gate 	char user[sizeof (ut.ut_user) + 1];
419*7c478bd9Sstevel@tonic-gate 	char ttyn[sizeof (ut.ut_line) + 1];
420*7c478bd9Sstevel@tonic-gate 	char rhost[sizeof (ut.ut_host) + 1];
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 	sighold(SIGCHLD);		/* no disruption during cleanup */
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate 	if (pamh) {
425*7c478bd9Sstevel@tonic-gate 		pam_end(pamh, PAM_SUCCESS);
426*7c478bd9Sstevel@tonic-gate 		pamh = NULL;
427*7c478bd9Sstevel@tonic-gate 	}
428*7c478bd9Sstevel@tonic-gate 
429*7c478bd9Sstevel@tonic-gate 	/* BEGIN RESET UTMP */
430*7c478bd9Sstevel@tonic-gate 	pid = child;
431*7c478bd9Sstevel@tonic-gate 	setutxent();
432*7c478bd9Sstevel@tonic-gate 	while (up = getutxent()) {
433*7c478bd9Sstevel@tonic-gate 		if (up->ut_pid == pid) {
434*7c478bd9Sstevel@tonic-gate 			if (up->ut_type == DEAD_PROCESS) {
435*7c478bd9Sstevel@tonic-gate 				/*
436*7c478bd9Sstevel@tonic-gate 				 * Cleaned up elsewhere.
437*7c478bd9Sstevel@tonic-gate 				 */
438*7c478bd9Sstevel@tonic-gate 				break;
439*7c478bd9Sstevel@tonic-gate 			}
440*7c478bd9Sstevel@tonic-gate 
441*7c478bd9Sstevel@tonic-gate 			strncpy(user, up->ut_user, sizeof (up->ut_user));
442*7c478bd9Sstevel@tonic-gate 			user[sizeof (up->ut_user)] = '\0';
443*7c478bd9Sstevel@tonic-gate 			strncpy(ttyn, up->ut_line, sizeof (up->ut_line));
444*7c478bd9Sstevel@tonic-gate 			ttyn[sizeof (up->ut_line)] = '\0';
445*7c478bd9Sstevel@tonic-gate 			strncpy(rhost, up->ut_host, sizeof (up->ut_host));
446*7c478bd9Sstevel@tonic-gate 			rhost[sizeof (up->ut_host)] = '\0';
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate 			if ((pam_start("rexd", user, NULL, &pamh))
449*7c478bd9Sstevel@tonic-gate 							== PAM_SUCCESS) {
450*7c478bd9Sstevel@tonic-gate 				(void) pam_set_item(pamh, PAM_TTY, ttyn);
451*7c478bd9Sstevel@tonic-gate 				(void) pam_set_item(pamh, PAM_RHOST, rhost);
452*7c478bd9Sstevel@tonic-gate 				(void) pam_close_session(pamh, 0);
453*7c478bd9Sstevel@tonic-gate 				(void) pam_end(pamh, PAM_SUCCESS);
454*7c478bd9Sstevel@tonic-gate 				pamh = NULL;
455*7c478bd9Sstevel@tonic-gate 			}
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 			up->ut_type = DEAD_PROCESS;
458*7c478bd9Sstevel@tonic-gate 			up->ut_exit.e_termination = WTERMSIG(0);
459*7c478bd9Sstevel@tonic-gate 			up->ut_exit.e_exit = WEXITSTATUS(0);
460*7c478bd9Sstevel@tonic-gate 			(void) time(&up->ut_tv.tv_sec);
461*7c478bd9Sstevel@tonic-gate 			if (modutx(up) == NULL) {
462*7c478bd9Sstevel@tonic-gate 				/*
463*7c478bd9Sstevel@tonic-gate 				 * Since modutx failed we'll
464*7c478bd9Sstevel@tonic-gate 				 * write out the new entry
465*7c478bd9Sstevel@tonic-gate 				 * ourselves.
466*7c478bd9Sstevel@tonic-gate 				 */
467*7c478bd9Sstevel@tonic-gate 				(void) pututxline(up);
468*7c478bd9Sstevel@tonic-gate 				updwtmpx("wtmpx", up);
469*7c478bd9Sstevel@tonic-gate 			}
470*7c478bd9Sstevel@tonic-gate 			break;
471*7c478bd9Sstevel@tonic-gate 		}
472*7c478bd9Sstevel@tonic-gate 	}
473*7c478bd9Sstevel@tonic-gate 	endutxent();
474*7c478bd9Sstevel@tonic-gate 	/* END RESET UTMP */
475*7c478bd9Sstevel@tonic-gate 	sigrelse(SIGCHLD);
476*7c478bd9Sstevel@tonic-gate }
477*7c478bd9Sstevel@tonic-gate 
478*7c478bd9Sstevel@tonic-gate /*
479*7c478bd9Sstevel@tonic-gate  * set the pty modes to the given values
480*7c478bd9Sstevel@tonic-gate  */
481*7c478bd9Sstevel@tonic-gate SetPtyMode(mode)
482*7c478bd9Sstevel@tonic-gate 	struct rex_ttymode *mode;
483*7c478bd9Sstevel@tonic-gate {
484*7c478bd9Sstevel@tonic-gate 	struct sgttyb svr4_sgttyb_var;
485*7c478bd9Sstevel@tonic-gate 	int ldisc = NTTYDISC;
486*7c478bd9Sstevel@tonic-gate 
487*7c478bd9Sstevel@tonic-gate 	if (Debug)
488*7c478bd9Sstevel@tonic-gate 		printf("Enter SetPtyMode\n");
489*7c478bd9Sstevel@tonic-gate 	if (Debug)
490*7c478bd9Sstevel@tonic-gate 		printf("SetPtyMode:opened slave\n");
491*7c478bd9Sstevel@tonic-gate 	ioctl(Slave, TIOCSETD, &ldisc);
492*7c478bd9Sstevel@tonic-gate 	if (Debug)
493*7c478bd9Sstevel@tonic-gate 		printf("SetPtyMode:Slave TIOCSETD done\n");
494*7c478bd9Sstevel@tonic-gate 
495*7c478bd9Sstevel@tonic-gate 	/*
496*7c478bd9Sstevel@tonic-gate 	 * Copy from over-the-net(bsd) to SVR4 format
497*7c478bd9Sstevel@tonic-gate 	 */
498*7c478bd9Sstevel@tonic-gate 	svr4_sgttyb_var.sg_ispeed = mode->basic.sg_ispeed;
499*7c478bd9Sstevel@tonic-gate 	svr4_sgttyb_var.sg_ospeed = mode->basic.sg_ospeed;
500*7c478bd9Sstevel@tonic-gate 	svr4_sgttyb_var.sg_erase  = mode->basic.sg_erase;
501*7c478bd9Sstevel@tonic-gate 	svr4_sgttyb_var.sg_kill = mode->basic.sg_kill;
502*7c478bd9Sstevel@tonic-gate 	svr4_sgttyb_var.sg_flags = (int)mode->basic.sg_flags;
503*7c478bd9Sstevel@tonic-gate 	/*
504*7c478bd9Sstevel@tonic-gate 	 * Clear any possible sign extension caused by (int)
505*7c478bd9Sstevel@tonic-gate 	 * typecast
506*7c478bd9Sstevel@tonic-gate 	 */
507*7c478bd9Sstevel@tonic-gate 	svr4_sgttyb_var.sg_flags &= 0xFFFF;
508*7c478bd9Sstevel@tonic-gate 
509*7c478bd9Sstevel@tonic-gate 	ioctl(Slave, TIOCSETN, &svr4_sgttyb_var);
510*7c478bd9Sstevel@tonic-gate 	if (Debug)
511*7c478bd9Sstevel@tonic-gate 		printf("SetPtyMode:Slave TIOCSETN done\n");
512*7c478bd9Sstevel@tonic-gate 	ioctl(Slave, TIOCSETC, &mode->more);
513*7c478bd9Sstevel@tonic-gate 	if (Debug)
514*7c478bd9Sstevel@tonic-gate 		printf("SetPtyMode:Slave TIOCSETC done\n");
515*7c478bd9Sstevel@tonic-gate 	ioctl(Slave, TIOCSLTC, &mode->yetmore);
516*7c478bd9Sstevel@tonic-gate 	if (Debug)
517*7c478bd9Sstevel@tonic-gate 		printf("SetPtyMode:Slave TIOCSLTC done\n");
518*7c478bd9Sstevel@tonic-gate 	ioctl(Slave, TIOCLSET, &mode->andmore);
519*7c478bd9Sstevel@tonic-gate 	if (Debug)
520*7c478bd9Sstevel@tonic-gate 		printf("SetPtyMode:Slave TIOCSET done\n");
521*7c478bd9Sstevel@tonic-gate 
522*7c478bd9Sstevel@tonic-gate 	/* Opened in AllocPty for parent, still open in child */
523*7c478bd9Sstevel@tonic-gate 	if (Slave_is_closed_on_master_side == FALSE) {
524*7c478bd9Sstevel@tonic-gate 		close(Slave);
525*7c478bd9Sstevel@tonic-gate 		Slave_is_closed_on_master_side = TRUE;
526*7c478bd9Sstevel@tonic-gate 	}
527*7c478bd9Sstevel@tonic-gate }
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate /*
530*7c478bd9Sstevel@tonic-gate  * set the pty window size to the given value
531*7c478bd9Sstevel@tonic-gate  */
532*7c478bd9Sstevel@tonic-gate SetPtySize(sizep)
533*7c478bd9Sstevel@tonic-gate 	struct rex_ttysize *sizep;
534*7c478bd9Sstevel@tonic-gate {
535*7c478bd9Sstevel@tonic-gate 	struct winsize newsize;
536*7c478bd9Sstevel@tonic-gate 
537*7c478bd9Sstevel@tonic-gate 	/* if size has changed, this ioctl changes it */
538*7c478bd9Sstevel@tonic-gate 	/* *and* sends SIGWINCH to process group */
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate 	newsize.ws_row = (unsigned short) sizep->ts_lines;
541*7c478bd9Sstevel@tonic-gate 	newsize.ws_col = (unsigned short) sizep->ts_cols;
542*7c478bd9Sstevel@tonic-gate 
543*7c478bd9Sstevel@tonic-gate 	(void) ioctl(Master, TIOCSWINSZ, &newsize);
544*7c478bd9Sstevel@tonic-gate 	if (Slave_is_closed_on_master_side == FALSE) {
545*7c478bd9Sstevel@tonic-gate 		close(Slave);
546*7c478bd9Sstevel@tonic-gate 		Slave_is_closed_on_master_side = TRUE;
547*7c478bd9Sstevel@tonic-gate 	}
548*7c478bd9Sstevel@tonic-gate }
549*7c478bd9Sstevel@tonic-gate 
550*7c478bd9Sstevel@tonic-gate 
551*7c478bd9Sstevel@tonic-gate /*
552*7c478bd9Sstevel@tonic-gate  * send the given signal to the group controlling the terminal
553*7c478bd9Sstevel@tonic-gate  */
554*7c478bd9Sstevel@tonic-gate SendSignal(sig)
555*7c478bd9Sstevel@tonic-gate 	int sig;
556*7c478bd9Sstevel@tonic-gate {
557*7c478bd9Sstevel@tonic-gate 	pid_t pgrp;
558*7c478bd9Sstevel@tonic-gate 
559*7c478bd9Sstevel@tonic-gate 	pgrp = getpgid(child);
560*7c478bd9Sstevel@tonic-gate 	if (pgrp != (pid_t)-1)
561*7c478bd9Sstevel@tonic-gate 		(void) kill((-pgrp), sig);
562*7c478bd9Sstevel@tonic-gate }
563*7c478bd9Sstevel@tonic-gate 
564*7c478bd9Sstevel@tonic-gate /*
565*7c478bd9Sstevel@tonic-gate  * called when the main select loop detects that we might want to
566*7c478bd9Sstevel@tonic-gate  * read something.
567*7c478bd9Sstevel@tonic-gate  */
568*7c478bd9Sstevel@tonic-gate void
569*7c478bd9Sstevel@tonic-gate HelperRead(pollfd_t *fdp, int nfds, int *pollretval)
570*7c478bd9Sstevel@tonic-gate {
571*7c478bd9Sstevel@tonic-gate 	char buf[128];
572*7c478bd9Sstevel@tonic-gate 	int retval;
573*7c478bd9Sstevel@tonic-gate 	extern int errno;
574*7c478bd9Sstevel@tonic-gate 	int mask;
575*7c478bd9Sstevel@tonic-gate 	int master = -1;
576*7c478bd9Sstevel@tonic-gate 	int inputsocket = -1;
577*7c478bd9Sstevel@tonic-gate 
578*7c478bd9Sstevel@tonic-gate 	/*
579*7c478bd9Sstevel@tonic-gate 	 * fdp pollset may be compressed. Search for Master and
580*7c478bd9Sstevel@tonic-gate 	 * InputSocket fds.
581*7c478bd9Sstevel@tonic-gate 	 */
582*7c478bd9Sstevel@tonic-gate 	int i;
583*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < nfds; i++) {
584*7c478bd9Sstevel@tonic-gate 		if (fdp[i].fd == Master && fdp[i].revents != 0)
585*7c478bd9Sstevel@tonic-gate 			master = i;
586*7c478bd9Sstevel@tonic-gate 		if (fdp[i].fd == InputSocket && fdp[i].revents != 0)
587*7c478bd9Sstevel@tonic-gate 			inputsocket = i;
588*7c478bd9Sstevel@tonic-gate 	}
589*7c478bd9Sstevel@tonic-gate 
590*7c478bd9Sstevel@tonic-gate /*	mask = sigsetmask (sigmask (SIGCHLD));	*/
591*7c478bd9Sstevel@tonic-gate 	mask = sighold(SIGCHLD);
592*7c478bd9Sstevel@tonic-gate 	retval = 0;
593*7c478bd9Sstevel@tonic-gate 	if (master != -1) {
594*7c478bd9Sstevel@tonic-gate 		if (!(fdp[master].revents & (POLLERR | POLLHUP | POLLNVAL))) {
595*7c478bd9Sstevel@tonic-gate 			retval = read(Master, buf, sizeof (buf));
596*7c478bd9Sstevel@tonic-gate 			if (retval > 0) {
597*7c478bd9Sstevel@tonic-gate 				(void) write(OutputSocket, buf, retval);
598*7c478bd9Sstevel@tonic-gate 			} else {
599*7c478bd9Sstevel@tonic-gate 				if (errno != EINTR && errno != EIO &&
600*7c478bd9Sstevel@tonic-gate 				    errno != EWOULDBLOCK)
601*7c478bd9Sstevel@tonic-gate 					perror("pty read");
602*7c478bd9Sstevel@tonic-gate 				/* 1 => further sends disallowed */
603*7c478bd9Sstevel@tonic-gate 				shutdown(OutputSocket, 1);
604*7c478bd9Sstevel@tonic-gate 				xprt_unregister(&uxprt[MASTER]);
605*7c478bd9Sstevel@tonic-gate 			}
606*7c478bd9Sstevel@tonic-gate 		}
607*7c478bd9Sstevel@tonic-gate 
608*7c478bd9Sstevel@tonic-gate 		/* clear this event for svc_getreq_poll */
609*7c478bd9Sstevel@tonic-gate 		fdp[master].revents = 0;
610*7c478bd9Sstevel@tonic-gate 		*pollretval = *pollretval - 1;
611*7c478bd9Sstevel@tonic-gate 
612*7c478bd9Sstevel@tonic-gate 		if (retval <= 0 && ChildDied) {
613*7c478bd9Sstevel@tonic-gate 			KillHelper(child);
614*7c478bd9Sstevel@tonic-gate 			HasHelper = 0;
615*7c478bd9Sstevel@tonic-gate 			if (inputsocket != -1) {
616*7c478bd9Sstevel@tonic-gate 				fdp[inputsocket].revents = 0;
617*7c478bd9Sstevel@tonic-gate 				*pollretval = *pollretval - 1;
618*7c478bd9Sstevel@tonic-gate 			}
619*7c478bd9Sstevel@tonic-gate 			goto done;
620*7c478bd9Sstevel@tonic-gate 		}
621*7c478bd9Sstevel@tonic-gate 	}
622*7c478bd9Sstevel@tonic-gate 
623*7c478bd9Sstevel@tonic-gate 	if (inputsocket != -1) {
624*7c478bd9Sstevel@tonic-gate 		if (!(fdp[inputsocket].revents & (POLLERR | POLLHUP |
625*7c478bd9Sstevel@tonic-gate 							    POLLNVAL))) {
626*7c478bd9Sstevel@tonic-gate 			retval = read(InputSocket, buf, sizeof (buf));
627*7c478bd9Sstevel@tonic-gate 			if (retval > 0) {
628*7c478bd9Sstevel@tonic-gate 				(void) write(Master, buf, retval);
629*7c478bd9Sstevel@tonic-gate 			} else {
630*7c478bd9Sstevel@tonic-gate 				if (errno != EINTR && errno != EWOULDBLOCK)
631*7c478bd9Sstevel@tonic-gate 					perror("socket read");
632*7c478bd9Sstevel@tonic-gate 				xprt_unregister(&uxprt[INPUTSOCKET]);
633*7c478bd9Sstevel@tonic-gate 			}
634*7c478bd9Sstevel@tonic-gate 		}
635*7c478bd9Sstevel@tonic-gate 
636*7c478bd9Sstevel@tonic-gate 		/* clear this event for svc_getreq_poll */
637*7c478bd9Sstevel@tonic-gate 		fdp[inputsocket].revents = 0;
638*7c478bd9Sstevel@tonic-gate 		*pollretval = *pollretval - 1;
639*7c478bd9Sstevel@tonic-gate 	}
640*7c478bd9Sstevel@tonic-gate 
641*7c478bd9Sstevel@tonic-gate 	done:
642*7c478bd9Sstevel@tonic-gate /*	sigsetmask (mask);	*/
643*7c478bd9Sstevel@tonic-gate 	sigrelse(SIGCHLD);
644*7c478bd9Sstevel@tonic-gate }
645