xref: /titanic_51/usr/src/cmd/ttymon/tmhandler.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 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
34*7c478bd9Sstevel@tonic-gate #include <stdio.h>
35*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
36*7c478bd9Sstevel@tonic-gate #include <errno.h>
37*7c478bd9Sstevel@tonic-gate #include <poll.h>
38*7c478bd9Sstevel@tonic-gate #include <string.h>
39*7c478bd9Sstevel@tonic-gate #include <termio.h>
40*7c478bd9Sstevel@tonic-gate #include <signal.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
43*7c478bd9Sstevel@tonic-gate #include <unistd.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/wait.h>
45*7c478bd9Sstevel@tonic-gate #include "ttymon.h"
46*7c478bd9Sstevel@tonic-gate #include "tmstruct.h"
47*7c478bd9Sstevel@tonic-gate #include "tmextern.h"
48*7c478bd9Sstevel@tonic-gate #include "sac.h"
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate extern	int	Retry;
51*7c478bd9Sstevel@tonic-gate static	struct	pmtab	*find_pid();
52*7c478bd9Sstevel@tonic-gate static	void	kill_children();
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate static 	struct	pmtab	*find_fd();
55*7c478bd9Sstevel@tonic-gate static	void	pcsync_close();
56*7c478bd9Sstevel@tonic-gate extern  void	sigalarm();
57*7c478bd9Sstevel@tonic-gate extern	void	tmchild();
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate /*
60*7c478bd9Sstevel@tonic-gate  *	fork_tmchild	- fork child on the device
61*7c478bd9Sstevel@tonic-gate  */
62*7c478bd9Sstevel@tonic-gate static	void
63*7c478bd9Sstevel@tonic-gate fork_tmchild(pmptr)
64*7c478bd9Sstevel@tonic-gate struct	pmtab	*pmptr;
65*7c478bd9Sstevel@tonic-gate {
66*7c478bd9Sstevel@tonic-gate 	pid_t	pid;
67*7c478bd9Sstevel@tonic-gate 	sigset_t	cset;
68*7c478bd9Sstevel@tonic-gate 	sigset_t	tset;
69*7c478bd9Sstevel@tonic-gate 	int	pcpipe0[2], pcpipe1[2];
70*7c478bd9Sstevel@tonic-gate 	int	p0;
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
73*7c478bd9Sstevel@tonic-gate 	debug("in fork_tmchild");
74*7c478bd9Sstevel@tonic-gate #endif
75*7c478bd9Sstevel@tonic-gate 	pmptr->p_inservice = FALSE;
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate 	/*
78*7c478bd9Sstevel@tonic-gate 	 * initialize pipe.
79*7c478bd9Sstevel@tonic-gate 	 * Child has pcpipe[0] pipe fd for reading and writing
80*7c478bd9Sstevel@tonic-gate 	 * and closes pcpipe[1]. Parent has pcpipe[1] pipe fd for
81*7c478bd9Sstevel@tonic-gate 	 * reading and writing and closes pcpipe[0].
82*7c478bd9Sstevel@tonic-gate 	 *
83*7c478bd9Sstevel@tonic-gate 	 * This way if the child process exits the parent's block
84*7c478bd9Sstevel@tonic-gate 	 * read on pipe will return immediately as the other end of
85*7c478bd9Sstevel@tonic-gate 	 * the pipe has closed. Similarly if the parent process exits
86*7c478bd9Sstevel@tonic-gate 	 * child's blocking read on the pipe will return immediately.
87*7c478bd9Sstevel@tonic-gate 	 */
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate 	if (((p0 = pipe(pcpipe0)) == -1) || (pipe(pcpipe1) == -1))  {
90*7c478bd9Sstevel@tonic-gate 		if (p0 == 0) {
91*7c478bd9Sstevel@tonic-gate 			close(pcpipe0[0]);
92*7c478bd9Sstevel@tonic-gate 			close(pcpipe0[1]);
93*7c478bd9Sstevel@tonic-gate 		}
94*7c478bd9Sstevel@tonic-gate 		log("pipe() failed: %s", strerror(errno));
95*7c478bd9Sstevel@tonic-gate 		pmptr->p_status = VALID;
96*7c478bd9Sstevel@tonic-gate 		pmptr->p_pid = 0;
97*7c478bd9Sstevel@tonic-gate 		Retry = TRUE;
98*7c478bd9Sstevel@tonic-gate 	}
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 	/* protect following region from SIGCLD */
101*7c478bd9Sstevel@tonic-gate 	(void)sigprocmask(SIG_SETMASK, NULL, &cset);
102*7c478bd9Sstevel@tonic-gate 	tset = cset;
103*7c478bd9Sstevel@tonic-gate 	(void)sigaddset(&tset, SIGCLD);
104*7c478bd9Sstevel@tonic-gate 	(void)sigprocmask(SIG_SETMASK, &tset, NULL);
105*7c478bd9Sstevel@tonic-gate 	if( (pid=fork()) == 0 ) {
106*7c478bd9Sstevel@tonic-gate 		/*
107*7c478bd9Sstevel@tonic-gate 		 * Close all file descriptors except pmptr->p_fd
108*7c478bd9Sstevel@tonic-gate 		 * Wait for the parent process to close its fd
109*7c478bd9Sstevel@tonic-gate 		 */
110*7c478bd9Sstevel@tonic-gate 		pcsync_close(pcpipe0, pcpipe1, pid, pmptr->p_fd);
111*7c478bd9Sstevel@tonic-gate 	 	/* The CHILD */
112*7c478bd9Sstevel@tonic-gate 		tmchild(pmptr);
113*7c478bd9Sstevel@tonic-gate 		/* tmchild should never return */
114*7c478bd9Sstevel@tonic-gate 		fatal("tmchild for <%s> returns unexpected", pmptr->p_device);
115*7c478bd9Sstevel@tonic-gate 	}
116*7c478bd9Sstevel@tonic-gate 	else if (pid < 0) {
117*7c478bd9Sstevel@tonic-gate 		log("fork failed: %s", strerror(errno));
118*7c478bd9Sstevel@tonic-gate 		pmptr->p_status = VALID;
119*7c478bd9Sstevel@tonic-gate 		pmptr->p_pid = 0;
120*7c478bd9Sstevel@tonic-gate 		Retry = TRUE;
121*7c478bd9Sstevel@tonic-gate 	}
122*7c478bd9Sstevel@tonic-gate 	else {
123*7c478bd9Sstevel@tonic-gate 		/*
124*7c478bd9Sstevel@tonic-gate 		 * The PARENT - store pid of child and close the device
125*7c478bd9Sstevel@tonic-gate 		 */
126*7c478bd9Sstevel@tonic-gate 		pmptr->p_pid = pid;
127*7c478bd9Sstevel@tonic-gate 	}
128*7c478bd9Sstevel@tonic-gate 	if (pmptr->p_fd > 0) {
129*7c478bd9Sstevel@tonic-gate 		(void)close(pmptr->p_fd);
130*7c478bd9Sstevel@tonic-gate 		pmptr->p_fd = 0;
131*7c478bd9Sstevel@tonic-gate 	}
132*7c478bd9Sstevel@tonic-gate 	(void)sigprocmask(SIG_SETMASK, &cset, NULL);
133*7c478bd9Sstevel@tonic-gate 	/*
134*7c478bd9Sstevel@tonic-gate 	 * Wait for child to close file descriptors
135*7c478bd9Sstevel@tonic-gate 	 */
136*7c478bd9Sstevel@tonic-gate 	pcsync_close(pcpipe0, pcpipe1, pid, pmptr->p_fd);
137*7c478bd9Sstevel@tonic-gate }
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate /*
140*7c478bd9Sstevel@tonic-gate  * got_carrier - carrier is detected on the stream
141*7c478bd9Sstevel@tonic-gate  *	       - depends on the flags, different action is taken
142*7c478bd9Sstevel@tonic-gate  *	       - R_FLAG - wait for data
143*7c478bd9Sstevel@tonic-gate  *	       - C_FLAG - if port is not disabled, fork tmchild
144*7c478bd9Sstevel@tonic-gate  *	       - A_FLAG - wait for data
145*7c478bd9Sstevel@tonic-gate  *	       - otherwise - write out prompt, then wait for data
146*7c478bd9Sstevel@tonic-gate  */
147*7c478bd9Sstevel@tonic-gate void
148*7c478bd9Sstevel@tonic-gate got_carrier(pmptr)
149*7c478bd9Sstevel@tonic-gate struct	pmtab	*pmptr;
150*7c478bd9Sstevel@tonic-gate {
151*7c478bd9Sstevel@tonic-gate 	flush_input(pmptr->p_fd);
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	if (pmptr->p_ttyflags & R_FLAG) {
154*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
155*7c478bd9Sstevel@tonic-gate 	debug("R_FLAG");
156*7c478bd9Sstevel@tonic-gate #endif
157*7c478bd9Sstevel@tonic-gate 		return;
158*7c478bd9Sstevel@tonic-gate 	}
159*7c478bd9Sstevel@tonic-gate 	else if ((pmptr->p_ttyflags & (C_FLAG|B_FLAG)) &&
160*7c478bd9Sstevel@tonic-gate 		(State != PM_DISABLED) &&
161*7c478bd9Sstevel@tonic-gate 		(!(pmptr->p_flags & X_FLAG))) {
162*7c478bd9Sstevel@tonic-gate 		fork_tmchild(pmptr);
163*7c478bd9Sstevel@tonic-gate 	}
164*7c478bd9Sstevel@tonic-gate 	else if (pmptr->p_ttyflags & A_FLAG) {
165*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
166*7c478bd9Sstevel@tonic-gate 	debug("A_FLAG");
167*7c478bd9Sstevel@tonic-gate #endif
168*7c478bd9Sstevel@tonic-gate 		return;
169*7c478bd9Sstevel@tonic-gate 	}
170*7c478bd9Sstevel@tonic-gate 	else if (pmptr->p_timeout) {
171*7c478bd9Sstevel@tonic-gate 		fork_tmchild(pmptr);
172*7c478bd9Sstevel@tonic-gate 	}
173*7c478bd9Sstevel@tonic-gate 	else if ( ! (pmptr->p_ttyflags & X_FLAG) ) {
174*7c478bd9Sstevel@tonic-gate 		write_prompt(pmptr->p_fd,pmptr,TRUE,TRUE);
175*7c478bd9Sstevel@tonic-gate 	}
176*7c478bd9Sstevel@tonic-gate }
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate /*
179*7c478bd9Sstevel@tonic-gate  * got_data - data is detected on the stream, fork tmchild
180*7c478bd9Sstevel@tonic-gate  */
181*7c478bd9Sstevel@tonic-gate static void
182*7c478bd9Sstevel@tonic-gate got_data(pmptr)
183*7c478bd9Sstevel@tonic-gate struct	pmtab	*pmptr;
184*7c478bd9Sstevel@tonic-gate {
185*7c478bd9Sstevel@tonic-gate 	struct	sigaction sigact;
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate 	if (tm_checklock(pmptr->p_fd) != 0) {
188*7c478bd9Sstevel@tonic-gate 		pmptr->p_status = LOCKED;
189*7c478bd9Sstevel@tonic-gate 		(void)close(pmptr->p_fd);
190*7c478bd9Sstevel@tonic-gate 		pmptr->p_fd = 0;
191*7c478bd9Sstevel@tonic-gate 		Nlocked++;
192*7c478bd9Sstevel@tonic-gate 		if (Nlocked == 1) {
193*7c478bd9Sstevel@tonic-gate 			sigact.sa_flags = 0;
194*7c478bd9Sstevel@tonic-gate 			sigact.sa_handler = sigalarm;
195*7c478bd9Sstevel@tonic-gate 			(void)sigemptyset(&sigact.sa_mask);
196*7c478bd9Sstevel@tonic-gate 			(void)sigaction(SIGALRM, &sigact, NULL);
197*7c478bd9Sstevel@tonic-gate 			(void)alarm(ALARMTIME);
198*7c478bd9Sstevel@tonic-gate 		}
199*7c478bd9Sstevel@tonic-gate 	}
200*7c478bd9Sstevel@tonic-gate 	else
201*7c478bd9Sstevel@tonic-gate 		fork_tmchild(pmptr);
202*7c478bd9Sstevel@tonic-gate }
203*7c478bd9Sstevel@tonic-gate /*
204*7c478bd9Sstevel@tonic-gate  * got_hup - stream hangup is detected, close the device
205*7c478bd9Sstevel@tonic-gate  */
206*7c478bd9Sstevel@tonic-gate static void
207*7c478bd9Sstevel@tonic-gate got_hup(pmptr)
208*7c478bd9Sstevel@tonic-gate struct	pmtab	*pmptr;
209*7c478bd9Sstevel@tonic-gate {
210*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
211*7c478bd9Sstevel@tonic-gate 	debug("in got hup");
212*7c478bd9Sstevel@tonic-gate #endif
213*7c478bd9Sstevel@tonic-gate 	(void)close(pmptr->p_fd);
214*7c478bd9Sstevel@tonic-gate 	pmptr->p_fd = 0;
215*7c478bd9Sstevel@tonic-gate 	pmptr->p_inservice = 0;
216*7c478bd9Sstevel@tonic-gate 	Retry = TRUE;
217*7c478bd9Sstevel@tonic-gate }
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate /*
221*7c478bd9Sstevel@tonic-gate  *	do_poll	- poll device
222*7c478bd9Sstevel@tonic-gate  *		- if POLLHUP received, close the device
223*7c478bd9Sstevel@tonic-gate  *		- if POLLIN received, fork tmchild.
224*7c478bd9Sstevel@tonic-gate  */
225*7c478bd9Sstevel@tonic-gate void
226*7c478bd9Sstevel@tonic-gate do_poll(fdp,nfds)
227*7c478bd9Sstevel@tonic-gate struct 	pollfd *fdp;
228*7c478bd9Sstevel@tonic-gate int 	nfds;
229*7c478bd9Sstevel@tonic-gate {
230*7c478bd9Sstevel@tonic-gate 	int	i,n;
231*7c478bd9Sstevel@tonic-gate 	struct	pmtab	*pmptr;
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 	n = poll(fdp, (unsigned long)nfds, -1);	/* blocked poll */
234*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
235*7c478bd9Sstevel@tonic-gate 	debug("poll return");
236*7c478bd9Sstevel@tonic-gate #endif
237*7c478bd9Sstevel@tonic-gate 	if (n < 0) {
238*7c478bd9Sstevel@tonic-gate 		if (errno == EINTR)	/* interrupt by signal */
239*7c478bd9Sstevel@tonic-gate 			return;
240*7c478bd9Sstevel@tonic-gate 		fatal("do_poll: poll failed: %s", strerror(errno));
241*7c478bd9Sstevel@tonic-gate 	}
242*7c478bd9Sstevel@tonic-gate 	for (i = 0; (i < nfds)&&(n); i++,fdp++) {
243*7c478bd9Sstevel@tonic-gate 		if (fdp->revents != 0) {
244*7c478bd9Sstevel@tonic-gate 			n--;
245*7c478bd9Sstevel@tonic-gate 			if ((pmptr = find_fd(fdp->fd)) == NULL) {
246*7c478bd9Sstevel@tonic-gate 				log("do_poll: cannot find fd %d in pmtab",
247*7c478bd9Sstevel@tonic-gate 				    fdp->fd);
248*7c478bd9Sstevel@tonic-gate 				continue;
249*7c478bd9Sstevel@tonic-gate 			}
250*7c478bd9Sstevel@tonic-gate 			else if (fdp->revents & POLLHUP) {
251*7c478bd9Sstevel@tonic-gate 				got_hup(pmptr);
252*7c478bd9Sstevel@tonic-gate 			}
253*7c478bd9Sstevel@tonic-gate 			else if (fdp->revents & POLLIN) {
254*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
255*7c478bd9Sstevel@tonic-gate 				debug("got POLLIN");
256*7c478bd9Sstevel@tonic-gate #endif
257*7c478bd9Sstevel@tonic-gate 				got_data(pmptr);
258*7c478bd9Sstevel@tonic-gate 			} else if (fdp->revents & POLLERR) {
259*7c478bd9Sstevel@tonic-gate 				fatal("ttymon[%d]: do_poll: POLLERR on fd %d",
260*7c478bd9Sstevel@tonic-gate 				    getpid(), fdp->fd);
261*7c478bd9Sstevel@tonic-gate 			}
262*7c478bd9Sstevel@tonic-gate 		}
263*7c478bd9Sstevel@tonic-gate 	}
264*7c478bd9Sstevel@tonic-gate }
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate /*
267*7c478bd9Sstevel@tonic-gate  *	sigchild	- handler for SIGCLD
268*7c478bd9Sstevel@tonic-gate  *			- find the pid of dead child
269*7c478bd9Sstevel@tonic-gate  *			- clean utmp if U_FLAG is set
270*7c478bd9Sstevel@tonic-gate  */
271*7c478bd9Sstevel@tonic-gate void
272*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
273*7c478bd9Sstevel@tonic-gate sigchild(n)
274*7c478bd9Sstevel@tonic-gate int	n;	/* this is declared to make cc happy, but it is not used */
275*7c478bd9Sstevel@tonic-gate {
276*7c478bd9Sstevel@tonic-gate 	struct	pmtab	*pmptr;
277*7c478bd9Sstevel@tonic-gate 	struct	sigaction	sigact;
278*7c478bd9Sstevel@tonic-gate 	siginfo_t	info;
279*7c478bd9Sstevel@tonic-gate 	int 	status;
280*7c478bd9Sstevel@tonic-gate 	pid_t 	pid;
281*7c478bd9Sstevel@tonic-gate 	int	rcode;
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
284*7c478bd9Sstevel@tonic-gate 	debug("in sigchild");
285*7c478bd9Sstevel@tonic-gate #endif
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate 	/* find all processes that died */
288*7c478bd9Sstevel@tonic-gate 	for (;;) {
289*7c478bd9Sstevel@tonic-gate 		rcode = waitid(P_ALL, 0, &info, WNOHANG|WEXITED);
290*7c478bd9Sstevel@tonic-gate 		if (rcode == -1 && errno == EINTR)
291*7c478bd9Sstevel@tonic-gate 			continue;
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 		/* If no more children have exited, just return */
294*7c478bd9Sstevel@tonic-gate 		if (rcode == -1 || (pid = info.si_pid) == 0)
295*7c478bd9Sstevel@tonic-gate 			break;
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate 		/* construct status as returned from waitid() */
298*7c478bd9Sstevel@tonic-gate 		status = info.si_status & 0377;
299*7c478bd9Sstevel@tonic-gate 		switch (info.si_code) {
300*7c478bd9Sstevel@tonic-gate 		case CLD_EXITED:
301*7c478bd9Sstevel@tonic-gate 			status <<= 8;
302*7c478bd9Sstevel@tonic-gate 			break;
303*7c478bd9Sstevel@tonic-gate 		case CLD_DUMPED:
304*7c478bd9Sstevel@tonic-gate 			status |= WCOREFLG;
305*7c478bd9Sstevel@tonic-gate 			break;
306*7c478bd9Sstevel@tonic-gate 		case CLD_KILLED:
307*7c478bd9Sstevel@tonic-gate 			break;
308*7c478bd9Sstevel@tonic-gate 		}
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 		if ((pmptr = find_pid(pid)) == NULL) {
311*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
312*7c478bd9Sstevel@tonic-gate 			log("cannot find dead child (%ld) in pmtab", pid);
313*7c478bd9Sstevel@tonic-gate #endif
314*7c478bd9Sstevel@tonic-gate 			/*
315*7c478bd9Sstevel@tonic-gate 			 * This may happen if the entry is deleted from pmtab
316*7c478bd9Sstevel@tonic-gate 			 * before the service exits.
317*7c478bd9Sstevel@tonic-gate 			 * We try to cleanup utmp entry
318*7c478bd9Sstevel@tonic-gate 			 */
319*7c478bd9Sstevel@tonic-gate 			cleanut(pid, status);
320*7c478bd9Sstevel@tonic-gate 		} else {
321*7c478bd9Sstevel@tonic-gate 			if (pmptr->p_flags & U_FLAG)
322*7c478bd9Sstevel@tonic-gate 				cleanut(pid, status);
323*7c478bd9Sstevel@tonic-gate 			pmptr->p_status = VALID;
324*7c478bd9Sstevel@tonic-gate 			pmptr->p_fd = 0;
325*7c478bd9Sstevel@tonic-gate 			pmptr->p_pid = 0;
326*7c478bd9Sstevel@tonic-gate 			pmptr->p_inservice = 0;
327*7c478bd9Sstevel@tonic-gate 			Retry = TRUE;
328*7c478bd9Sstevel@tonic-gate 		}
329*7c478bd9Sstevel@tonic-gate 	}
330*7c478bd9Sstevel@tonic-gate }
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate /*
333*7c478bd9Sstevel@tonic-gate  *	sigterm	- handler for SIGTERM
334*7c478bd9Sstevel@tonic-gate  */
335*7c478bd9Sstevel@tonic-gate void
336*7c478bd9Sstevel@tonic-gate sigterm()
337*7c478bd9Sstevel@tonic-gate {
338*7c478bd9Sstevel@tonic-gate 	fatal("caught SIGTERM");
339*7c478bd9Sstevel@tonic-gate }
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate /*
342*7c478bd9Sstevel@tonic-gate  *	state_change	- this is called when ttymon changes
343*7c478bd9Sstevel@tonic-gate  *			  its internal state between enabled and disabled
344*7c478bd9Sstevel@tonic-gate  */
345*7c478bd9Sstevel@tonic-gate void
346*7c478bd9Sstevel@tonic-gate state_change()
347*7c478bd9Sstevel@tonic-gate {
348*7c478bd9Sstevel@tonic-gate 	struct pmtab *pmptr;
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
351*7c478bd9Sstevel@tonic-gate 	debug("in state_change");
352*7c478bd9Sstevel@tonic-gate #endif
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate 	/*
355*7c478bd9Sstevel@tonic-gate 	 * closing PCpipe will cause attached non-service children
356*7c478bd9Sstevel@tonic-gate 	 * to get SIGPOLL and exit
357*7c478bd9Sstevel@tonic-gate 	 */
358*7c478bd9Sstevel@tonic-gate 	(void)close(PCpipe[0]);
359*7c478bd9Sstevel@tonic-gate 	(void)close(PCpipe[1]);
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate 	/* reopen PCpipe */
362*7c478bd9Sstevel@tonic-gate 	setup_PCpipe();
363*7c478bd9Sstevel@tonic-gate 
364*7c478bd9Sstevel@tonic-gate 	/*
365*7c478bd9Sstevel@tonic-gate 	 * also close all open ports so ttymon can start over
366*7c478bd9Sstevel@tonic-gate 	 * with new internal state
367*7c478bd9Sstevel@tonic-gate 	 */
368*7c478bd9Sstevel@tonic-gate 	for (pmptr = PMtab; pmptr; pmptr = pmptr->p_next) {
369*7c478bd9Sstevel@tonic-gate 		if ((pmptr->p_fd > 0) && (pmptr->p_pid == 0)) {
370*7c478bd9Sstevel@tonic-gate 			(void)close(pmptr->p_fd);
371*7c478bd9Sstevel@tonic-gate 			pmptr->p_fd = 0;
372*7c478bd9Sstevel@tonic-gate 		}
373*7c478bd9Sstevel@tonic-gate 	}
374*7c478bd9Sstevel@tonic-gate 	Retry = TRUE;
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate }
377*7c478bd9Sstevel@tonic-gate 
378*7c478bd9Sstevel@tonic-gate /*
379*7c478bd9Sstevel@tonic-gate  *	re_read	- reread pmtab
380*7c478bd9Sstevel@tonic-gate  *		- kill tmchild if entry changed
381*7c478bd9Sstevel@tonic-gate  */
382*7c478bd9Sstevel@tonic-gate void
383*7c478bd9Sstevel@tonic-gate re_read()
384*7c478bd9Sstevel@tonic-gate {
385*7c478bd9Sstevel@tonic-gate 	extern	struct	pollfd	*Pollp;
386*7c478bd9Sstevel@tonic-gate 	sigset_t	cset;
387*7c478bd9Sstevel@tonic-gate 	sigset_t	tset;
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate 	(void)sigprocmask(SIG_SETMASK, NULL, &cset);
390*7c478bd9Sstevel@tonic-gate 	tset = cset;
391*7c478bd9Sstevel@tonic-gate 	(void)sigaddset(&tset, SIGCLD);
392*7c478bd9Sstevel@tonic-gate 	(void)sigprocmask(SIG_SETMASK, &tset, NULL);
393*7c478bd9Sstevel@tonic-gate 	if (Nlocked > 0) {
394*7c478bd9Sstevel@tonic-gate 		alarm(0);
395*7c478bd9Sstevel@tonic-gate 		Nlocked = 0;
396*7c478bd9Sstevel@tonic-gate 	}
397*7c478bd9Sstevel@tonic-gate 	read_pmtab();
398*7c478bd9Sstevel@tonic-gate 	kill_children();
399*7c478bd9Sstevel@tonic-gate 	(void)sigprocmask(SIG_SETMASK, &cset, NULL);
400*7c478bd9Sstevel@tonic-gate 	purge();
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate 	if (Nentries > Npollfd) {
403*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
404*7c478bd9Sstevel@tonic-gate 		debug("Nentries > Npollfd, reallocating pollfds");
405*7c478bd9Sstevel@tonic-gate #endif
406*7c478bd9Sstevel@tonic-gate 		/* need to malloc more pollfd structure */
407*7c478bd9Sstevel@tonic-gate 		free((char *)Pollp);
408*7c478bd9Sstevel@tonic-gate 		Npollfd = Nentries + 10;
409*7c478bd9Sstevel@tonic-gate 		if (Npollfd > Maxfds)
410*7c478bd9Sstevel@tonic-gate 			Npollfd = Maxfds;
411*7c478bd9Sstevel@tonic-gate 		if ((Pollp = (struct pollfd *)
412*7c478bd9Sstevel@tonic-gate 		    malloc((unsigned)(Npollfd * sizeof(struct pollfd))))
413*7c478bd9Sstevel@tonic-gate 		    == (struct pollfd *)NULL)
414*7c478bd9Sstevel@tonic-gate 			fatal("malloc for Pollp failed");
415*7c478bd9Sstevel@tonic-gate 	}
416*7c478bd9Sstevel@tonic-gate 	Retry = TRUE;
417*7c478bd9Sstevel@tonic-gate }
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate /*
420*7c478bd9Sstevel@tonic-gate  *	find_pid(pid)	- find the corresponding pmtab entry for the pid
421*7c478bd9Sstevel@tonic-gate  */
422*7c478bd9Sstevel@tonic-gate static	struct pmtab *
423*7c478bd9Sstevel@tonic-gate find_pid(pid)
424*7c478bd9Sstevel@tonic-gate pid_t	pid;
425*7c478bd9Sstevel@tonic-gate {
426*7c478bd9Sstevel@tonic-gate 	struct pmtab *pmptr;
427*7c478bd9Sstevel@tonic-gate 
428*7c478bd9Sstevel@tonic-gate 	for (pmptr = PMtab; pmptr; pmptr = pmptr->p_next) {
429*7c478bd9Sstevel@tonic-gate 		if (pmptr->p_pid == pid) {
430*7c478bd9Sstevel@tonic-gate 			return(pmptr);
431*7c478bd9Sstevel@tonic-gate 		}
432*7c478bd9Sstevel@tonic-gate 	}
433*7c478bd9Sstevel@tonic-gate 	return((struct pmtab *)NULL);
434*7c478bd9Sstevel@tonic-gate }
435*7c478bd9Sstevel@tonic-gate 
436*7c478bd9Sstevel@tonic-gate /*
437*7c478bd9Sstevel@tonic-gate  *	find_fd(fd)	- find the corresponding pmtab entry for the fd
438*7c478bd9Sstevel@tonic-gate  */
439*7c478bd9Sstevel@tonic-gate static struct pmtab *
440*7c478bd9Sstevel@tonic-gate find_fd(fd)
441*7c478bd9Sstevel@tonic-gate int	fd;
442*7c478bd9Sstevel@tonic-gate {
443*7c478bd9Sstevel@tonic-gate 	struct pmtab *pmptr;
444*7c478bd9Sstevel@tonic-gate 
445*7c478bd9Sstevel@tonic-gate 	for (pmptr = PMtab; pmptr; pmptr = pmptr->p_next) {
446*7c478bd9Sstevel@tonic-gate 		if (pmptr->p_fd == fd) {
447*7c478bd9Sstevel@tonic-gate 			return(pmptr);
448*7c478bd9Sstevel@tonic-gate 		}
449*7c478bd9Sstevel@tonic-gate 	}
450*7c478bd9Sstevel@tonic-gate 	return((struct pmtab *)NULL);
451*7c478bd9Sstevel@tonic-gate }
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate /*
454*7c478bd9Sstevel@tonic-gate  *	kill_children()	- if the pmtab entry has been changed,
455*7c478bd9Sstevel@tonic-gate  *			  kill tmchild if it is not in service.
456*7c478bd9Sstevel@tonic-gate  *			- close the device if there is no tmchild
457*7c478bd9Sstevel@tonic-gate  */
458*7c478bd9Sstevel@tonic-gate static	void
459*7c478bd9Sstevel@tonic-gate kill_children()
460*7c478bd9Sstevel@tonic-gate {
461*7c478bd9Sstevel@tonic-gate 	struct pmtab *pmptr;
462*7c478bd9Sstevel@tonic-gate 	for (pmptr = PMtab; pmptr; pmptr = pmptr->p_next) {
463*7c478bd9Sstevel@tonic-gate 		if (pmptr->p_status == VALID)
464*7c478bd9Sstevel@tonic-gate 			continue;
465*7c478bd9Sstevel@tonic-gate 		if ((pmptr->p_fd > 0) && (pmptr->p_pid == 0)) {
466*7c478bd9Sstevel@tonic-gate 			(void)close(pmptr->p_fd);
467*7c478bd9Sstevel@tonic-gate 			pmptr->p_fd = 0;
468*7c478bd9Sstevel@tonic-gate 		}
469*7c478bd9Sstevel@tonic-gate 		else if ((pmptr->p_fd == 0) && (pmptr->p_pid > 0)
470*7c478bd9Sstevel@tonic-gate 			&& (pmptr->p_inservice == FALSE)) {
471*7c478bd9Sstevel@tonic-gate 			(void)kill(pmptr->p_pid, SIGTERM);
472*7c478bd9Sstevel@tonic-gate 		}
473*7c478bd9Sstevel@tonic-gate 	}
474*7c478bd9Sstevel@tonic-gate }
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate static	void
477*7c478bd9Sstevel@tonic-gate mark_service(pid)
478*7c478bd9Sstevel@tonic-gate pid_t	pid;
479*7c478bd9Sstevel@tonic-gate {
480*7c478bd9Sstevel@tonic-gate 	struct	pmtab	*pmptr;
481*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
482*7c478bd9Sstevel@tonic-gate 	debug("in mark_service");
483*7c478bd9Sstevel@tonic-gate #endif
484*7c478bd9Sstevel@tonic-gate 	if ((pmptr = find_pid(pid)) == NULL) {
485*7c478bd9Sstevel@tonic-gate 		log("mark_service: cannot find child (%ld) in pmtab", pid);
486*7c478bd9Sstevel@tonic-gate 		return;
487*7c478bd9Sstevel@tonic-gate 	}
488*7c478bd9Sstevel@tonic-gate 	pmptr->p_inservice = TRUE;
489*7c478bd9Sstevel@tonic-gate 	return;
490*7c478bd9Sstevel@tonic-gate }
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate /*
493*7c478bd9Sstevel@tonic-gate  * read_pid(fd)	- read pid info from PCpipe
494*7c478bd9Sstevel@tonic-gate  */
495*7c478bd9Sstevel@tonic-gate static	void
496*7c478bd9Sstevel@tonic-gate read_pid(fd)
497*7c478bd9Sstevel@tonic-gate int	fd;
498*7c478bd9Sstevel@tonic-gate {
499*7c478bd9Sstevel@tonic-gate 	int	ret;
500*7c478bd9Sstevel@tonic-gate 	pid_t	pid;
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate 	for (;;) {
503*7c478bd9Sstevel@tonic-gate 		if ((ret = read(fd,&pid,sizeof(pid))) < 0) {
504*7c478bd9Sstevel@tonic-gate 			if (errno == EINTR)
505*7c478bd9Sstevel@tonic-gate 				continue;
506*7c478bd9Sstevel@tonic-gate 			if (errno == EAGAIN)
507*7c478bd9Sstevel@tonic-gate 				return;
508*7c478bd9Sstevel@tonic-gate 			fatal("read PCpipe failed: %s", strerror(errno));
509*7c478bd9Sstevel@tonic-gate 		}
510*7c478bd9Sstevel@tonic-gate 		if (ret == 0)
511*7c478bd9Sstevel@tonic-gate 			return;
512*7c478bd9Sstevel@tonic-gate 		if (ret != sizeof(pid))
513*7c478bd9Sstevel@tonic-gate 			fatal("read return size incorrect, ret = %d", ret);
514*7c478bd9Sstevel@tonic-gate 
515*7c478bd9Sstevel@tonic-gate 		mark_service(pid);
516*7c478bd9Sstevel@tonic-gate 	}
517*7c478bd9Sstevel@tonic-gate }
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate /*
520*7c478bd9Sstevel@tonic-gate  * sipoll_catch()	- signal handle of SIGPOLL for ttymon
521*7c478bd9Sstevel@tonic-gate  *			- it will check both PCpipe and pmpipe
522*7c478bd9Sstevel@tonic-gate  */
523*7c478bd9Sstevel@tonic-gate void
524*7c478bd9Sstevel@tonic-gate sigpoll_catch()
525*7c478bd9Sstevel@tonic-gate {
526*7c478bd9Sstevel@tonic-gate 	int	ret;
527*7c478bd9Sstevel@tonic-gate 	struct	pollfd	pfd[2];
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
530*7c478bd9Sstevel@tonic-gate 	debug("in sigpoll_catch");
531*7c478bd9Sstevel@tonic-gate #endif
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate 	pfd[0].fd = PCpipe[0];
534*7c478bd9Sstevel@tonic-gate 	pfd[1].fd = Pfd;
535*7c478bd9Sstevel@tonic-gate 	pfd[0].events = POLLIN;
536*7c478bd9Sstevel@tonic-gate 	pfd[1].events = POLLIN;
537*7c478bd9Sstevel@tonic-gate 	if ((ret = poll(pfd, 2, 0)) < 0)
538*7c478bd9Sstevel@tonic-gate 		fatal("sigpoll_catch: poll failed: %s", strerror(errno));
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate 	if (ret > 0) {
541*7c478bd9Sstevel@tonic-gate 		if (pfd[0].revents & POLLIN)
542*7c478bd9Sstevel@tonic-gate 			read_pid(pfd[0].fd);
543*7c478bd9Sstevel@tonic-gate 		if (pfd[1].revents & POLLIN)
544*7c478bd9Sstevel@tonic-gate 			sacpoll();
545*7c478bd9Sstevel@tonic-gate 	}
546*7c478bd9Sstevel@tonic-gate }
547*7c478bd9Sstevel@tonic-gate 
548*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
549*7c478bd9Sstevel@tonic-gate void
550*7c478bd9Sstevel@tonic-gate sigalarm(signo)
551*7c478bd9Sstevel@tonic-gate int	signo;
552*7c478bd9Sstevel@tonic-gate {
553*7c478bd9Sstevel@tonic-gate 	struct pmtab *pmptr;
554*7c478bd9Sstevel@tonic-gate 	struct sigaction sigact;
555*7c478bd9Sstevel@tonic-gate 	int	fd;
556*7c478bd9Sstevel@tonic-gate 	extern	int	check_session();
557*7c478bd9Sstevel@tonic-gate 
558*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
559*7c478bd9Sstevel@tonic-gate 	debug("in sigalarm, Nlocked = %d", Nlocked);
560*7c478bd9Sstevel@tonic-gate #endif
561*7c478bd9Sstevel@tonic-gate 	for (pmptr = PMtab; pmptr; pmptr = pmptr->p_next) {
562*7c478bd9Sstevel@tonic-gate 		if ((pmptr->p_status == LOCKED) && (pmptr->p_fd == 0)) {
563*7c478bd9Sstevel@tonic-gate 			if ((fd=open(pmptr->p_device,O_RDWR|O_NONBLOCK)) == -1){
564*7c478bd9Sstevel@tonic-gate 				log("open (%s) failed: %s", pmptr->p_device,
565*7c478bd9Sstevel@tonic-gate 				    strerror(errno));
566*7c478bd9Sstevel@tonic-gate 				pmptr->p_status = VALID;
567*7c478bd9Sstevel@tonic-gate 				Nlocked--;
568*7c478bd9Sstevel@tonic-gate 				Retry = TRUE;
569*7c478bd9Sstevel@tonic-gate 			}
570*7c478bd9Sstevel@tonic-gate 			else {
571*7c478bd9Sstevel@tonic-gate 				if (tm_checklock(fd) == 0) {
572*7c478bd9Sstevel@tonic-gate 					Nlocked--;
573*7c478bd9Sstevel@tonic-gate 					pmptr->p_fd = fd;
574*7c478bd9Sstevel@tonic-gate 					Retry = TRUE;
575*7c478bd9Sstevel@tonic-gate 				}
576*7c478bd9Sstevel@tonic-gate 				else
577*7c478bd9Sstevel@tonic-gate 					(void)close(fd);
578*7c478bd9Sstevel@tonic-gate 			}
579*7c478bd9Sstevel@tonic-gate 		}
580*7c478bd9Sstevel@tonic-gate 		else if ((pmptr->p_status == SESSION) && (pmptr->p_fd == 0)) {
581*7c478bd9Sstevel@tonic-gate 			if ((fd=open(pmptr->p_device,O_RDWR|O_NONBLOCK)) == -1){
582*7c478bd9Sstevel@tonic-gate 				log("open (%s) failed: %s", pmptr->p_device,
583*7c478bd9Sstevel@tonic-gate 				    strerror(errno));
584*7c478bd9Sstevel@tonic-gate 				pmptr->p_status = VALID;
585*7c478bd9Sstevel@tonic-gate 				Nlocked--;
586*7c478bd9Sstevel@tonic-gate 				Retry = TRUE;
587*7c478bd9Sstevel@tonic-gate 			}
588*7c478bd9Sstevel@tonic-gate 			else {
589*7c478bd9Sstevel@tonic-gate 				if (check_session(fd) == 0) {
590*7c478bd9Sstevel@tonic-gate 					Nlocked--;
591*7c478bd9Sstevel@tonic-gate 					pmptr->p_fd = fd;
592*7c478bd9Sstevel@tonic-gate 					Retry = TRUE;
593*7c478bd9Sstevel@tonic-gate 				}
594*7c478bd9Sstevel@tonic-gate 				else
595*7c478bd9Sstevel@tonic-gate 					(void)close(fd);
596*7c478bd9Sstevel@tonic-gate 			}
597*7c478bd9Sstevel@tonic-gate 		}
598*7c478bd9Sstevel@tonic-gate 		else if ((pmptr->p_status == UNACCESS) && (pmptr->p_fd == 0)) {
599*7c478bd9Sstevel@tonic-gate 			if ((fd=open(pmptr->p_device,O_RDWR|O_NONBLOCK)) == -1){
600*7c478bd9Sstevel@tonic-gate 				log("open (%s) failed: %s", pmptr->p_device,
601*7c478bd9Sstevel@tonic-gate 				    strerror(errno));
602*7c478bd9Sstevel@tonic-gate 				pmptr->p_status = VALID;
603*7c478bd9Sstevel@tonic-gate 				Nlocked--;
604*7c478bd9Sstevel@tonic-gate 				Retry = TRUE;
605*7c478bd9Sstevel@tonic-gate 			}
606*7c478bd9Sstevel@tonic-gate 			else {
607*7c478bd9Sstevel@tonic-gate 				Nlocked--;
608*7c478bd9Sstevel@tonic-gate 				pmptr->p_fd = fd;
609*7c478bd9Sstevel@tonic-gate 				Retry = TRUE;
610*7c478bd9Sstevel@tonic-gate 			}
611*7c478bd9Sstevel@tonic-gate 		}
612*7c478bd9Sstevel@tonic-gate 	}
613*7c478bd9Sstevel@tonic-gate 	if (Nlocked > 0) {
614*7c478bd9Sstevel@tonic-gate 		sigact.sa_flags = 0;
615*7c478bd9Sstevel@tonic-gate 		sigact.sa_handler = sigalarm;
616*7c478bd9Sstevel@tonic-gate 		(void)sigemptyset(&sigact.sa_mask);
617*7c478bd9Sstevel@tonic-gate 		(void)sigaction(SIGALRM, &sigact, NULL);
618*7c478bd9Sstevel@tonic-gate 		(void)alarm(ALARMTIME);
619*7c478bd9Sstevel@tonic-gate 	}
620*7c478bd9Sstevel@tonic-gate 	else {
621*7c478bd9Sstevel@tonic-gate 		sigact.sa_flags = 0;
622*7c478bd9Sstevel@tonic-gate 		sigact.sa_handler = SIG_IGN;
623*7c478bd9Sstevel@tonic-gate 		(void)sigemptyset(&sigact.sa_mask);
624*7c478bd9Sstevel@tonic-gate 		(void)sigaction(SIGALRM, &sigact, NULL);
625*7c478bd9Sstevel@tonic-gate 	}
626*7c478bd9Sstevel@tonic-gate }
627*7c478bd9Sstevel@tonic-gate 
628*7c478bd9Sstevel@tonic-gate /*
629*7c478bd9Sstevel@tonic-gate  * pcsync_close -  For the child process close all open fd's except
630*7c478bd9Sstevel@tonic-gate  * the one that is passed to the routine. Coordinate the reads and
631*7c478bd9Sstevel@tonic-gate  * writes to the pipes by the parent and child process to ensure
632*7c478bd9Sstevel@tonic-gate  * the parent and child processes have closed all the file descriptors
633*7c478bd9Sstevel@tonic-gate  * that are not needed any more.
634*7c478bd9Sstevel@tonic-gate  */
635*7c478bd9Sstevel@tonic-gate static void
636*7c478bd9Sstevel@tonic-gate pcsync_close(p0, p1, pid, fd)
637*7c478bd9Sstevel@tonic-gate int	*p0;
638*7c478bd9Sstevel@tonic-gate int	*p1;
639*7c478bd9Sstevel@tonic-gate int	pid;
640*7c478bd9Sstevel@tonic-gate {
641*7c478bd9Sstevel@tonic-gate 	char	ch;
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate 	if (pid == 0) {				/* Child */
644*7c478bd9Sstevel@tonic-gate 		struct  pmtab   *tp;
645*7c478bd9Sstevel@tonic-gate 		for (tp = PMtab; tp; tp = tp->p_next)
646*7c478bd9Sstevel@tonic-gate 			if ((tp->p_fd > 0) && (tp->p_fd != fd))
647*7c478bd9Sstevel@tonic-gate 				close(tp->p_fd);
648*7c478bd9Sstevel@tonic-gate 		close(p0[1]); close(p1[0]);
649*7c478bd9Sstevel@tonic-gate 		if (read(p0[0], &ch, 1) == 1)
650*7c478bd9Sstevel@tonic-gate 			write(p1[1], "a", 1);
651*7c478bd9Sstevel@tonic-gate 		close(p0[0]); close(p1[1]);
652*7c478bd9Sstevel@tonic-gate 	} else {				/* Parent */
653*7c478bd9Sstevel@tonic-gate 		close(p0[0]); close(p1[1]);
654*7c478bd9Sstevel@tonic-gate 		if (write(p0[1], "a", 1) == 1)
655*7c478bd9Sstevel@tonic-gate 			read(p1[0], &ch, 1);
656*7c478bd9Sstevel@tonic-gate 		close(p0[1]); close(p1[0]);
657*7c478bd9Sstevel@tonic-gate 	}
658*7c478bd9Sstevel@tonic-gate }
659