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