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