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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate /* 26*7c478bd9Sstevel@tonic-gate * Copyright (c) 1998 by Sun Microsystems, Inc. 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" /* SVr4.0 1.14 */ 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate #include <stdio.h> 33*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 34*7c478bd9Sstevel@tonic-gate #include <ctype.h> 35*7c478bd9Sstevel@tonic-gate #include <signal.h> 36*7c478bd9Sstevel@tonic-gate #include <errno.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 41*7c478bd9Sstevel@tonic-gate #include <unistd.h> 42*7c478bd9Sstevel@tonic-gate #include <utmpx.h> 43*7c478bd9Sstevel@tonic-gate #include <memory.h> 44*7c478bd9Sstevel@tonic-gate #include "msgs.h" 45*7c478bd9Sstevel@tonic-gate #include "extern.h" 46*7c478bd9Sstevel@tonic-gate #include <sac.h> 47*7c478bd9Sstevel@tonic-gate #include "misc.h" 48*7c478bd9Sstevel@tonic-gate #include "structs.h" 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate #include <security/pam_appl.h> 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate #define RESP 1 /* pollfail via no response to sanity poll */ 53*7c478bd9Sstevel@tonic-gate #define DEATH 2 /* pollfail via child death */ 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate /* signal whose dispositions will be changed */ 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate static struct sigaction Sigpoll; /* SIGPOLL */ 58*7c478bd9Sstevel@tonic-gate static struct sigaction Sigcld; /* SIGCLD */ 59*7c478bd9Sstevel@tonic-gate static struct sigaction Sigalrm; /* SIGALRM */ 60*7c478bd9Sstevel@tonic-gate static sigset_t Origmask; /* original signal mask */ 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate void usage(void); 63*7c478bd9Sstevel@tonic-gate void initialize(void); 64*7c478bd9Sstevel@tonic-gate void startpms(void); 65*7c478bd9Sstevel@tonic-gate void readutmpx(void); 66*7c478bd9Sstevel@tonic-gate int startpm(struct sactab *); 67*7c478bd9Sstevel@tonic-gate void cleanutx(struct sactab *); 68*7c478bd9Sstevel@tonic-gate void account(struct sactab *, pid_t); 69*7c478bd9Sstevel@tonic-gate void startit(struct sactab *); 70*7c478bd9Sstevel@tonic-gate char **mkargv(struct sactab *); 71*7c478bd9Sstevel@tonic-gate void pollpms(void); 72*7c478bd9Sstevel@tonic-gate void reap(int); 73*7c478bd9Sstevel@tonic-gate void pollfail(struct sactab *, int); 74*7c478bd9Sstevel@tonic-gate void readpipe(void); 75*7c478bd9Sstevel@tonic-gate int validstate(unchar); 76*7c478bd9Sstevel@tonic-gate int mk_cmd_pipe(void); 77*7c478bd9Sstevel@tonic-gate void startpoll(void); 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* 82*7c478bd9Sstevel@tonic-gate * main - scan args for sac, initialize everything, and wait for commands 83*7c478bd9Sstevel@tonic-gate * from sacadm via the command pipe 84*7c478bd9Sstevel@tonic-gate */ 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 87*7c478bd9Sstevel@tonic-gate { 88*7c478bd9Sstevel@tonic-gate int c; /* place to hold options */ 89*7c478bd9Sstevel@tonic-gate struct sigaction sigact; /* for signal handling */ 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, NULL, &Origmask); 92*7c478bd9Sstevel@tonic-gate if (argc == 1) 93*7c478bd9Sstevel@tonic-gate usage(); 94*7c478bd9Sstevel@tonic-gate (void) setpgrp(); 95*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "t:")) != -1) { 96*7c478bd9Sstevel@tonic-gate switch (c) { 97*7c478bd9Sstevel@tonic-gate case 't': 98*7c478bd9Sstevel@tonic-gate if (Stime != 0) 99*7c478bd9Sstevel@tonic-gate usage(); 100*7c478bd9Sstevel@tonic-gate Stime = atoi(optarg); 101*7c478bd9Sstevel@tonic-gate if (Stime <= 0) 102*7c478bd9Sstevel@tonic-gate usage(); 103*7c478bd9Sstevel@tonic-gate break; 104*7c478bd9Sstevel@tonic-gate case '?': 105*7c478bd9Sstevel@tonic-gate usage(); 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate } 108*7c478bd9Sstevel@tonic-gate if (optind < argc) 109*7c478bd9Sstevel@tonic-gate usage(); 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate initialize(); 112*7c478bd9Sstevel@tonic-gate sigact.sa_flags = 0; 113*7c478bd9Sstevel@tonic-gate sigact.sa_handler = pollpms; 114*7c478bd9Sstevel@tonic-gate (void) sigemptyset(&sigact.sa_mask); 115*7c478bd9Sstevel@tonic-gate (void) sigaddset(&sigact.sa_mask, SIGALRM); 116*7c478bd9Sstevel@tonic-gate (void) sigaction(SIGALRM, &sigact, &Sigalrm); 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate /* 119*7c478bd9Sstevel@tonic-gate * minimize time spent in STARTING or UNKNOWN, pollpms() sets alarm 120*7c478bd9Sstevel@tonic-gate */ 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate pollpms(); 123*7c478bd9Sstevel@tonic-gate for (;;) 124*7c478bd9Sstevel@tonic-gate readpipe(); 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate /* 129*7c478bd9Sstevel@tonic-gate * usage - output a usage message on the console 130*7c478bd9Sstevel@tonic-gate */ 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate void 133*7c478bd9Sstevel@tonic-gate usage() 134*7c478bd9Sstevel@tonic-gate { 135*7c478bd9Sstevel@tonic-gate FILE *fp; /* scratch file pointer */ 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate fp = fopen("/dev/console", "w"); 138*7c478bd9Sstevel@tonic-gate if (fp) 139*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "SAC: Usage: sac -t sanity_interval\n"); 140*7c478bd9Sstevel@tonic-gate exit(1); 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate /* 145*7c478bd9Sstevel@tonic-gate * initialize - initialization stuff 146*7c478bd9Sstevel@tonic-gate */ 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate void 150*7c478bd9Sstevel@tonic-gate initialize() 151*7c478bd9Sstevel@tonic-gate { 152*7c478bd9Sstevel@tonic-gate int ret; /* return code from doconfig() */ 153*7c478bd9Sstevel@tonic-gate struct sigaction sigact; /* for signal handling */ 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate openlog(); 156*7c478bd9Sstevel@tonic-gate log("*** SAC starting ***"); 157*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 158*7c478bd9Sstevel@tonic-gate opendebug(); 159*7c478bd9Sstevel@tonic-gate log("Debugging turned on"); 160*7c478bd9Sstevel@tonic-gate #endif 161*7c478bd9Sstevel@tonic-gate if (chdir(HOME) < 0) 162*7c478bd9Sstevel@tonic-gate error(E_CHDIR, EXIT); 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate /* 165*7c478bd9Sstevel@tonic-gate * pass an invalid fd, shouldn't be doing pushes and pops in this per-system 166*7c478bd9Sstevel@tonic-gate * configuration script (_sysconfig) 167*7c478bd9Sstevel@tonic-gate */ 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate if ((ret = doconfig(-1, SYSCONFIG, 0)) != 0) { 170*7c478bd9Sstevel@tonic-gate if (ret == -1) 171*7c478bd9Sstevel@tonic-gate error(E_SYSCONF, EXIT); 172*7c478bd9Sstevel@tonic-gate else { 173*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, 174*7c478bd9Sstevel@tonic-gate "Error in _sysconfig: line %d", ret); 175*7c478bd9Sstevel@tonic-gate log(Scratch); 176*7c478bd9Sstevel@tonic-gate error(E_BADSYSCONF, EXIT); 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate } 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate sigact.sa_flags = 0; 181*7c478bd9Sstevel@tonic-gate sigact.sa_handler = reap; 182*7c478bd9Sstevel@tonic-gate (void) sigemptyset(&sigact.sa_mask); 183*7c478bd9Sstevel@tonic-gate (void) sigaddset(&sigact.sa_mask, SIGCLD); 184*7c478bd9Sstevel@tonic-gate (void) sigaction(SIGCLD, &sigact, &Sigcld); 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate /* 187*7c478bd9Sstevel@tonic-gate * establish pipe for PMS to communicate with sac 188*7c478bd9Sstevel@tonic-gate */ 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate if (access("_sacpipe", 0) != 0) { 191*7c478bd9Sstevel@tonic-gate /* not there, create one */ 192*7c478bd9Sstevel@tonic-gate (void) umask(0); 193*7c478bd9Sstevel@tonic-gate if (mknod("_sacpipe", S_IFIFO | 0600, 0) < 0) 194*7c478bd9Sstevel@tonic-gate error(E_NOPIPE, EXIT); 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate Sfd = open("_sacpipe", O_RDWR); 197*7c478bd9Sstevel@tonic-gate if (Sfd < 0) 198*7c478bd9Sstevel@tonic-gate error(E_NOPIPE, EXIT); 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate /* 201*7c478bd9Sstevel@tonic-gate * establish pipe for sacadm to communicate with sac 202*7c478bd9Sstevel@tonic-gate */ 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate Cfd = mk_cmd_pipe(); 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate /* 207*7c478bd9Sstevel@tonic-gate * read in _sactab, but don't start port monitors as a by-product 208*7c478bd9Sstevel@tonic-gate * since we may be in recovery - start them explicitly instead 209*7c478bd9Sstevel@tonic-gate */ 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate read_table(FALSE); 212*7c478bd9Sstevel@tonic-gate startpoll(); 213*7c478bd9Sstevel@tonic-gate startpms(); 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate /* 218*7c478bd9Sstevel@tonic-gate * startpms - start initial set of port monitors 219*7c478bd9Sstevel@tonic-gate */ 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate void 223*7c478bd9Sstevel@tonic-gate startpms() 224*7c478bd9Sstevel@tonic-gate { 225*7c478bd9Sstevel@tonic-gate struct sactab *sp; /* working pointer */ 226*7c478bd9Sstevel@tonic-gate int rflag; /* recovery flag */ 227*7c478bd9Sstevel@tonic-gate pid_t checklock(); 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate /* 230*7c478bd9Sstevel@tonic-gate * check to see if we're really a recovering SAC (if any port monitors hold 231*7c478bd9Sstevel@tonic-gate * locks, assume that we're in recovery), if so, start differently 232*7c478bd9Sstevel@tonic-gate */ 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate rflag = 0; 235*7c478bd9Sstevel@tonic-gate for (sp = Sactab; sp; sp = sp->sc_next) { 236*7c478bd9Sstevel@tonic-gate if (checklock(sp)) { 237*7c478bd9Sstevel@tonic-gate rflag = 1; 238*7c478bd9Sstevel@tonic-gate sp->sc_sstate = sp->sc_pstate = UNKNOWN; 239*7c478bd9Sstevel@tonic-gate sp->sc_ok = 1; 240*7c478bd9Sstevel@tonic-gate sp->sc_exit = 0; 241*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, "%s/_pmpipe", sp->sc_tag); 242*7c478bd9Sstevel@tonic-gate sp->sc_fd = open(Scratch, O_RDWR); 243*7c478bd9Sstevel@tonic-gate if (sp->sc_fd < 0) { 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate /* 246*7c478bd9Sstevel@tonic-gate * if we get into here, we're in deep trouble. PM seems to be running 247*7c478bd9Sstevel@tonic-gate * and we're trying to recover, but we can't talk to it. Unfortunately, 248*7c478bd9Sstevel@tonic-gate * there's not much that can be done other than to try and restore a 249*7c478bd9Sstevel@tonic-gate * sane state. By setting sp->sc_ok to 0, this will look like a poll failure 250*7c478bd9Sstevel@tonic-gate * and if sp->rs_rsmax > 0, PM will be restarted. 251*7c478bd9Sstevel@tonic-gate */ 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, 254*7c478bd9Sstevel@tonic-gate "Could not open _pmpipe for port monitor <%s>", 255*7c478bd9Sstevel@tonic-gate sp->sc_tag); 256*7c478bd9Sstevel@tonic-gate log(Scratch); 257*7c478bd9Sstevel@tonic-gate (void) sendsig(sp, SIGTERM); 258*7c478bd9Sstevel@tonic-gate sp->sc_ok = 0; 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate } 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate if (rflag) { 263*7c478bd9Sstevel@tonic-gate readutmpx(); 264*7c478bd9Sstevel@tonic-gate log("SAC in recovery"); 265*7c478bd9Sstevel@tonic-gate return; 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate /* 269*7c478bd9Sstevel@tonic-gate * normal startup 270*7c478bd9Sstevel@tonic-gate */ 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate for (sp = Sactab; sp; sp = sp->sc_next) { 273*7c478bd9Sstevel@tonic-gate if (sp->sc_flags & X_FLAG) { 274*7c478bd9Sstevel@tonic-gate /* System Administator specified don't start */ 275*7c478bd9Sstevel@tonic-gate continue; 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate (void) startpm(sp); 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate /* 283*7c478bd9Sstevel@tonic-gate * readutmpx - read the utmpx file to find out the ids of running port 284*7c478bd9Sstevel@tonic-gate * monitors (only called during a recover start up). Note: 285*7c478bd9Sstevel@tonic-gate * after a sac failure, init will inherit all of the port 286*7c478bd9Sstevel@tonic-gate * monitors and should get the SIGCLD's if they die (and 287*7c478bd9Sstevel@tonic-gate * will clean up). This is mainly for stuck processes, 288*7c478bd9Sstevel@tonic-gate * although init would get the SIGCLD when the stuckie gets 289*7c478bd9Sstevel@tonic-gate * killed, it doesn't hurt to have the sac check. This is 290*7c478bd9Sstevel@tonic-gate * only done once. 291*7c478bd9Sstevel@tonic-gate * 292*7c478bd9Sstevel@tonic-gate */ 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate void 296*7c478bd9Sstevel@tonic-gate readutmpx() 297*7c478bd9Sstevel@tonic-gate { 298*7c478bd9Sstevel@tonic-gate struct sactab *sp; /* working pointer */ 299*7c478bd9Sstevel@tonic-gate struct sactab *savesp; /* rembered port monitor match */ 300*7c478bd9Sstevel@tonic-gate struct utmpx *uxp; /* working pointer */ 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate setutxent(); 303*7c478bd9Sstevel@tonic-gate while (uxp = getutxent()) { 304*7c478bd9Sstevel@tonic-gate /* we're only interested in login processes */ 305*7c478bd9Sstevel@tonic-gate if (uxp->ut_type != LOGIN_PROCESS) 306*7c478bd9Sstevel@tonic-gate continue; 307*7c478bd9Sstevel@tonic-gate if (uxp->ut_user[sizeof (uxp->ut_user) - 1] == '\0') { 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate /* 310*7c478bd9Sstevel@tonic-gate * possible port monitor and name is short enough to do a normal compare 311*7c478bd9Sstevel@tonic-gate */ 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate sp = findpm(uxp->ut_user); 314*7c478bd9Sstevel@tonic-gate if (sp && (sp->sc_sstate == UNKNOWN)) { 315*7c478bd9Sstevel@tonic-gate /* found one */ 316*7c478bd9Sstevel@tonic-gate (void) memcpy(sp->sc_utid, uxp->ut_id, IDLEN); 317*7c478bd9Sstevel@tonic-gate sp->sc_pid = uxp->ut_pid; 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate } else { 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate /* 322*7c478bd9Sstevel@tonic-gate * possible port monitor name, but it could have been truncated. If 323*7c478bd9Sstevel@tonic-gate * a match is found on a unique prefix, then it should be the correct 324*7c478bd9Sstevel@tonic-gate * entry. If an ambiguity is found, ignore the entry, init will clean 325*7c478bd9Sstevel@tonic-gate * up the entry if it dies. 326*7c478bd9Sstevel@tonic-gate */ 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate savesp = NULL; 329*7c478bd9Sstevel@tonic-gate for (sp = Sactab; sp; sp = sp->sc_next) { 330*7c478bd9Sstevel@tonic-gate if (strncmp(uxp->ut_user, sp->sc_tag, 331*7c478bd9Sstevel@tonic-gate sizeof (uxp->ut_user)) == 0) { 332*7c478bd9Sstevel@tonic-gate if (savesp) { 333*7c478bd9Sstevel@tonic-gate /* already found a match */ 334*7c478bd9Sstevel@tonic-gate savesp = NULL; 335*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, 336*7c478bd9Sstevel@tonic-gate "ambiguous utmpx entry <%.8s>", 337*7c478bd9Sstevel@tonic-gate sp->sc_tag); 338*7c478bd9Sstevel@tonic-gate log(Scratch); 339*7c478bd9Sstevel@tonic-gate break; 340*7c478bd9Sstevel@tonic-gate } else { 341*7c478bd9Sstevel@tonic-gate savesp = sp; 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate if (savesp && (savesp->sc_sstate == UNKNOWN)) { 346*7c478bd9Sstevel@tonic-gate /* found it */ 347*7c478bd9Sstevel@tonic-gate (void) memcpy(savesp->sc_utid, uxp->ut_id, 348*7c478bd9Sstevel@tonic-gate IDLEN); 349*7c478bd9Sstevel@tonic-gate savesp->sc_pid = uxp->ut_pid; 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate endutxent(); 354*7c478bd9Sstevel@tonic-gate } 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate /* 358*7c478bd9Sstevel@tonic-gate * startpm - start a particular PM, return code: 359*7c478bd9Sstevel@tonic-gate * -1: _pid file locked 360*7c478bd9Sstevel@tonic-gate * -2: any other reason 361*7c478bd9Sstevel@tonic-gate * 362*7c478bd9Sstevel@tonic-gate * args: sp - pointer to sac's port monitor information for 363*7c478bd9Sstevel@tonic-gate * designated port monitor 364*7c478bd9Sstevel@tonic-gate */ 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate int 367*7c478bd9Sstevel@tonic-gate startpm(struct sactab *sp) 368*7c478bd9Sstevel@tonic-gate { 369*7c478bd9Sstevel@tonic-gate sigset_t cset; /* for signal handling */ 370*7c478bd9Sstevel@tonic-gate sigset_t tset; /* for signal handling */ 371*7c478bd9Sstevel@tonic-gate pid_t pid; /* pid of new port monitor */ 372*7c478bd9Sstevel@tonic-gate pid_t checklock(); 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 375*7c478bd9Sstevel@tonic-gate debug("in startpm"); 376*7c478bd9Sstevel@tonic-gate #endif 377*7c478bd9Sstevel@tonic-gate if (checklock(sp)) { 378*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, 379*7c478bd9Sstevel@tonic-gate "could not start <%s> - _pid file locked", sp->sc_tag); 380*7c478bd9Sstevel@tonic-gate log(Scratch); 381*7c478bd9Sstevel@tonic-gate return (-1); 382*7c478bd9Sstevel@tonic-gate } 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, "%s/_pmpipe", sp->sc_tag); 385*7c478bd9Sstevel@tonic-gate if (access(Scratch, 0) != 0) { 386*7c478bd9Sstevel@tonic-gate /* not there, create one */ 387*7c478bd9Sstevel@tonic-gate (void) umask(0); 388*7c478bd9Sstevel@tonic-gate if (mknod(Scratch, S_IFIFO | 0600, 0) < 0) { 389*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, 390*7c478bd9Sstevel@tonic-gate "Could not create _pmpipe for port monitor <%s>, errno is %d", 391*7c478bd9Sstevel@tonic-gate sp->sc_tag, errno); 392*7c478bd9Sstevel@tonic-gate log(Scratch); 393*7c478bd9Sstevel@tonic-gate return (-2); 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate } 396*7c478bd9Sstevel@tonic-gate sp->sc_fd = open(Scratch, O_RDWR); 397*7c478bd9Sstevel@tonic-gate if (sp->sc_fd < 0) { 398*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, 399*7c478bd9Sstevel@tonic-gate "Could not open _pmpipe for port monitor <%s>, errno is %d", 400*7c478bd9Sstevel@tonic-gate sp->sc_tag, errno); 401*7c478bd9Sstevel@tonic-gate log(Scratch); 402*7c478bd9Sstevel@tonic-gate return (-2); 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate /* in case child dies too quickly */ 406*7c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, NULL, &cset); 407*7c478bd9Sstevel@tonic-gate tset = cset; 408*7c478bd9Sstevel@tonic-gate (void) sigaddset(&tset, SIGCLD); 409*7c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &tset, NULL); 410*7c478bd9Sstevel@tonic-gate if ((pid = fork()) < 0) { 411*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, 412*7c478bd9Sstevel@tonic-gate "Could not fork port monitor <%s>", sp->sc_tag); 413*7c478bd9Sstevel@tonic-gate log(Scratch); 414*7c478bd9Sstevel@tonic-gate return (-2); 415*7c478bd9Sstevel@tonic-gate } else if (!pid) { 416*7c478bd9Sstevel@tonic-gate startit(sp); 417*7c478bd9Sstevel@tonic-gate /* no return */ 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate /* 421*7c478bd9Sstevel@tonic-gate * clean up old utmpx if its there 422*7c478bd9Sstevel@tonic-gate */ 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate cleanutx(sp); 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate /* 427*7c478bd9Sstevel@tonic-gate * create a utmpx entry and set initial states 428*7c478bd9Sstevel@tonic-gate */ 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate account(sp, pid); 431*7c478bd9Sstevel@tonic-gate sp->sc_pstate = STARTING; 432*7c478bd9Sstevel@tonic-gate if (sp->sc_lstate == NOTRUNNING) 433*7c478bd9Sstevel@tonic-gate sp->sc_sstate = (sp->sc_flags & D_FLAG) ? DISABLED : ENABLED; 434*7c478bd9Sstevel@tonic-gate else 435*7c478bd9Sstevel@tonic-gate sp->sc_sstate = sp->sc_lstate; 436*7c478bd9Sstevel@tonic-gate sp->sc_ok = 1; 437*7c478bd9Sstevel@tonic-gate sp->sc_exit = 0; 438*7c478bd9Sstevel@tonic-gate sp->sc_pid = pid; 439*7c478bd9Sstevel@tonic-gate /* ok to take signals now that the table is up-to-table */ 440*7c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &cset, NULL); 441*7c478bd9Sstevel@tonic-gate return (0); 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate /* 446*7c478bd9Sstevel@tonic-gate * cleanutx - clean out a utmpx record for a port monitor 447*7c478bd9Sstevel@tonic-gate * 448*7c478bd9Sstevel@tonic-gate * args: sp - pointer to sac's port monitor information for 449*7c478bd9Sstevel@tonic-gate * designated port monitor 450*7c478bd9Sstevel@tonic-gate */ 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate void 454*7c478bd9Sstevel@tonic-gate cleanutx(struct sactab *sp) 455*7c478bd9Sstevel@tonic-gate { 456*7c478bd9Sstevel@tonic-gate int i; /* scratch variable */ 457*7c478bd9Sstevel@tonic-gate int zerocheck; /* scratch variable */ 458*7c478bd9Sstevel@tonic-gate char buf[SIZE]; /* scratch buffer */ 459*7c478bd9Sstevel@tonic-gate pam_handle_t *pamh; /* PAM auth descriptor */ 460*7c478bd9Sstevel@tonic-gate struct utmpx ut; 461*7c478bd9Sstevel@tonic-gate struct utmpx *up; 462*7c478bd9Sstevel@tonic-gate int pid; 463*7c478bd9Sstevel@tonic-gate char user[sizeof (up->ut_user) + 1]; 464*7c478bd9Sstevel@tonic-gate char ttyn[sizeof (up->ut_line) + 1]; 465*7c478bd9Sstevel@tonic-gate char rhost[sizeof (up->ut_host) + 1]; 466*7c478bd9Sstevel@tonic-gate /* 467*7c478bd9Sstevel@tonic-gate * check to see if there is a utmpx entry to clean up (indicated by a non 468*7c478bd9Sstevel@tonic-gate * zero utmpx id 469*7c478bd9Sstevel@tonic-gate */ 470*7c478bd9Sstevel@tonic-gate zerocheck = 0; 471*7c478bd9Sstevel@tonic-gate for (i = 0; i < IDLEN; ++i) { 472*7c478bd9Sstevel@tonic-gate zerocheck += sp->sc_utid[i]; 473*7c478bd9Sstevel@tonic-gate } 474*7c478bd9Sstevel@tonic-gate if (zerocheck == 0) 475*7c478bd9Sstevel@tonic-gate return; 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate pid = sp->sc_pid; 478*7c478bd9Sstevel@tonic-gate setutxent(); 479*7c478bd9Sstevel@tonic-gate while (up = getutxent()) { 480*7c478bd9Sstevel@tonic-gate if (up->ut_pid == pid) { 481*7c478bd9Sstevel@tonic-gate if (up->ut_type == DEAD_PROCESS) { 482*7c478bd9Sstevel@tonic-gate /* 483*7c478bd9Sstevel@tonic-gate * Cleaned up elsewhere. 484*7c478bd9Sstevel@tonic-gate */ 485*7c478bd9Sstevel@tonic-gate break; 486*7c478bd9Sstevel@tonic-gate } 487*7c478bd9Sstevel@tonic-gate strncpy(user, up->ut_user, sizeof (up->ut_user)); 488*7c478bd9Sstevel@tonic-gate user[sizeof (up->ut_user)] = '\0'; 489*7c478bd9Sstevel@tonic-gate strncpy(ttyn, up->ut_line, sizeof (up->ut_line)); 490*7c478bd9Sstevel@tonic-gate ttyn[sizeof (up->ut_line)] = '\0'; 491*7c478bd9Sstevel@tonic-gate strncpy(rhost, up->ut_host, sizeof (up->ut_host)); 492*7c478bd9Sstevel@tonic-gate rhost[sizeof (up->ut_host)] = '\0'; 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate if ((pam_start("sac", user, NULL, &pamh)) == 495*7c478bd9Sstevel@tonic-gate PAM_SUCCESS) { 496*7c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_TTY, ttyn); 497*7c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_RHOST, rhost); 498*7c478bd9Sstevel@tonic-gate (void) pam_close_session(pamh, 0); 499*7c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_SUCCESS); 500*7c478bd9Sstevel@tonic-gate } 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate up->ut_type = DEAD_PROCESS; 503*7c478bd9Sstevel@tonic-gate up->ut_exit.e_termination = WTERMSIG(sp->sc_exit); 504*7c478bd9Sstevel@tonic-gate up->ut_exit.e_exit = WEXITSTATUS(sp->sc_exit); 505*7c478bd9Sstevel@tonic-gate if (sp->sc_utid != NULL) 506*7c478bd9Sstevel@tonic-gate (void) memcpy(up->ut_id, sp->sc_utid, 507*7c478bd9Sstevel@tonic-gate sizeof (up->ut_id)); 508*7c478bd9Sstevel@tonic-gate (void) time(&up->ut_tv.tv_sec); 509*7c478bd9Sstevel@tonic-gate if (modutx(up) == NULL) { 510*7c478bd9Sstevel@tonic-gate /* 511*7c478bd9Sstevel@tonic-gate * Since modutx failed we'll 512*7c478bd9Sstevel@tonic-gate * write out the new entry 513*7c478bd9Sstevel@tonic-gate * ourselves. 514*7c478bd9Sstevel@tonic-gate */ 515*7c478bd9Sstevel@tonic-gate (void) pututxline(up); 516*7c478bd9Sstevel@tonic-gate updwtmpx("wtmpx", up); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate break; 519*7c478bd9Sstevel@tonic-gate } 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate endutxent(); 522*7c478bd9Sstevel@tonic-gate } 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate /* 525*7c478bd9Sstevel@tonic-gate * account - create a utmp record for a port monitor 526*7c478bd9Sstevel@tonic-gate * 527*7c478bd9Sstevel@tonic-gate * args: pid - process id of port monitor 528*7c478bd9Sstevel@tonic-gate */ 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate void 532*7c478bd9Sstevel@tonic-gate account(struct sactab *sp, pid_t pid) 533*7c478bd9Sstevel@tonic-gate { 534*7c478bd9Sstevel@tonic-gate struct utmpx utmpx; /* prototype utmpx entry */ 535*7c478bd9Sstevel@tonic-gate struct utmpx *up = &utmpx; /* and a pointer to it */ 536*7c478bd9Sstevel@tonic-gate 537*7c478bd9Sstevel@tonic-gate (void) memset(up, '\0', sizeof (utmpx)); 538*7c478bd9Sstevel@tonic-gate (void) strncpy(up->ut_user, sp->sc_tag, sizeof (up->ut_user)); 539*7c478bd9Sstevel@tonic-gate up->ut_pid = pid; 540*7c478bd9Sstevel@tonic-gate up->ut_type = LOGIN_PROCESS; 541*7c478bd9Sstevel@tonic-gate up->ut_id[0] = 'P'; 542*7c478bd9Sstevel@tonic-gate up->ut_id[1] = 'M'; 543*7c478bd9Sstevel@tonic-gate up->ut_id[2] = SC_WILDC; 544*7c478bd9Sstevel@tonic-gate up->ut_id[3] = SC_WILDC; 545*7c478bd9Sstevel@tonic-gate (void) time(&up->ut_xtime); 546*7c478bd9Sstevel@tonic-gate if (makeutx(up) == NULL) { 547*7c478bd9Sstevel@tonic-gate log("Could not create utmpx entry"); 548*7c478bd9Sstevel@tonic-gate (void) memset(sp->sc_utid, '\0', IDLEN); 549*7c478bd9Sstevel@tonic-gate } else { 550*7c478bd9Sstevel@tonic-gate (void) memcpy(sp->sc_utid, up->ut_id, IDLEN); 551*7c478bd9Sstevel@tonic-gate } 552*7c478bd9Sstevel@tonic-gate } 553*7c478bd9Sstevel@tonic-gate 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate /* 556*7c478bd9Sstevel@tonic-gate * startit - finish starting a particular port monitor, establish environment, 557*7c478bd9Sstevel@tonic-gate * etc. (Note: this is the child at this point) 558*7c478bd9Sstevel@tonic-gate * 559*7c478bd9Sstevel@tonic-gate * args: sp - pointer to sac's port monitor information for 560*7c478bd9Sstevel@tonic-gate * designated port monitor 561*7c478bd9Sstevel@tonic-gate */ 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate void 565*7c478bd9Sstevel@tonic-gate startit(struct sactab *sp) 566*7c478bd9Sstevel@tonic-gate { 567*7c478bd9Sstevel@tonic-gate static char istate[SIZE]; /* place to put ISTATE env var. */ 568*7c478bd9Sstevel@tonic-gate static char pmtag[SIZE]; /* place to put PMTAG env var. */ 569*7c478bd9Sstevel@tonic-gate char **argvp; /* arglist for PM */ 570*7c478bd9Sstevel@tonic-gate int i; /* loop control variable */ 571*7c478bd9Sstevel@tonic-gate long ndesc; /* # of file descriptors configured */ 572*7c478bd9Sstevel@tonic-gate int ret; /* return value from doconfig */ 573*7c478bd9Sstevel@tonic-gate sigset_t cset; /* for signal handling */ 574*7c478bd9Sstevel@tonic-gate sigset_t tset; /* for signal handling */ 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate /* 577*7c478bd9Sstevel@tonic-gate * establish the home directory 578*7c478bd9Sstevel@tonic-gate */ 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate if (chdir(sp->sc_tag) < 0) { 581*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, 582*7c478bd9Sstevel@tonic-gate "Cannot chdir to <%s/%s>, port monitor not started", 583*7c478bd9Sstevel@tonic-gate HOME, sp->sc_tag); 584*7c478bd9Sstevel@tonic-gate log(Scratch); 585*7c478bd9Sstevel@tonic-gate exit(1); 586*7c478bd9Sstevel@tonic-gate } 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate /* 589*7c478bd9Sstevel@tonic-gate * interpret the configuration script, pass an invalid fd, shouldn't be 590*7c478bd9Sstevel@tonic-gate * doing pushes and pops in this script 591*7c478bd9Sstevel@tonic-gate */ 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, NULL, &cset); 594*7c478bd9Sstevel@tonic-gate tset = cset; 595*7c478bd9Sstevel@tonic-gate (void) sigaddset(&tset, SIGCLD); 596*7c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &tset, NULL); 597*7c478bd9Sstevel@tonic-gate if ((ret = doconfig(-1, "_config", 0)) != 0) { 598*7c478bd9Sstevel@tonic-gate if (ret == -1) { 599*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, 600*7c478bd9Sstevel@tonic-gate "system error in _config script for <%s>", 601*7c478bd9Sstevel@tonic-gate sp->sc_tag); 602*7c478bd9Sstevel@tonic-gate log(Scratch); 603*7c478bd9Sstevel@tonic-gate exit(1); 604*7c478bd9Sstevel@tonic-gate } else { 605*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, 606*7c478bd9Sstevel@tonic-gate "Error in _config script for <%s>: line %d", 607*7c478bd9Sstevel@tonic-gate sp->sc_tag, ret); 608*7c478bd9Sstevel@tonic-gate log(Scratch); 609*7c478bd9Sstevel@tonic-gate exit(1); 610*7c478bd9Sstevel@tonic-gate } 611*7c478bd9Sstevel@tonic-gate } 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate /* 614*7c478bd9Sstevel@tonic-gate * add the promised environment variables 615*7c478bd9Sstevel@tonic-gate */ 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate if (sp->sc_lstate == NOTRUNNING) 618*7c478bd9Sstevel@tonic-gate (void) sprintf(istate, "ISTATE=%s", 619*7c478bd9Sstevel@tonic-gate (sp->sc_flags & D_FLAG) ? "disabled" : "enabled"); 620*7c478bd9Sstevel@tonic-gate else 621*7c478bd9Sstevel@tonic-gate (void) sprintf(istate, "ISTATE=%s", 622*7c478bd9Sstevel@tonic-gate (sp->sc_lstate == DISABLED) ? "disabled" : "enabled"); 623*7c478bd9Sstevel@tonic-gate if (putenv(istate)) { 624*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, 625*7c478bd9Sstevel@tonic-gate "can't expand port monitor <%s> environment", 626*7c478bd9Sstevel@tonic-gate sp->sc_tag); 627*7c478bd9Sstevel@tonic-gate log(Scratch); 628*7c478bd9Sstevel@tonic-gate exit(1); 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate (void) sprintf(pmtag, "PMTAG=%s", sp->sc_tag); 631*7c478bd9Sstevel@tonic-gate if (putenv(pmtag)) { 632*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, 633*7c478bd9Sstevel@tonic-gate "can't expand port monitor <%s> environment", 634*7c478bd9Sstevel@tonic-gate sp->sc_tag); 635*7c478bd9Sstevel@tonic-gate log(Scratch); 636*7c478bd9Sstevel@tonic-gate exit(1); 637*7c478bd9Sstevel@tonic-gate } 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate /* 640*7c478bd9Sstevel@tonic-gate * build an argv 641*7c478bd9Sstevel@tonic-gate */ 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate argvp = mkargv(sp); 644*7c478bd9Sstevel@tonic-gate 645*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, "starting port monitor <%s>", sp->sc_tag); 646*7c478bd9Sstevel@tonic-gate log(Scratch); 647*7c478bd9Sstevel@tonic-gate ndesc = ulimit(4, 0L); 648*7c478bd9Sstevel@tonic-gate for (i = 0; i < ndesc; i++) 649*7c478bd9Sstevel@tonic-gate (void) fcntl(i, F_SETFD, 1); 650*7c478bd9Sstevel@tonic-gate /* restore orignal handlers and mask */ 651*7c478bd9Sstevel@tonic-gate (void) sigaction(SIGPOLL, &Sigpoll, NULL); 652*7c478bd9Sstevel@tonic-gate (void) sigaction(SIGCLD, &Sigcld, NULL); 653*7c478bd9Sstevel@tonic-gate (void) sigaction(SIGALRM, &Sigalrm, NULL); 654*7c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &Origmask, NULL); 655*7c478bd9Sstevel@tonic-gate (void) execve(argvp[0], argvp, environ); 656*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, "exec of port monitor <%s> failed", sp->sc_tag); 657*7c478bd9Sstevel@tonic-gate log(Scratch); 658*7c478bd9Sstevel@tonic-gate exit(1); 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate /* 663*7c478bd9Sstevel@tonic-gate * mkargv - Given a pointer to a struct sactab, construct argv 664*7c478bd9Sstevel@tonic-gate * for an exec system call. 665*7c478bd9Sstevel@tonic-gate * 666*7c478bd9Sstevel@tonic-gate * args: sp - pointer to sac's port monitor information for 667*7c478bd9Sstevel@tonic-gate * designated port montior 668*7c478bd9Sstevel@tonic-gate */ 669*7c478bd9Sstevel@tonic-gate 670*7c478bd9Sstevel@tonic-gate 671*7c478bd9Sstevel@tonic-gate #define NARGS 50 /* max # of args */ 672*7c478bd9Sstevel@tonic-gate 673*7c478bd9Sstevel@tonic-gate static char *newargv[NARGS]; /* place for argv list */ 674*7c478bd9Sstevel@tonic-gate static char *delim = " \t'\""; /* delimiter list */ 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate char ** 677*7c478bd9Sstevel@tonic-gate mkargv(struct sactab *sp) 678*7c478bd9Sstevel@tonic-gate { 679*7c478bd9Sstevel@tonic-gate char **argvp = newargv; /* scratch pointer */ 680*7c478bd9Sstevel@tonic-gate char *p = sp->sc_cmd; /* working pointer */ 681*7c478bd9Sstevel@tonic-gate char delch; /* delimiter seen */ 682*7c478bd9Sstevel@tonic-gate char *savep; /* scratch pointer */ 683*7c478bd9Sstevel@tonic-gate char *tp; /* scratch pointer */ 684*7c478bd9Sstevel@tonic-gate 685*7c478bd9Sstevel@tonic-gate *argvp = 0; 686*7c478bd9Sstevel@tonic-gate savep = p; 687*7c478bd9Sstevel@tonic-gate while (p && *p) { 688*7c478bd9Sstevel@tonic-gate if (p = strpbrk(p, delim)) { 689*7c478bd9Sstevel@tonic-gate switch (*p) { 690*7c478bd9Sstevel@tonic-gate case ' ': 691*7c478bd9Sstevel@tonic-gate case '\t': 692*7c478bd9Sstevel@tonic-gate /* "normal" cases */ 693*7c478bd9Sstevel@tonic-gate *p++ = '\0'; 694*7c478bd9Sstevel@tonic-gate *argvp++ = savep; 695*7c478bd9Sstevel@tonic-gate /* zap trailing white space */ 696*7c478bd9Sstevel@tonic-gate while (isspace(*p)) 697*7c478bd9Sstevel@tonic-gate p++; 698*7c478bd9Sstevel@tonic-gate savep = p; 699*7c478bd9Sstevel@tonic-gate break; 700*7c478bd9Sstevel@tonic-gate case '"': 701*7c478bd9Sstevel@tonic-gate case '\'': 702*7c478bd9Sstevel@tonic-gate /* found a string */ 703*7c478bd9Sstevel@tonic-gate delch = *p; /* remember the delimiter */ 704*7c478bd9Sstevel@tonic-gate savep = ++p; 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate /* 707*7c478bd9Sstevel@tonic-gate * We work the string in place, embedded instances of the string delimiter, 708*7c478bd9Sstevel@tonic-gate * i.e. \" must have the '\' removed. Since we'd have to do a compare to 709*7c478bd9Sstevel@tonic-gate * decide if a copy were needed, it's less work to just do the copy, even 710*7c478bd9Sstevel@tonic-gate * though it is most likely unnecessary. 711*7c478bd9Sstevel@tonic-gate */ 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate tp = p; 714*7c478bd9Sstevel@tonic-gate for (;;) { 715*7c478bd9Sstevel@tonic-gate if (*p == '\0') { 716*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, 717*7c478bd9Sstevel@tonic-gate "invalid command line, non-terminated string for port monitor %s", 718*7c478bd9Sstevel@tonic-gate sp->sc_tag); 719*7c478bd9Sstevel@tonic-gate log(Scratch); 720*7c478bd9Sstevel@tonic-gate exit(1); 721*7c478bd9Sstevel@tonic-gate } 722*7c478bd9Sstevel@tonic-gate if (*p == delch) { 723*7c478bd9Sstevel@tonic-gate if (*(tp - 1) == '\\') { 724*7c478bd9Sstevel@tonic-gate /* \delim */ 725*7c478bd9Sstevel@tonic-gate *(tp - 1) = *p; 726*7c478bd9Sstevel@tonic-gate p++; 727*7c478bd9Sstevel@tonic-gate } else { /* end of string */ 728*7c478bd9Sstevel@tonic-gate *tp = 0; 729*7c478bd9Sstevel@tonic-gate *argvp++ = savep; 730*7c478bd9Sstevel@tonic-gate p++; 731*7c478bd9Sstevel@tonic-gate /* zap trailing white space */ 732*7c478bd9Sstevel@tonic-gate while (isspace(*p)) 733*7c478bd9Sstevel@tonic-gate p++; 734*7c478bd9Sstevel@tonic-gate savep = p; 735*7c478bd9Sstevel@tonic-gate break; 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate } else { 738*7c478bd9Sstevel@tonic-gate *tp++ = *p++; 739*7c478bd9Sstevel@tonic-gate } 740*7c478bd9Sstevel@tonic-gate } 741*7c478bd9Sstevel@tonic-gate break; 742*7c478bd9Sstevel@tonic-gate default: 743*7c478bd9Sstevel@tonic-gate log("Internal error in parse routine"); 744*7c478bd9Sstevel@tonic-gate exit(1); 745*7c478bd9Sstevel@tonic-gate } 746*7c478bd9Sstevel@tonic-gate } 747*7c478bd9Sstevel@tonic-gate else 748*7c478bd9Sstevel@tonic-gate *argvp++ = savep; 749*7c478bd9Sstevel@tonic-gate } 750*7c478bd9Sstevel@tonic-gate *argvp = 0; 751*7c478bd9Sstevel@tonic-gate return (newargv); 752*7c478bd9Sstevel@tonic-gate } 753*7c478bd9Sstevel@tonic-gate 754*7c478bd9Sstevel@tonic-gate 755*7c478bd9Sstevel@tonic-gate /* 756*7c478bd9Sstevel@tonic-gate * pollpms - send out sanity polls, if sc_sstate and sc_pstate are 757*7c478bd9Sstevel@tonic-gate * the same (everyone agrees on the state) or if SAC thinks PM 758*7c478bd9Sstevel@tonic-gate * should be stopping, send out a status message; 759*7c478bd9Sstevel@tonic-gate * otherwise, send out a message indicating the state the SAC 760*7c478bd9Sstevel@tonic-gate * thinks the PM should be entering 761*7c478bd9Sstevel@tonic-gate */ 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate void 764*7c478bd9Sstevel@tonic-gate pollpms() 765*7c478bd9Sstevel@tonic-gate { 766*7c478bd9Sstevel@tonic-gate struct sactab *sp; /* working pointer */ 767*7c478bd9Sstevel@tonic-gate struct sacmsg sacmsg; /* message to send to PM */ 768*7c478bd9Sstevel@tonic-gate 769*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 770*7c478bd9Sstevel@tonic-gate debug("alarm went off"); 771*7c478bd9Sstevel@tonic-gate #endif 772*7c478bd9Sstevel@tonic-gate for (sp = Sactab; sp; sp = sp->sc_next) { 773*7c478bd9Sstevel@tonic-gate if (sp->sc_pstate == NOTRUNNING || sp->sc_pstate == FAILED) { 774*7c478bd9Sstevel@tonic-gate /* don't bother if no one is home */ 775*7c478bd9Sstevel@tonic-gate continue; 776*7c478bd9Sstevel@tonic-gate } 777*7c478bd9Sstevel@tonic-gate if (sp->sc_ok == 0) { 778*7c478bd9Sstevel@tonic-gate /* PM has stopped responding */ 779*7c478bd9Sstevel@tonic-gate pollfail(sp, RESP); 780*7c478bd9Sstevel@tonic-gate continue; 781*7c478bd9Sstevel@tonic-gate } 782*7c478bd9Sstevel@tonic-gate 783*7c478bd9Sstevel@tonic-gate /* 784*7c478bd9Sstevel@tonic-gate * note - if we're in recovery, a SC_STATUS message is sent 785*7c478bd9Sstevel@tonic-gate * (sc_sstate = UNKNOWN and sc_pstate = UNKNOWN) 786*7c478bd9Sstevel@tonic-gate */ 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate if (sp->sc_sstate == sp->sc_pstate) { 789*7c478bd9Sstevel@tonic-gate sacmsg.sc_type = SC_STATUS; 790*7c478bd9Sstevel@tonic-gate sacmsg.sc_size = 0; 791*7c478bd9Sstevel@tonic-gate } else { 792*7c478bd9Sstevel@tonic-gate switch (sp->sc_sstate) { 793*7c478bd9Sstevel@tonic-gate case ENABLED: 794*7c478bd9Sstevel@tonic-gate sacmsg.sc_type = SC_ENABLE; 795*7c478bd9Sstevel@tonic-gate sacmsg.sc_size = 0; 796*7c478bd9Sstevel@tonic-gate break; 797*7c478bd9Sstevel@tonic-gate case DISABLED: 798*7c478bd9Sstevel@tonic-gate sacmsg.sc_type = SC_DISABLE; 799*7c478bd9Sstevel@tonic-gate sacmsg.sc_size = 0; 800*7c478bd9Sstevel@tonic-gate break; 801*7c478bd9Sstevel@tonic-gate case STARTING: 802*7c478bd9Sstevel@tonic-gate case STOPPING: 803*7c478bd9Sstevel@tonic-gate case NOTRUNNING: 804*7c478bd9Sstevel@tonic-gate case FAILED: 805*7c478bd9Sstevel@tonic-gate case UNKNOWN: 806*7c478bd9Sstevel@tonic-gate /* 807*7c478bd9Sstevel@tonic-gate * if NOTRUNNING or FAILED, PM will probably 808*7c478bd9Sstevel@tonic-gate * not respond to poll, that's how we detect 809*7c478bd9Sstevel@tonic-gate * that it's gone 810*7c478bd9Sstevel@tonic-gate */ 811*7c478bd9Sstevel@tonic-gate sacmsg.sc_type = SC_STATUS; 812*7c478bd9Sstevel@tonic-gate sacmsg.sc_size = 0; 813*7c478bd9Sstevel@tonic-gate break; 814*7c478bd9Sstevel@tonic-gate default: 815*7c478bd9Sstevel@tonic-gate error(E_BADSTATE, EXIT); 816*7c478bd9Sstevel@tonic-gate } 817*7c478bd9Sstevel@tonic-gate } 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate /* send the message */ 820*7c478bd9Sstevel@tonic-gate sendpmmsg(sp, &sacmsg); 821*7c478bd9Sstevel@tonic-gate sp->sc_ok = 0; 822*7c478bd9Sstevel@tonic-gate } 823*7c478bd9Sstevel@tonic-gate (void) alarm(Stime); 824*7c478bd9Sstevel@tonic-gate } 825*7c478bd9Sstevel@tonic-gate 826*7c478bd9Sstevel@tonic-gate 827*7c478bd9Sstevel@tonic-gate /* 828*7c478bd9Sstevel@tonic-gate * reap - clean up dead children, equivalent to a "fast" poll failure 829*7c478bd9Sstevel@tonic-gate * 830*7c478bd9Sstevel@tonic-gate * args: signo - signal # 831*7c478bd9Sstevel@tonic-gate */ 832*7c478bd9Sstevel@tonic-gate 833*7c478bd9Sstevel@tonic-gate void 834*7c478bd9Sstevel@tonic-gate reap(int signo) 835*7c478bd9Sstevel@tonic-gate { 836*7c478bd9Sstevel@tonic-gate struct sactab *sp; /* working pointer */ 837*7c478bd9Sstevel@tonic-gate pid_t pid; /* returned pid from wait */ 838*7c478bd9Sstevel@tonic-gate int status; /* returned status from wait */ 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate pid = wait(&status); 841*7c478bd9Sstevel@tonic-gate for (sp = Sactab; sp; sp = sp->sc_next) { 842*7c478bd9Sstevel@tonic-gate if (sp->sc_pid == pid) 843*7c478bd9Sstevel@tonic-gate break; 844*7c478bd9Sstevel@tonic-gate } 845*7c478bd9Sstevel@tonic-gate if (sp == NULL) { 846*7c478bd9Sstevel@tonic-gate /* not from a port monitor we know about */ 847*7c478bd9Sstevel@tonic-gate return; 848*7c478bd9Sstevel@tonic-gate } 849*7c478bd9Sstevel@tonic-gate sp->sc_exit = status; 850*7c478bd9Sstevel@tonic-gate /* only call pollfail for "stuck" and stopping processes */ 851*7c478bd9Sstevel@tonic-gate if (sp->sc_pstate != NOTRUNNING && sp->sc_pstate != FAILED) 852*7c478bd9Sstevel@tonic-gate pollfail(sp, DEATH); 853*7c478bd9Sstevel@tonic-gate } 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate /* 857*7c478bd9Sstevel@tonic-gate * pollfail - handle the case where a PM stops responding to a sanity poll 858*7c478bd9Sstevel@tonic-gate * 859*7c478bd9Sstevel@tonic-gate * args: sp - pointer to sac's port monitor information for 860*7c478bd9Sstevel@tonic-gate * designated port monitor 861*7c478bd9Sstevel@tonic-gate * reason - RESP or DEATH (indicates why pollfail called) 862*7c478bd9Sstevel@tonic-gate */ 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate 865*7c478bd9Sstevel@tonic-gate void 866*7c478bd9Sstevel@tonic-gate pollfail(struct sactab *sp, int reason) 867*7c478bd9Sstevel@tonic-gate { 868*7c478bd9Sstevel@tonic-gate char buf[SIZE]; /* scratch buffer */ 869*7c478bd9Sstevel@tonic-gate sigset_t cset; /* for signal handling */ 870*7c478bd9Sstevel@tonic-gate sigset_t tset; /* for signal handling */ 871*7c478bd9Sstevel@tonic-gate 872*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 873*7c478bd9Sstevel@tonic-gate debug("in pollfail"); 874*7c478bd9Sstevel@tonic-gate #endif 875*7c478bd9Sstevel@tonic-gate 876*7c478bd9Sstevel@tonic-gate /* first, remove the utmpx entry and clean up any links */ 877*7c478bd9Sstevel@tonic-gate 878*7c478bd9Sstevel@tonic-gate cleanutx(sp); 879*7c478bd9Sstevel@tonic-gate 880*7c478bd9Sstevel@tonic-gate if (sp->sc_pstate == STOPPING) { 881*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "<%s> has stopped", sp->sc_tag); 882*7c478bd9Sstevel@tonic-gate log(buf); 883*7c478bd9Sstevel@tonic-gate sp->sc_pstate = NOTRUNNING; 884*7c478bd9Sstevel@tonic-gate sp->sc_lstate = NOTRUNNING; 885*7c478bd9Sstevel@tonic-gate (void) close(sp->sc_fd); 886*7c478bd9Sstevel@tonic-gate } else { 887*7c478bd9Sstevel@tonic-gate 888*7c478bd9Sstevel@tonic-gate /* 889*7c478bd9Sstevel@tonic-gate * PM in trouble - if it's still there, try to put it out of its misery 890*7c478bd9Sstevel@tonic-gate * We play with SIGCLD here to that after SIGKILL is sent, the catcher 891*7c478bd9Sstevel@tonic-gate * routine reap() is not called until we're ready (note: when a catcher 892*7c478bd9Sstevel@tonic-gate * is established for SIGCLD and any zombies are present, the signal is 893*7c478bd9Sstevel@tonic-gate * immediately received) 894*7c478bd9Sstevel@tonic-gate */ 895*7c478bd9Sstevel@tonic-gate 896*7c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, NULL, &cset); 897*7c478bd9Sstevel@tonic-gate tset = cset; 898*7c478bd9Sstevel@tonic-gate (void) sigaddset(&tset, SIGCLD); 899*7c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &tset, NULL); 900*7c478bd9Sstevel@tonic-gate (void) sendsig(sp, SIGKILL); 901*7c478bd9Sstevel@tonic-gate if (sp->sc_rscnt < sp->sc_rsmax) { 902*7c478bd9Sstevel@tonic-gate /* try to restart it */ 903*7c478bd9Sstevel@tonic-gate if (reason == RESP) 904*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, 905*7c478bd9Sstevel@tonic-gate "<%s> stopped responding to sanity polls - trying to restart", 906*7c478bd9Sstevel@tonic-gate sp->sc_tag); 907*7c478bd9Sstevel@tonic-gate else 908*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, 909*7c478bd9Sstevel@tonic-gate "<%s> has died - trying to restart", 910*7c478bd9Sstevel@tonic-gate sp->sc_tag); 911*7c478bd9Sstevel@tonic-gate log(buf); 912*7c478bd9Sstevel@tonic-gate sp->sc_rscnt++; 913*7c478bd9Sstevel@tonic-gate (void) close(sp->sc_fd); 914*7c478bd9Sstevel@tonic-gate (void) startpm(sp); 915*7c478bd9Sstevel@tonic-gate } else { 916*7c478bd9Sstevel@tonic-gate sp->sc_sstate = sp->sc_pstate = FAILED; 917*7c478bd9Sstevel@tonic-gate (void) close(sp->sc_fd); 918*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "<%s> has FAILED", sp->sc_tag); 919*7c478bd9Sstevel@tonic-gate log(buf); 920*7c478bd9Sstevel@tonic-gate } 921*7c478bd9Sstevel@tonic-gate } 922*7c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &cset, NULL); 923*7c478bd9Sstevel@tonic-gate } 924*7c478bd9Sstevel@tonic-gate 925*7c478bd9Sstevel@tonic-gate 926*7c478bd9Sstevel@tonic-gate /* 927*7c478bd9Sstevel@tonic-gate * readpipe - read messages from _sacpipe 928*7c478bd9Sstevel@tonic-gate */ 929*7c478bd9Sstevel@tonic-gate 930*7c478bd9Sstevel@tonic-gate 931*7c478bd9Sstevel@tonic-gate void 932*7c478bd9Sstevel@tonic-gate readpipe() 933*7c478bd9Sstevel@tonic-gate { 934*7c478bd9Sstevel@tonic-gate struct pmmsg pmmsg; /* incoming message */ 935*7c478bd9Sstevel@tonic-gate struct pmmsg *pp = &pmmsg; /* and a pointer to it */ 936*7c478bd9Sstevel@tonic-gate struct sactab *sp; /* working pointer */ 937*7c478bd9Sstevel@tonic-gate int ret; /* return value from read */ 938*7c478bd9Sstevel@tonic-gate 939*7c478bd9Sstevel@tonic-gate /* 940*7c478bd9Sstevel@tonic-gate * This routine's main purpose is to maintain the state associated with 941*7c478bd9Sstevel@tonic-gate * each of the known port monitors. Because it may be confusing, following 942*7c478bd9Sstevel@tonic-gate * is a brief discussion of what is happening. Three different views of 943*7c478bd9Sstevel@tonic-gate * a port monitor's state exist: sc_sstate, sc_pstate, and sc_lstate. 944*7c478bd9Sstevel@tonic-gate * sc_sstate is the state in which the sac has been instructed to place 945*7c478bd9Sstevel@tonic-gate * a port monitor. sc_lstate is essentially a shadow of this field, however, 946*7c478bd9Sstevel@tonic-gate * it will only take on the values ENABLED, DISABLED, and NOTRUNNING. 947*7c478bd9Sstevel@tonic-gate * sc_lstate is used if a port monitor dies to restart it in the state in 948*7c478bd9Sstevel@tonic-gate * which it was last running. sc_pstate is the last state that the port 949*7c478bd9Sstevel@tonic-gate * monitor reported itself in. Note that if the administrator specifies 950*7c478bd9Sstevel@tonic-gate * a state change, there is a window where sc_sstate and sc_pstate will 951*7c478bd9Sstevel@tonic-gate * be different (until the port monitor enacts and acknowledges the change). 952*7c478bd9Sstevel@tonic-gate * 953*7c478bd9Sstevel@tonic-gate * These states interact with the polling loop to determine which message 954*7c478bd9Sstevel@tonic-gate * should be sent to a port monitor. If the states agree, an SC_STATUS 955*7c478bd9Sstevel@tonic-gate * is sent. If they disagree, the appropriate message to put the port 956*7c478bd9Sstevel@tonic-gate * monitor in the correct state is sent (SC_ENABLE or SC_DISABLE). sc_pstate 957*7c478bd9Sstevel@tonic-gate * is the state that is reported back to an AC_STATUS request. Finally, 958*7c478bd9Sstevel@tonic-gate * when in recovery (sc_sstate and sc_pstate both = UNKNOWN), the sac will 959*7c478bd9Sstevel@tonic-gate * take the port monitor's reported state as the true state. This is the 960*7c478bd9Sstevel@tonic-gate * only instance in which a port monitor can cause sc_sstate to change. 961*7c478bd9Sstevel@tonic-gate */ 962*7c478bd9Sstevel@tonic-gate 963*7c478bd9Sstevel@tonic-gate for (;;) { 964*7c478bd9Sstevel@tonic-gate if (read(Sfd, pp, sizeof (pmmsg)) < 0) { 965*7c478bd9Sstevel@tonic-gate if (errno != EINTR) 966*7c478bd9Sstevel@tonic-gate error(E_BADREAD, EXIT); 967*7c478bd9Sstevel@tonic-gate continue; 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate while (pp->pm_size) { 971*7c478bd9Sstevel@tonic-gate 972*7c478bd9Sstevel@tonic-gate /* 973*7c478bd9Sstevel@tonic-gate * there's data after the header, unfortunately, we don't understand 974*7c478bd9Sstevel@tonic-gate * any of it because only class 1 (no data) messages are defined. Just 975*7c478bd9Sstevel@tonic-gate * flush it 976*7c478bd9Sstevel@tonic-gate */ 977*7c478bd9Sstevel@tonic-gate 978*7c478bd9Sstevel@tonic-gate ret = read(Sfd, Scratch, 979*7c478bd9Sstevel@tonic-gate (pp->pm_size > SIZE) ? (unsigned) SIZE : 980*7c478bd9Sstevel@tonic-gate (unsigned) pp->pm_size); 981*7c478bd9Sstevel@tonic-gate if (ret < 0) { 982*7c478bd9Sstevel@tonic-gate if (errno != EINTR) 983*7c478bd9Sstevel@tonic-gate error(E_BADREAD, EXIT); 984*7c478bd9Sstevel@tonic-gate continue; 985*7c478bd9Sstevel@tonic-gate } 986*7c478bd9Sstevel@tonic-gate else 987*7c478bd9Sstevel@tonic-gate pp->pm_size -= ret; 988*7c478bd9Sstevel@tonic-gate } 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gate sp = findpm(pp->pm_tag); 991*7c478bd9Sstevel@tonic-gate if (sp == NULL) { 992*7c478bd9Sstevel@tonic-gate log("message from unknown process"); 993*7c478bd9Sstevel@tonic-gate continue; 994*7c478bd9Sstevel@tonic-gate } 995*7c478bd9Sstevel@tonic-gate switch (pp->pm_type) { 996*7c478bd9Sstevel@tonic-gate case PM_UNKNOWN: 997*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, 998*7c478bd9Sstevel@tonic-gate "port monitor <%s> didn't recognize message", 999*7c478bd9Sstevel@tonic-gate sp->sc_tag); 1000*7c478bd9Sstevel@tonic-gate log(Scratch); 1001*7c478bd9Sstevel@tonic-gate /* fall through */ 1002*7c478bd9Sstevel@tonic-gate case PM_STATUS: 1003*7c478bd9Sstevel@tonic-gate /* 1004*7c478bd9Sstevel@tonic-gate * paranoia check, if port monitor reports garbage 1005*7c478bd9Sstevel@tonic-gate * state, pretend it said UNKNOWN 1006*7c478bd9Sstevel@tonic-gate */ 1007*7c478bd9Sstevel@tonic-gate if (!validstate(pp->pm_state)) { 1008*7c478bd9Sstevel@tonic-gate pp->pm_state = UNKNOWN; 1009*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, 1010*7c478bd9Sstevel@tonic-gate "port monitor <%s> reporting invalid state", 1011*7c478bd9Sstevel@tonic-gate sp->sc_tag); 1012*7c478bd9Sstevel@tonic-gate log(Scratch); 1013*7c478bd9Sstevel@tonic-gate } 1014*7c478bd9Sstevel@tonic-gate if (sp->sc_sstate == sp->sc_pstate) { 1015*7c478bd9Sstevel@tonic-gate /* everyone agrees on the current state */ 1016*7c478bd9Sstevel@tonic-gate if (sp->sc_sstate == UNKNOWN) { 1017*7c478bd9Sstevel@tonic-gate /* special case for recovery */ 1018*7c478bd9Sstevel@tonic-gate sp->sc_sstate = pp->pm_state; 1019*7c478bd9Sstevel@tonic-gate sp->sc_pstate = pp->pm_state; 1020*7c478bd9Sstevel@tonic-gate if (pp->pm_state == ENABLED || 1021*7c478bd9Sstevel@tonic-gate pp->pm_state == DISABLED) 1022*7c478bd9Sstevel@tonic-gate /* sc_lstate NOTRUNNING by default */ 1023*7c478bd9Sstevel@tonic-gate sp->sc_lstate = pp->pm_state; 1024*7c478bd9Sstevel@tonic-gate } 1025*7c478bd9Sstevel@tonic-gate if (pp->pm_state != sp->sc_pstate) { 1026*7c478bd9Sstevel@tonic-gate /* 1027*7c478bd9Sstevel@tonic-gate * something isn't right here, PM 1028*7c478bd9Sstevel@tonic-gate * changed state without orders, try 1029*7c478bd9Sstevel@tonic-gate * to restore to correct state 1030*7c478bd9Sstevel@tonic-gate */ 1031*7c478bd9Sstevel@tonic-gate sp->sc_pstate = pp->pm_state; 1032*7c478bd9Sstevel@tonic-gate } 1033*7c478bd9Sstevel@tonic-gate } else if (sp->sc_sstate == pp->pm_state) { 1034*7c478bd9Sstevel@tonic-gate /* PM changed to state requested */ 1035*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, 1036*7c478bd9Sstevel@tonic-gate "port monitor <%s> changed state from %s to %s", 1037*7c478bd9Sstevel@tonic-gate sp->sc_tag, pstate(sp->sc_pstate), 1038*7c478bd9Sstevel@tonic-gate pstate(pp->pm_state)); 1039*7c478bd9Sstevel@tonic-gate log(Scratch); 1040*7c478bd9Sstevel@tonic-gate sp->sc_pstate = pp->pm_state; 1041*7c478bd9Sstevel@tonic-gate } else if (sp->sc_pstate != pp->pm_state) { 1042*7c478bd9Sstevel@tonic-gate /* 1043*7c478bd9Sstevel@tonic-gate * something isn't right here, PM isn't 1044*7c478bd9Sstevel@tonic-gate * in the state it was, nor is it in the 1045*7c478bd9Sstevel@tonic-gate * state we just tried to put it in, try 1046*7c478bd9Sstevel@tonic-gate * to restore to correct state if we should 1047*7c478bd9Sstevel@tonic-gate */ 1048*7c478bd9Sstevel@tonic-gate if (sp->sc_pstate != STOPPING) 1049*7c478bd9Sstevel@tonic-gate sp->sc_pstate = pp->pm_state; 1050*7c478bd9Sstevel@tonic-gate } 1051*7c478bd9Sstevel@tonic-gate break; 1052*7c478bd9Sstevel@tonic-gate default: 1053*7c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, 1054*7c478bd9Sstevel@tonic-gate "port monitor <%s> sent an invalid message - ignoring it", 1055*7c478bd9Sstevel@tonic-gate sp->sc_tag); 1056*7c478bd9Sstevel@tonic-gate log(Scratch); 1057*7c478bd9Sstevel@tonic-gate break; 1058*7c478bd9Sstevel@tonic-gate } 1059*7c478bd9Sstevel@tonic-gate /* no matter what, PM did answer the poll */ 1060*7c478bd9Sstevel@tonic-gate sp->sc_ok = 1; 1061*7c478bd9Sstevel@tonic-gate /* Note the messages it understands */ 1062*7c478bd9Sstevel@tonic-gate sp->sc_maxclass = pp->pm_maxclass; 1063*7c478bd9Sstevel@tonic-gate } 1064*7c478bd9Sstevel@tonic-gate } 1065*7c478bd9Sstevel@tonic-gate 1066*7c478bd9Sstevel@tonic-gate 1067*7c478bd9Sstevel@tonic-gate /* 1068*7c478bd9Sstevel@tonic-gate * validstate - determine if arg s a valid return state from a port monitor 1069*7c478bd9Sstevel@tonic-gate * return 1 if ok, 0 otherwise 1070*7c478bd9Sstevel@tonic-gate * 1071*7c478bd9Sstevel@tonic-gate * args: state - state to be verified 1072*7c478bd9Sstevel@tonic-gate */ 1073*7c478bd9Sstevel@tonic-gate int 1074*7c478bd9Sstevel@tonic-gate validstate(unchar state) 1075*7c478bd9Sstevel@tonic-gate { 1076*7c478bd9Sstevel@tonic-gate switch (state) { 1077*7c478bd9Sstevel@tonic-gate case PM_ENABLED: 1078*7c478bd9Sstevel@tonic-gate case PM_DISABLED: 1079*7c478bd9Sstevel@tonic-gate case PM_STARTING: 1080*7c478bd9Sstevel@tonic-gate case PM_STOPPING: 1081*7c478bd9Sstevel@tonic-gate return (1); 1082*7c478bd9Sstevel@tonic-gate default: 1083*7c478bd9Sstevel@tonic-gate return (0); 1084*7c478bd9Sstevel@tonic-gate } 1085*7c478bd9Sstevel@tonic-gate } 1086*7c478bd9Sstevel@tonic-gate 1087*7c478bd9Sstevel@tonic-gate 1088*7c478bd9Sstevel@tonic-gate /* 1089*7c478bd9Sstevel@tonic-gate * mk_cmd_pipe - create the command pipe used by sacadm 1090*7c478bd9Sstevel@tonic-gate */ 1091*7c478bd9Sstevel@tonic-gate 1092*7c478bd9Sstevel@tonic-gate int 1093*7c478bd9Sstevel@tonic-gate mk_cmd_pipe() 1094*7c478bd9Sstevel@tonic-gate { 1095*7c478bd9Sstevel@tonic-gate int fds[2]; /* pipe endpoints */ 1096*7c478bd9Sstevel@tonic-gate int fd; /* scratch file descriptor */ 1097*7c478bd9Sstevel@tonic-gate 1098*7c478bd9Sstevel@tonic-gate /* make sure there is a file here to mount on */ 1099*7c478bd9Sstevel@tonic-gate (void) unlink(CMDPIPE); 1100*7c478bd9Sstevel@tonic-gate fd = open(CMDPIPE, O_RDWR | O_CREAT, 0600); 1101*7c478bd9Sstevel@tonic-gate if (fd < 0) 1102*7c478bd9Sstevel@tonic-gate error(E_CMDPIPE, EXIT); 1103*7c478bd9Sstevel@tonic-gate close(fd); 1104*7c478bd9Sstevel@tonic-gate if (pipe(fds) < 0) 1105*7c478bd9Sstevel@tonic-gate error(E_PIPE, EXIT); 1106*7c478bd9Sstevel@tonic-gate if (fattach(fds[0], CMDPIPE) < 0) 1107*7c478bd9Sstevel@tonic-gate error(E_FATTACH, EXIT); 1108*7c478bd9Sstevel@tonic-gate return (fds[1]); 1109*7c478bd9Sstevel@tonic-gate } 1110*7c478bd9Sstevel@tonic-gate 1111*7c478bd9Sstevel@tonic-gate 1112*7c478bd9Sstevel@tonic-gate /* 1113*7c478bd9Sstevel@tonic-gate * startpoll - enable polling on command pipe by setting up to catch SIGPOLL 1114*7c478bd9Sstevel@tonic-gate */ 1115*7c478bd9Sstevel@tonic-gate 1116*7c478bd9Sstevel@tonic-gate 1117*7c478bd9Sstevel@tonic-gate void 1118*7c478bd9Sstevel@tonic-gate startpoll() 1119*7c478bd9Sstevel@tonic-gate { 1120*7c478bd9Sstevel@tonic-gate struct sigaction sigact; /* for signal handling */ 1121*7c478bd9Sstevel@tonic-gate 1122*7c478bd9Sstevel@tonic-gate if (ioctl(Cfd, I_SETSIG, S_INPUT) < 0) 1123*7c478bd9Sstevel@tonic-gate error(E_SETSIG, EXIT); 1124*7c478bd9Sstevel@tonic-gate sigact.sa_flags = 0; 1125*7c478bd9Sstevel@tonic-gate sigact.sa_handler = sigpoll; 1126*7c478bd9Sstevel@tonic-gate (void) sigemptyset(&sigact.sa_mask); 1127*7c478bd9Sstevel@tonic-gate (void) sigaddset(&sigact.sa_mask, SIGPOLL); 1128*7c478bd9Sstevel@tonic-gate (void) sigaction(SIGPOLL, &sigact, &Sigpoll); 1129*7c478bd9Sstevel@tonic-gate } 1130