17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27*3bb2c156SToomas Soome /* All Rights Reserved */
282756274fSJohn Levon /*
292756274fSJohn Levon * Copyright (c) 2018, Joyent, Inc.
302756274fSJohn Levon */
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate #include <stdlib.h>
347c478bd9Sstevel@tonic-gate #include <stdio.h>
357c478bd9Sstevel@tonic-gate #include <fcntl.h>
367c478bd9Sstevel@tonic-gate #include <errno.h>
377c478bd9Sstevel@tonic-gate #include <poll.h>
387c478bd9Sstevel@tonic-gate #include <string.h>
397c478bd9Sstevel@tonic-gate #include <termio.h>
407c478bd9Sstevel@tonic-gate #include <signal.h>
417c478bd9Sstevel@tonic-gate #include <sys/types.h>
427c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
437c478bd9Sstevel@tonic-gate #include <unistd.h>
447c478bd9Sstevel@tonic-gate #include <sys/wait.h>
457c478bd9Sstevel@tonic-gate #include "ttymon.h"
467c478bd9Sstevel@tonic-gate #include "tmstruct.h"
477c478bd9Sstevel@tonic-gate #include "tmextern.h"
487c478bd9Sstevel@tonic-gate #include "sac.h"
497c478bd9Sstevel@tonic-gate
50*3bb2c156SToomas Soome static struct pmtab *find_pid(pid_t);
51*3bb2c156SToomas Soome static void kill_subprocesses(void);
527c478bd9Sstevel@tonic-gate
53*3bb2c156SToomas Soome static struct pmtab *find_fd(int);
54*3bb2c156SToomas Soome static void pcsync_close(int *, int *, int, int);
557c478bd9Sstevel@tonic-gate
567c478bd9Sstevel@tonic-gate /*
577c478bd9Sstevel@tonic-gate * fork_tmchild - fork child on the device
587c478bd9Sstevel@tonic-gate */
597c478bd9Sstevel@tonic-gate static void
fork_tmchild(struct pmtab * pmptr)60*3bb2c156SToomas Soome fork_tmchild(struct pmtab *pmptr)
617c478bd9Sstevel@tonic-gate {
627c478bd9Sstevel@tonic-gate pid_t pid;
637c478bd9Sstevel@tonic-gate sigset_t cset;
647c478bd9Sstevel@tonic-gate sigset_t tset;
657c478bd9Sstevel@tonic-gate int pcpipe0[2], pcpipe1[2];
667c478bd9Sstevel@tonic-gate int p0;
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate #ifdef DEBUG
697c478bd9Sstevel@tonic-gate debug("in fork_tmchild");
707c478bd9Sstevel@tonic-gate #endif
717c478bd9Sstevel@tonic-gate pmptr->p_inservice = FALSE;
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate /*
74*3bb2c156SToomas Soome * initialize pipe.
757c478bd9Sstevel@tonic-gate * Child has pcpipe[0] pipe fd for reading and writing
767c478bd9Sstevel@tonic-gate * and closes pcpipe[1]. Parent has pcpipe[1] pipe fd for
777c478bd9Sstevel@tonic-gate * reading and writing and closes pcpipe[0].
787c478bd9Sstevel@tonic-gate *
797c478bd9Sstevel@tonic-gate * This way if the child process exits the parent's block
807c478bd9Sstevel@tonic-gate * read on pipe will return immediately as the other end of
817c478bd9Sstevel@tonic-gate * the pipe has closed. Similarly if the parent process exits
827c478bd9Sstevel@tonic-gate * child's blocking read on the pipe will return immediately.
837c478bd9Sstevel@tonic-gate */
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate if (((p0 = pipe(pcpipe0)) == -1) || (pipe(pcpipe1) == -1)) {
867c478bd9Sstevel@tonic-gate if (p0 == 0) {
87*3bb2c156SToomas Soome (void) close(pcpipe0[0]);
88*3bb2c156SToomas Soome (void) close(pcpipe0[1]);
897c478bd9Sstevel@tonic-gate }
907c478bd9Sstevel@tonic-gate log("pipe() failed: %s", strerror(errno));
917c478bd9Sstevel@tonic-gate pmptr->p_status = VALID;
92*3bb2c156SToomas Soome pmptr->p_childpid = 0;
937c478bd9Sstevel@tonic-gate Retry = TRUE;
947c478bd9Sstevel@tonic-gate }
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate /* protect following region from SIGCLD */
97*3bb2c156SToomas Soome (void) sigprocmask(SIG_SETMASK, NULL, &cset);
987c478bd9Sstevel@tonic-gate tset = cset;
99*3bb2c156SToomas Soome (void) sigaddset(&tset, SIGCLD);
100*3bb2c156SToomas Soome (void) sigprocmask(SIG_SETMASK, &tset, NULL);
101*3bb2c156SToomas Soome if ((pid = fork()) == 0) {
1027c478bd9Sstevel@tonic-gate /*
1037c478bd9Sstevel@tonic-gate * Close all file descriptors except pmptr->p_fd
1047c478bd9Sstevel@tonic-gate * Wait for the parent process to close its fd
1057c478bd9Sstevel@tonic-gate */
1067c478bd9Sstevel@tonic-gate pcsync_close(pcpipe0, pcpipe1, pid, pmptr->p_fd);
107*3bb2c156SToomas Soome /* The CHILD */
108*3bb2c156SToomas Soome tmchild(pmptr);
1097c478bd9Sstevel@tonic-gate /* tmchild should never return */
1107c478bd9Sstevel@tonic-gate fatal("tmchild for <%s> returns unexpected", pmptr->p_device);
111*3bb2c156SToomas Soome } else if (pid < 0) {
1127c478bd9Sstevel@tonic-gate log("fork failed: %s", strerror(errno));
1137c478bd9Sstevel@tonic-gate pmptr->p_status = VALID;
114*3bb2c156SToomas Soome pmptr->p_childpid = 0;
1157c478bd9Sstevel@tonic-gate Retry = TRUE;
116*3bb2c156SToomas Soome } else {
1177c478bd9Sstevel@tonic-gate /*
1187c478bd9Sstevel@tonic-gate * The PARENT - store pid of child and close the device
1197c478bd9Sstevel@tonic-gate */
120*3bb2c156SToomas Soome pmptr->p_childpid = pid;
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate if (pmptr->p_fd > 0) {
123*3bb2c156SToomas Soome (void) close(pmptr->p_fd);
124*3bb2c156SToomas Soome pmptr->p_fd = 0;
1257c478bd9Sstevel@tonic-gate }
126*3bb2c156SToomas Soome (void) sigprocmask(SIG_SETMASK, &cset, NULL);
1277c478bd9Sstevel@tonic-gate /*
1287c478bd9Sstevel@tonic-gate * Wait for child to close file descriptors
1297c478bd9Sstevel@tonic-gate */
1307c478bd9Sstevel@tonic-gate pcsync_close(pcpipe0, pcpipe1, pid, pmptr->p_fd);
1317c478bd9Sstevel@tonic-gate }
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate /*
1347c478bd9Sstevel@tonic-gate * got_carrier - carrier is detected on the stream
1357c478bd9Sstevel@tonic-gate * - depends on the flags, different action is taken
1367c478bd9Sstevel@tonic-gate * - R_FLAG - wait for data
1377c478bd9Sstevel@tonic-gate * - C_FLAG - if port is not disabled, fork tmchild
138*3bb2c156SToomas Soome * - A_FLAG - wait for data
1397c478bd9Sstevel@tonic-gate * - otherwise - write out prompt, then wait for data
1407c478bd9Sstevel@tonic-gate */
1417c478bd9Sstevel@tonic-gate void
got_carrier(struct pmtab * pmptr)142*3bb2c156SToomas Soome got_carrier(struct pmtab *pmptr)
1437c478bd9Sstevel@tonic-gate {
1447c478bd9Sstevel@tonic-gate flush_input(pmptr->p_fd);
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate if (pmptr->p_ttyflags & R_FLAG) {
1477c478bd9Sstevel@tonic-gate #ifdef DEBUG
148*3bb2c156SToomas Soome debug("R_FLAG");
1497c478bd9Sstevel@tonic-gate #endif
1507c478bd9Sstevel@tonic-gate return;
151*3bb2c156SToomas Soome } else if ((pmptr->p_ttyflags & (C_FLAG|B_FLAG)) &&
152*3bb2c156SToomas Soome (State != PM_DISABLED) &&
153*3bb2c156SToomas Soome (!(pmptr->p_flags & X_FLAG))) {
1547c478bd9Sstevel@tonic-gate fork_tmchild(pmptr);
155*3bb2c156SToomas Soome } else if (pmptr->p_ttyflags & A_FLAG) {
1567c478bd9Sstevel@tonic-gate #ifdef DEBUG
1577c478bd9Sstevel@tonic-gate debug("A_FLAG");
1587c478bd9Sstevel@tonic-gate #endif
1597c478bd9Sstevel@tonic-gate return;
160*3bb2c156SToomas Soome } else if (pmptr->p_timeout) {
1617c478bd9Sstevel@tonic-gate fork_tmchild(pmptr);
162*3bb2c156SToomas Soome } else if (!(pmptr->p_ttyflags & X_FLAG)) {
163*3bb2c156SToomas Soome write_prompt(pmptr->p_fd, pmptr, TRUE, TRUE);
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate /*
1687c478bd9Sstevel@tonic-gate * got_data - data is detected on the stream, fork tmchild
1697c478bd9Sstevel@tonic-gate */
1707c478bd9Sstevel@tonic-gate static void
got_data(struct pmtab * pmptr)171*3bb2c156SToomas Soome got_data(struct pmtab *pmptr)
1727c478bd9Sstevel@tonic-gate {
1737c478bd9Sstevel@tonic-gate struct sigaction sigact;
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate if (tm_checklock(pmptr->p_fd) != 0) {
1767c478bd9Sstevel@tonic-gate pmptr->p_status = LOCKED;
177*3bb2c156SToomas Soome (void) close(pmptr->p_fd);
1787c478bd9Sstevel@tonic-gate pmptr->p_fd = 0;
1797c478bd9Sstevel@tonic-gate Nlocked++;
1807c478bd9Sstevel@tonic-gate if (Nlocked == 1) {
1817c478bd9Sstevel@tonic-gate sigact.sa_flags = 0;
1827c478bd9Sstevel@tonic-gate sigact.sa_handler = sigalarm;
183*3bb2c156SToomas Soome (void) sigemptyset(&sigact.sa_mask);
184*3bb2c156SToomas Soome (void) sigaction(SIGALRM, &sigact, NULL);
185*3bb2c156SToomas Soome (void) alarm(ALARMTIME);
1867c478bd9Sstevel@tonic-gate }
187*3bb2c156SToomas Soome } else {
1887c478bd9Sstevel@tonic-gate fork_tmchild(pmptr);
189*3bb2c156SToomas Soome }
1907c478bd9Sstevel@tonic-gate }
1917c478bd9Sstevel@tonic-gate /*
1927c478bd9Sstevel@tonic-gate * got_hup - stream hangup is detected, close the device
1937c478bd9Sstevel@tonic-gate */
1947c478bd9Sstevel@tonic-gate static void
got_hup(struct pmtab * pmptr)195*3bb2c156SToomas Soome got_hup(struct pmtab *pmptr)
1967c478bd9Sstevel@tonic-gate {
1977c478bd9Sstevel@tonic-gate #ifdef DEBUG
1987c478bd9Sstevel@tonic-gate debug("in got hup");
1997c478bd9Sstevel@tonic-gate #endif
200*3bb2c156SToomas Soome (void) close(pmptr->p_fd);
2017c478bd9Sstevel@tonic-gate pmptr->p_fd = 0;
2027c478bd9Sstevel@tonic-gate pmptr->p_inservice = 0;
2037c478bd9Sstevel@tonic-gate Retry = TRUE;
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate /*
2087c478bd9Sstevel@tonic-gate * do_poll - poll device
2097c478bd9Sstevel@tonic-gate * - if POLLHUP received, close the device
2107c478bd9Sstevel@tonic-gate * - if POLLIN received, fork tmchild.
2117c478bd9Sstevel@tonic-gate */
2127c478bd9Sstevel@tonic-gate void
do_poll(struct pollfd * fdp,int nfds)213*3bb2c156SToomas Soome do_poll(struct pollfd *fdp, int nfds)
2147c478bd9Sstevel@tonic-gate {
215*3bb2c156SToomas Soome int i, n;
2167c478bd9Sstevel@tonic-gate struct pmtab *pmptr;
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate n = poll(fdp, (unsigned long)nfds, -1); /* blocked poll */
2197c478bd9Sstevel@tonic-gate #ifdef DEBUG
2207c478bd9Sstevel@tonic-gate debug("poll return");
2217c478bd9Sstevel@tonic-gate #endif
2227c478bd9Sstevel@tonic-gate if (n < 0) {
2237c478bd9Sstevel@tonic-gate if (errno == EINTR) /* interrupt by signal */
2247c478bd9Sstevel@tonic-gate return;
2257c478bd9Sstevel@tonic-gate fatal("do_poll: poll failed: %s", strerror(errno));
2267c478bd9Sstevel@tonic-gate }
227*3bb2c156SToomas Soome for (i = 0; (i < nfds) && (n != 0); i++, fdp++) {
2287c478bd9Sstevel@tonic-gate if (fdp->revents != 0) {
2297c478bd9Sstevel@tonic-gate n--;
2307c478bd9Sstevel@tonic-gate if ((pmptr = find_fd(fdp->fd)) == NULL) {
2317c478bd9Sstevel@tonic-gate log("do_poll: cannot find fd %d in pmtab",
2327c478bd9Sstevel@tonic-gate fdp->fd);
2337c478bd9Sstevel@tonic-gate continue;
234*3bb2c156SToomas Soome } else if (fdp->revents & POLLHUP) {
2357c478bd9Sstevel@tonic-gate got_hup(pmptr);
236*3bb2c156SToomas Soome } else if (fdp->revents & POLLIN) {
2377c478bd9Sstevel@tonic-gate #ifdef DEBUG
2387c478bd9Sstevel@tonic-gate debug("got POLLIN");
2397c478bd9Sstevel@tonic-gate #endif
2407c478bd9Sstevel@tonic-gate got_data(pmptr);
2417c478bd9Sstevel@tonic-gate } else if (fdp->revents & POLLERR) {
2427c478bd9Sstevel@tonic-gate fatal("ttymon[%d]: do_poll: POLLERR on fd %d",
2437c478bd9Sstevel@tonic-gate getpid(), fdp->fd);
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate }
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate /*
2507c478bd9Sstevel@tonic-gate * sigchild - handler for SIGCLD
2517c478bd9Sstevel@tonic-gate * - find the pid of dead child
2527c478bd9Sstevel@tonic-gate * - clean utmp if U_FLAG is set
2537c478bd9Sstevel@tonic-gate */
2547c478bd9Sstevel@tonic-gate void
sigchild(int n __unused)255*3bb2c156SToomas Soome sigchild(int n __unused)
2567c478bd9Sstevel@tonic-gate {
2577c478bd9Sstevel@tonic-gate struct pmtab *pmptr;
2587c478bd9Sstevel@tonic-gate siginfo_t info;
259*3bb2c156SToomas Soome int status;
260*3bb2c156SToomas Soome pid_t pid;
2617c478bd9Sstevel@tonic-gate int rcode;
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate #ifdef DEBUG
2647c478bd9Sstevel@tonic-gate debug("in sigchild");
2657c478bd9Sstevel@tonic-gate #endif
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate /* find all processes that died */
2687c478bd9Sstevel@tonic-gate for (;;) {
2697c478bd9Sstevel@tonic-gate rcode = waitid(P_ALL, 0, &info, WNOHANG|WEXITED);
2707c478bd9Sstevel@tonic-gate if (rcode == -1 && errno == EINTR)
2717c478bd9Sstevel@tonic-gate continue;
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate /* If no more children have exited, just return */
2747c478bd9Sstevel@tonic-gate if (rcode == -1 || (pid = info.si_pid) == 0)
2757c478bd9Sstevel@tonic-gate break;
2767c478bd9Sstevel@tonic-gate
2777c478bd9Sstevel@tonic-gate /* construct status as returned from waitid() */
2787c478bd9Sstevel@tonic-gate status = info.si_status & 0377;
2797c478bd9Sstevel@tonic-gate switch (info.si_code) {
2807c478bd9Sstevel@tonic-gate case CLD_EXITED:
2817c478bd9Sstevel@tonic-gate status <<= 8;
2827c478bd9Sstevel@tonic-gate break;
2837c478bd9Sstevel@tonic-gate case CLD_DUMPED:
2847c478bd9Sstevel@tonic-gate status |= WCOREFLG;
2857c478bd9Sstevel@tonic-gate break;
2867c478bd9Sstevel@tonic-gate case CLD_KILLED:
2877c478bd9Sstevel@tonic-gate break;
2887c478bd9Sstevel@tonic-gate }
2897c478bd9Sstevel@tonic-gate
2907c478bd9Sstevel@tonic-gate if ((pmptr = find_pid(pid)) == NULL) {
2917c478bd9Sstevel@tonic-gate #ifdef DEBUG
2927c478bd9Sstevel@tonic-gate log("cannot find dead child (%ld) in pmtab", pid);
2937c478bd9Sstevel@tonic-gate #endif
2947c478bd9Sstevel@tonic-gate /*
2957c478bd9Sstevel@tonic-gate * This may happen if the entry is deleted from pmtab
2967c478bd9Sstevel@tonic-gate * before the service exits.
2977c478bd9Sstevel@tonic-gate * We try to cleanup utmp entry
2987c478bd9Sstevel@tonic-gate */
2997c478bd9Sstevel@tonic-gate cleanut(pid, status);
3007c478bd9Sstevel@tonic-gate } else {
3017c478bd9Sstevel@tonic-gate if (pmptr->p_flags & U_FLAG)
3027c478bd9Sstevel@tonic-gate cleanut(pid, status);
3037c478bd9Sstevel@tonic-gate pmptr->p_status = VALID;
3047c478bd9Sstevel@tonic-gate pmptr->p_fd = 0;
305*3bb2c156SToomas Soome pmptr->p_childpid = 0;
3067c478bd9Sstevel@tonic-gate pmptr->p_inservice = 0;
3077c478bd9Sstevel@tonic-gate Retry = TRUE;
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate }
3107c478bd9Sstevel@tonic-gate }
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate /*
3137c478bd9Sstevel@tonic-gate * sigterm - handler for SIGTERM
3147c478bd9Sstevel@tonic-gate */
3157c478bd9Sstevel@tonic-gate void
sigterm(int _s __unused)316*3bb2c156SToomas Soome sigterm(int _s __unused)
3177c478bd9Sstevel@tonic-gate {
3187c478bd9Sstevel@tonic-gate fatal("caught SIGTERM");
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate /*
3227c478bd9Sstevel@tonic-gate * state_change - this is called when ttymon changes
3237c478bd9Sstevel@tonic-gate * its internal state between enabled and disabled
3247c478bd9Sstevel@tonic-gate */
3257c478bd9Sstevel@tonic-gate void
state_change(void)326*3bb2c156SToomas Soome state_change(void)
3277c478bd9Sstevel@tonic-gate {
3287c478bd9Sstevel@tonic-gate struct pmtab *pmptr;
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate #ifdef DEBUG
3317c478bd9Sstevel@tonic-gate debug("in state_change");
3327c478bd9Sstevel@tonic-gate #endif
3337c478bd9Sstevel@tonic-gate
334*3bb2c156SToomas Soome /*
335*3bb2c156SToomas Soome * closing PCpipe will cause attached non-service children
3367c478bd9Sstevel@tonic-gate * to get SIGPOLL and exit
3377c478bd9Sstevel@tonic-gate */
338*3bb2c156SToomas Soome (void) close(PCpipe[0]);
339*3bb2c156SToomas Soome (void) close(PCpipe[1]);
3407c478bd9Sstevel@tonic-gate
3417c478bd9Sstevel@tonic-gate /* reopen PCpipe */
3427c478bd9Sstevel@tonic-gate setup_PCpipe();
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate /*
3457c478bd9Sstevel@tonic-gate * also close all open ports so ttymon can start over
3467c478bd9Sstevel@tonic-gate * with new internal state
3477c478bd9Sstevel@tonic-gate */
3487c478bd9Sstevel@tonic-gate for (pmptr = PMtab; pmptr; pmptr = pmptr->p_next) {
349*3bb2c156SToomas Soome if ((pmptr->p_fd > 0) && (pmptr->p_childpid == 0)) {
350*3bb2c156SToomas Soome (void) close(pmptr->p_fd);
3517c478bd9Sstevel@tonic-gate pmptr->p_fd = 0;
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate }
3547c478bd9Sstevel@tonic-gate Retry = TRUE;
3557c478bd9Sstevel@tonic-gate
3567c478bd9Sstevel@tonic-gate }
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate /*
3597c478bd9Sstevel@tonic-gate * re_read - reread pmtab
3607c478bd9Sstevel@tonic-gate * - kill tmchild if entry changed
3617c478bd9Sstevel@tonic-gate */
3627c478bd9Sstevel@tonic-gate void
re_read(void)363*3bb2c156SToomas Soome re_read(void)
3647c478bd9Sstevel@tonic-gate {
3657c478bd9Sstevel@tonic-gate sigset_t cset;
3667c478bd9Sstevel@tonic-gate sigset_t tset;
3677c478bd9Sstevel@tonic-gate
368*3bb2c156SToomas Soome (void) sigprocmask(SIG_SETMASK, NULL, &cset);
3697c478bd9Sstevel@tonic-gate tset = cset;
370*3bb2c156SToomas Soome (void) sigaddset(&tset, SIGCLD);
371*3bb2c156SToomas Soome (void) sigprocmask(SIG_SETMASK, &tset, NULL);
3727c478bd9Sstevel@tonic-gate if (Nlocked > 0) {
373*3bb2c156SToomas Soome (void) alarm(0);
3747c478bd9Sstevel@tonic-gate Nlocked = 0;
3757c478bd9Sstevel@tonic-gate }
3767c478bd9Sstevel@tonic-gate read_pmtab();
377*3bb2c156SToomas Soome kill_subprocesses();
378*3bb2c156SToomas Soome (void) sigprocmask(SIG_SETMASK, &cset, NULL);
3797c478bd9Sstevel@tonic-gate purge();
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gate if (Nentries > Npollfd) {
3827c478bd9Sstevel@tonic-gate #ifdef DEBUG
3837c478bd9Sstevel@tonic-gate debug("Nentries > Npollfd, reallocating pollfds");
3847c478bd9Sstevel@tonic-gate #endif
3857c478bd9Sstevel@tonic-gate /* need to malloc more pollfd structure */
386*3bb2c156SToomas Soome free(Pollp);
3877c478bd9Sstevel@tonic-gate Npollfd = Nentries + 10;
3887c478bd9Sstevel@tonic-gate if (Npollfd > Maxfds)
3897c478bd9Sstevel@tonic-gate Npollfd = Maxfds;
390*3bb2c156SToomas Soome Pollp = malloc((unsigned)(Npollfd * sizeof (struct pollfd)));
391*3bb2c156SToomas Soome if (Pollp == NULL)
3927c478bd9Sstevel@tonic-gate fatal("malloc for Pollp failed");
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate Retry = TRUE;
3957c478bd9Sstevel@tonic-gate }
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate /*
3987c478bd9Sstevel@tonic-gate * find_pid(pid) - find the corresponding pmtab entry for the pid
3997c478bd9Sstevel@tonic-gate */
4007c478bd9Sstevel@tonic-gate static struct pmtab *
find_pid(pid_t pid)401*3bb2c156SToomas Soome find_pid(pid_t pid)
4027c478bd9Sstevel@tonic-gate {
4037c478bd9Sstevel@tonic-gate struct pmtab *pmptr;
4047c478bd9Sstevel@tonic-gate
4057c478bd9Sstevel@tonic-gate for (pmptr = PMtab; pmptr; pmptr = pmptr->p_next) {
406*3bb2c156SToomas Soome if (pmptr->p_childpid == pid) {
407*3bb2c156SToomas Soome return (pmptr);
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate }
410*3bb2c156SToomas Soome return (NULL);
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate /*
4147c478bd9Sstevel@tonic-gate * find_fd(fd) - find the corresponding pmtab entry for the fd
4157c478bd9Sstevel@tonic-gate */
4167c478bd9Sstevel@tonic-gate static struct pmtab *
find_fd(int fd)417*3bb2c156SToomas Soome find_fd(int fd)
4187c478bd9Sstevel@tonic-gate {
4197c478bd9Sstevel@tonic-gate struct pmtab *pmptr;
4207c478bd9Sstevel@tonic-gate
4217c478bd9Sstevel@tonic-gate for (pmptr = PMtab; pmptr; pmptr = pmptr->p_next) {
4227c478bd9Sstevel@tonic-gate if (pmptr->p_fd == fd) {
423*3bb2c156SToomas Soome return (pmptr);
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate }
426*3bb2c156SToomas Soome return (NULL);
4277c478bd9Sstevel@tonic-gate }
4287c478bd9Sstevel@tonic-gate
4297c478bd9Sstevel@tonic-gate /*
430*3bb2c156SToomas Soome * kill_subprocesses() - if the pmtab entry has been changed,
4317c478bd9Sstevel@tonic-gate * kill tmchild if it is not in service.
4327c478bd9Sstevel@tonic-gate * - close the device if there is no tmchild
4337c478bd9Sstevel@tonic-gate */
4347c478bd9Sstevel@tonic-gate static void
kill_subprocesses(void)435*3bb2c156SToomas Soome kill_subprocesses(void)
4367c478bd9Sstevel@tonic-gate {
4377c478bd9Sstevel@tonic-gate struct pmtab *pmptr;
438*3bb2c156SToomas Soome
4397c478bd9Sstevel@tonic-gate for (pmptr = PMtab; pmptr; pmptr = pmptr->p_next) {
4407c478bd9Sstevel@tonic-gate if (pmptr->p_status == VALID)
4417c478bd9Sstevel@tonic-gate continue;
442*3bb2c156SToomas Soome if ((pmptr->p_fd > 0) && (pmptr->p_childpid == 0)) {
443*3bb2c156SToomas Soome (void) close(pmptr->p_fd);
4447c478bd9Sstevel@tonic-gate pmptr->p_fd = 0;
445*3bb2c156SToomas Soome } else if ((pmptr->p_fd == 0) && (pmptr->p_childpid > 0) &&
446*3bb2c156SToomas Soome (pmptr->p_inservice == FALSE)) {
447*3bb2c156SToomas Soome (void) kill(pmptr->p_childpid, SIGTERM);
4487c478bd9Sstevel@tonic-gate }
4497c478bd9Sstevel@tonic-gate }
4507c478bd9Sstevel@tonic-gate }
4517c478bd9Sstevel@tonic-gate
4527c478bd9Sstevel@tonic-gate static void
mark_service(pid_t pid)453*3bb2c156SToomas Soome mark_service(pid_t pid)
4547c478bd9Sstevel@tonic-gate {
4557c478bd9Sstevel@tonic-gate struct pmtab *pmptr;
4567c478bd9Sstevel@tonic-gate #ifdef DEBUG
4577c478bd9Sstevel@tonic-gate debug("in mark_service");
4587c478bd9Sstevel@tonic-gate #endif
4597c478bd9Sstevel@tonic-gate if ((pmptr = find_pid(pid)) == NULL) {
4607c478bd9Sstevel@tonic-gate log("mark_service: cannot find child (%ld) in pmtab", pid);
4617c478bd9Sstevel@tonic-gate return;
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate pmptr->p_inservice = TRUE;
4647c478bd9Sstevel@tonic-gate }
4657c478bd9Sstevel@tonic-gate
4667c478bd9Sstevel@tonic-gate /*
4677c478bd9Sstevel@tonic-gate * read_pid(fd) - read pid info from PCpipe
4687c478bd9Sstevel@tonic-gate */
4697c478bd9Sstevel@tonic-gate static void
read_pid(int fd)470*3bb2c156SToomas Soome read_pid(int fd)
4717c478bd9Sstevel@tonic-gate {
4727c478bd9Sstevel@tonic-gate int ret;
4737c478bd9Sstevel@tonic-gate pid_t pid;
4747c478bd9Sstevel@tonic-gate
4757c478bd9Sstevel@tonic-gate for (;;) {
476*3bb2c156SToomas Soome if ((ret = read(fd, &pid, sizeof (pid))) < 0) {
4777c478bd9Sstevel@tonic-gate if (errno == EINTR)
4787c478bd9Sstevel@tonic-gate continue;
479*3bb2c156SToomas Soome if (errno == EAGAIN)
4807c478bd9Sstevel@tonic-gate return;
4817c478bd9Sstevel@tonic-gate fatal("read PCpipe failed: %s", strerror(errno));
4827c478bd9Sstevel@tonic-gate }
4837c478bd9Sstevel@tonic-gate if (ret == 0)
4847c478bd9Sstevel@tonic-gate return;
485*3bb2c156SToomas Soome if (ret != sizeof (pid))
4867c478bd9Sstevel@tonic-gate fatal("read return size incorrect, ret = %d", ret);
4877c478bd9Sstevel@tonic-gate
4887c478bd9Sstevel@tonic-gate mark_service(pid);
4897c478bd9Sstevel@tonic-gate }
4907c478bd9Sstevel@tonic-gate }
4917c478bd9Sstevel@tonic-gate
4927c478bd9Sstevel@tonic-gate /*
4937c478bd9Sstevel@tonic-gate * sipoll_catch() - signal handle of SIGPOLL for ttymon
4947c478bd9Sstevel@tonic-gate * - it will check both PCpipe and pmpipe
4957c478bd9Sstevel@tonic-gate */
4967c478bd9Sstevel@tonic-gate void
sigpoll_catch(int s __unused)497*3bb2c156SToomas Soome sigpoll_catch(int s __unused)
4987c478bd9Sstevel@tonic-gate {
4997c478bd9Sstevel@tonic-gate int ret;
5007c478bd9Sstevel@tonic-gate struct pollfd pfd[2];
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate #ifdef DEBUG
5037c478bd9Sstevel@tonic-gate debug("in sigpoll_catch");
5047c478bd9Sstevel@tonic-gate #endif
5057c478bd9Sstevel@tonic-gate
5067c478bd9Sstevel@tonic-gate pfd[0].fd = PCpipe[0];
5077c478bd9Sstevel@tonic-gate pfd[1].fd = Pfd;
5087c478bd9Sstevel@tonic-gate pfd[0].events = POLLIN;
5097c478bd9Sstevel@tonic-gate pfd[1].events = POLLIN;
5107c478bd9Sstevel@tonic-gate if ((ret = poll(pfd, 2, 0)) < 0)
5117c478bd9Sstevel@tonic-gate fatal("sigpoll_catch: poll failed: %s", strerror(errno));
5127c478bd9Sstevel@tonic-gate
5137c478bd9Sstevel@tonic-gate if (ret > 0) {
514*3bb2c156SToomas Soome if (pfd[0].revents & POLLIN)
5157c478bd9Sstevel@tonic-gate read_pid(pfd[0].fd);
5167c478bd9Sstevel@tonic-gate if (pfd[1].revents & POLLIN)
5177c478bd9Sstevel@tonic-gate sacpoll();
5187c478bd9Sstevel@tonic-gate }
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate void
sigalarm(int signo __unused)522*3bb2c156SToomas Soome sigalarm(int signo __unused)
5237c478bd9Sstevel@tonic-gate {
5247c478bd9Sstevel@tonic-gate struct pmtab *pmptr;
5257c478bd9Sstevel@tonic-gate struct sigaction sigact;
5267c478bd9Sstevel@tonic-gate int fd;
5277c478bd9Sstevel@tonic-gate
5287c478bd9Sstevel@tonic-gate #ifdef DEBUG
5297c478bd9Sstevel@tonic-gate debug("in sigalarm, Nlocked = %d", Nlocked);
5307c478bd9Sstevel@tonic-gate #endif
5317c478bd9Sstevel@tonic-gate for (pmptr = PMtab; pmptr; pmptr = pmptr->p_next) {
5327c478bd9Sstevel@tonic-gate if ((pmptr->p_status == LOCKED) && (pmptr->p_fd == 0)) {
533*3bb2c156SToomas Soome fd = open(pmptr->p_device, O_RDWR | O_NONBLOCK);
534*3bb2c156SToomas Soome if (fd == -1) {
5357c478bd9Sstevel@tonic-gate log("open (%s) failed: %s", pmptr->p_device,
5367c478bd9Sstevel@tonic-gate strerror(errno));
5377c478bd9Sstevel@tonic-gate pmptr->p_status = VALID;
5387c478bd9Sstevel@tonic-gate Nlocked--;
5397c478bd9Sstevel@tonic-gate Retry = TRUE;
540*3bb2c156SToomas Soome } else {
5417c478bd9Sstevel@tonic-gate if (tm_checklock(fd) == 0) {
5427c478bd9Sstevel@tonic-gate Nlocked--;
5437c478bd9Sstevel@tonic-gate pmptr->p_fd = fd;
5447c478bd9Sstevel@tonic-gate Retry = TRUE;
545*3bb2c156SToomas Soome } else {
546*3bb2c156SToomas Soome (void) close(fd);
5477c478bd9Sstevel@tonic-gate }
5487c478bd9Sstevel@tonic-gate }
549*3bb2c156SToomas Soome } else if ((pmptr->p_status == SESSION) && (pmptr->p_fd == 0)) {
550*3bb2c156SToomas Soome fd = open(pmptr->p_device, O_RDWR | O_NONBLOCK);
551*3bb2c156SToomas Soome if (fd == -1) {
5527c478bd9Sstevel@tonic-gate log("open (%s) failed: %s", pmptr->p_device,
5537c478bd9Sstevel@tonic-gate strerror(errno));
5547c478bd9Sstevel@tonic-gate pmptr->p_status = VALID;
5557c478bd9Sstevel@tonic-gate Nlocked--;
5567c478bd9Sstevel@tonic-gate Retry = TRUE;
557*3bb2c156SToomas Soome } else {
5587c478bd9Sstevel@tonic-gate if (check_session(fd) == 0) {
5597c478bd9Sstevel@tonic-gate Nlocked--;
5607c478bd9Sstevel@tonic-gate pmptr->p_fd = fd;
5617c478bd9Sstevel@tonic-gate Retry = TRUE;
562*3bb2c156SToomas Soome } else {
563*3bb2c156SToomas Soome (void) close(fd);
5647c478bd9Sstevel@tonic-gate }
5657c478bd9Sstevel@tonic-gate }
566*3bb2c156SToomas Soome } else if ((pmptr->p_status == UNACCESS) &&
567*3bb2c156SToomas Soome (pmptr->p_fd == 0)) {
568*3bb2c156SToomas Soome fd = open(pmptr->p_device, O_RDWR | O_NONBLOCK);
569*3bb2c156SToomas Soome if (fd == -1) {
5707c478bd9Sstevel@tonic-gate log("open (%s) failed: %s", pmptr->p_device,
5717c478bd9Sstevel@tonic-gate strerror(errno));
5727c478bd9Sstevel@tonic-gate pmptr->p_status = VALID;
5737c478bd9Sstevel@tonic-gate Nlocked--;
5747c478bd9Sstevel@tonic-gate Retry = TRUE;
575*3bb2c156SToomas Soome } else {
5767c478bd9Sstevel@tonic-gate Nlocked--;
5777c478bd9Sstevel@tonic-gate pmptr->p_fd = fd;
5787c478bd9Sstevel@tonic-gate Retry = TRUE;
5797c478bd9Sstevel@tonic-gate }
5807c478bd9Sstevel@tonic-gate }
5817c478bd9Sstevel@tonic-gate }
5827c478bd9Sstevel@tonic-gate if (Nlocked > 0) {
5837c478bd9Sstevel@tonic-gate sigact.sa_flags = 0;
5847c478bd9Sstevel@tonic-gate sigact.sa_handler = sigalarm;
585*3bb2c156SToomas Soome (void) sigemptyset(&sigact.sa_mask);
586*3bb2c156SToomas Soome (void) sigaction(SIGALRM, &sigact, NULL);
587*3bb2c156SToomas Soome (void) alarm(ALARMTIME);
588*3bb2c156SToomas Soome } else {
5897c478bd9Sstevel@tonic-gate sigact.sa_flags = 0;
5907c478bd9Sstevel@tonic-gate sigact.sa_handler = SIG_IGN;
591*3bb2c156SToomas Soome (void) sigemptyset(&sigact.sa_mask);
592*3bb2c156SToomas Soome (void) sigaction(SIGALRM, &sigact, NULL);
5937c478bd9Sstevel@tonic-gate }
5947c478bd9Sstevel@tonic-gate }
5957c478bd9Sstevel@tonic-gate
5967c478bd9Sstevel@tonic-gate /*
5977c478bd9Sstevel@tonic-gate * pcsync_close - For the child process close all open fd's except
5987c478bd9Sstevel@tonic-gate * the one that is passed to the routine. Coordinate the reads and
5997c478bd9Sstevel@tonic-gate * writes to the pipes by the parent and child process to ensure
6007c478bd9Sstevel@tonic-gate * the parent and child processes have closed all the file descriptors
6017c478bd9Sstevel@tonic-gate * that are not needed any more.
6027c478bd9Sstevel@tonic-gate */
6037c478bd9Sstevel@tonic-gate static void
pcsync_close(int * p0,int * p1,int pid,int fd)6042756274fSJohn Levon pcsync_close(int *p0, int *p1, int pid, int fd)
6057c478bd9Sstevel@tonic-gate {
6067c478bd9Sstevel@tonic-gate char ch;
6077c478bd9Sstevel@tonic-gate
6087c478bd9Sstevel@tonic-gate if (pid == 0) { /* Child */
6097c478bd9Sstevel@tonic-gate struct pmtab *tp;
6107c478bd9Sstevel@tonic-gate for (tp = PMtab; tp; tp = tp->p_next)
6117c478bd9Sstevel@tonic-gate if ((tp->p_fd > 0) && (tp->p_fd != fd))
612*3bb2c156SToomas Soome (void) close(tp->p_fd);
613*3bb2c156SToomas Soome (void) close(p0[1]);
614*3bb2c156SToomas Soome (void) close(p1[0]);
6157c478bd9Sstevel@tonic-gate if (read(p0[0], &ch, 1) == 1)
616*3bb2c156SToomas Soome (void) write(p1[1], "a", 1);
617*3bb2c156SToomas Soome (void) close(p0[0]);
618*3bb2c156SToomas Soome (void) close(p1[1]);
6197c478bd9Sstevel@tonic-gate } else { /* Parent */
620*3bb2c156SToomas Soome (void) close(p0[0]);
621*3bb2c156SToomas Soome (void) close(p1[1]);
6227c478bd9Sstevel@tonic-gate if (write(p0[1], "a", 1) == 1)
623*3bb2c156SToomas Soome (void) read(p1[0], &ch, 1);
624*3bb2c156SToomas Soome (void) close(p0[1]);
625*3bb2c156SToomas Soome (void) close(p1[0]);
6267c478bd9Sstevel@tonic-gate }
6277c478bd9Sstevel@tonic-gate }
628