17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
237c478bd9Sstevel@tonic-gate /* All Rights Reserved */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate /*
26*34e48580Sdp * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
27*34e48580Sdp * Use is subject to license terms.
287c478bd9Sstevel@tonic-gate */
297c478bd9Sstevel@tonic-gate
30*34e48580Sdp #pragma ident "%Z%%M% %I% %E% SMI"
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate #include <stdio.h>
33*34e48580Sdp #include <stdlib.h>
347c478bd9Sstevel@tonic-gate #include <fcntl.h>
357c478bd9Sstevel@tonic-gate #include <ctype.h>
367c478bd9Sstevel@tonic-gate #include <signal.h>
37*34e48580Sdp #include <strings.h>
387c478bd9Sstevel@tonic-gate #include <errno.h>
397c478bd9Sstevel@tonic-gate #include <sys/types.h>
407c478bd9Sstevel@tonic-gate #include <sys/stat.h>
417c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
427c478bd9Sstevel@tonic-gate #include <sys/wait.h>
437c478bd9Sstevel@tonic-gate #include <unistd.h>
447c478bd9Sstevel@tonic-gate #include <utmpx.h>
457c478bd9Sstevel@tonic-gate #include <memory.h>
467c478bd9Sstevel@tonic-gate #include "msgs.h"
477c478bd9Sstevel@tonic-gate #include "extern.h"
487c478bd9Sstevel@tonic-gate #include <sac.h>
497c478bd9Sstevel@tonic-gate #include "misc.h"
507c478bd9Sstevel@tonic-gate #include "structs.h"
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate #include <security/pam_appl.h>
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate #define RESP 1 /* pollfail via no response to sanity poll */
557c478bd9Sstevel@tonic-gate #define DEATH 2 /* pollfail via child death */
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate /* signal whose dispositions will be changed */
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate static struct sigaction Sigpoll; /* SIGPOLL */
607c478bd9Sstevel@tonic-gate static struct sigaction Sigcld; /* SIGCLD */
617c478bd9Sstevel@tonic-gate static struct sigaction Sigalrm; /* SIGALRM */
627c478bd9Sstevel@tonic-gate static sigset_t Origmask; /* original signal mask */
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate void usage(void);
657c478bd9Sstevel@tonic-gate void initialize(void);
667c478bd9Sstevel@tonic-gate void startpms(void);
677c478bd9Sstevel@tonic-gate void readutmpx(void);
687c478bd9Sstevel@tonic-gate int startpm(struct sactab *);
697c478bd9Sstevel@tonic-gate void cleanutx(struct sactab *);
707c478bd9Sstevel@tonic-gate void account(struct sactab *, pid_t);
717c478bd9Sstevel@tonic-gate void startit(struct sactab *);
727c478bd9Sstevel@tonic-gate char **mkargv(struct sactab *);
737c478bd9Sstevel@tonic-gate void pollpms(void);
747c478bd9Sstevel@tonic-gate void reap(int);
757c478bd9Sstevel@tonic-gate void pollfail(struct sactab *, int);
767c478bd9Sstevel@tonic-gate void readpipe(void);
777c478bd9Sstevel@tonic-gate int validstate(unchar);
787c478bd9Sstevel@tonic-gate int mk_cmd_pipe(void);
797c478bd9Sstevel@tonic-gate void startpoll(void);
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate /*
847c478bd9Sstevel@tonic-gate * main - scan args for sac, initialize everything, and wait for commands
857c478bd9Sstevel@tonic-gate * from sacadm via the command pipe
867c478bd9Sstevel@tonic-gate */
877c478bd9Sstevel@tonic-gate
88*34e48580Sdp int
main(int argc,char * argv[])897c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate int c; /* place to hold options */
927c478bd9Sstevel@tonic-gate struct sigaction sigact; /* for signal handling */
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, NULL, &Origmask);
957c478bd9Sstevel@tonic-gate if (argc == 1)
967c478bd9Sstevel@tonic-gate usage();
977c478bd9Sstevel@tonic-gate (void) setpgrp();
987c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "t:")) != -1) {
997c478bd9Sstevel@tonic-gate switch (c) {
1007c478bd9Sstevel@tonic-gate case 't':
1017c478bd9Sstevel@tonic-gate if (Stime != 0)
1027c478bd9Sstevel@tonic-gate usage();
1037c478bd9Sstevel@tonic-gate Stime = atoi(optarg);
1047c478bd9Sstevel@tonic-gate if (Stime <= 0)
1057c478bd9Sstevel@tonic-gate usage();
1067c478bd9Sstevel@tonic-gate break;
1077c478bd9Sstevel@tonic-gate case '?':
1087c478bd9Sstevel@tonic-gate usage();
1097c478bd9Sstevel@tonic-gate }
1107c478bd9Sstevel@tonic-gate }
1117c478bd9Sstevel@tonic-gate if (optind < argc)
1127c478bd9Sstevel@tonic-gate usage();
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate initialize();
1157c478bd9Sstevel@tonic-gate sigact.sa_flags = 0;
1167c478bd9Sstevel@tonic-gate sigact.sa_handler = pollpms;
1177c478bd9Sstevel@tonic-gate (void) sigemptyset(&sigact.sa_mask);
1187c478bd9Sstevel@tonic-gate (void) sigaddset(&sigact.sa_mask, SIGALRM);
1197c478bd9Sstevel@tonic-gate (void) sigaction(SIGALRM, &sigact, &Sigalrm);
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate /*
1227c478bd9Sstevel@tonic-gate * minimize time spent in STARTING or UNKNOWN, pollpms() sets alarm
1237c478bd9Sstevel@tonic-gate */
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate pollpms();
1267c478bd9Sstevel@tonic-gate for (;;)
1277c478bd9Sstevel@tonic-gate readpipe();
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate /*
1327c478bd9Sstevel@tonic-gate * usage - output a usage message on the console
1337c478bd9Sstevel@tonic-gate */
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate void
usage()1367c478bd9Sstevel@tonic-gate usage()
1377c478bd9Sstevel@tonic-gate {
1387c478bd9Sstevel@tonic-gate FILE *fp; /* scratch file pointer */
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate fp = fopen("/dev/console", "w");
1417c478bd9Sstevel@tonic-gate if (fp)
1427c478bd9Sstevel@tonic-gate (void) fprintf(fp, "SAC: Usage: sac -t sanity_interval\n");
1437c478bd9Sstevel@tonic-gate exit(1);
1447c478bd9Sstevel@tonic-gate }
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate /*
1487c478bd9Sstevel@tonic-gate * initialize - initialization stuff
1497c478bd9Sstevel@tonic-gate */
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate void
initialize()1537c478bd9Sstevel@tonic-gate initialize()
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate int ret; /* return code from doconfig() */
1567c478bd9Sstevel@tonic-gate struct sigaction sigact; /* for signal handling */
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate openlog();
1597c478bd9Sstevel@tonic-gate log("*** SAC starting ***");
1607c478bd9Sstevel@tonic-gate #ifdef DEBUG
1617c478bd9Sstevel@tonic-gate opendebug();
1627c478bd9Sstevel@tonic-gate log("Debugging turned on");
1637c478bd9Sstevel@tonic-gate #endif
1647c478bd9Sstevel@tonic-gate if (chdir(HOME) < 0)
1657c478bd9Sstevel@tonic-gate error(E_CHDIR, EXIT);
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate /*
1687c478bd9Sstevel@tonic-gate * pass an invalid fd, shouldn't be doing pushes and pops in this per-system
1697c478bd9Sstevel@tonic-gate * configuration script (_sysconfig)
1707c478bd9Sstevel@tonic-gate */
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate if ((ret = doconfig(-1, SYSCONFIG, 0)) != 0) {
1737c478bd9Sstevel@tonic-gate if (ret == -1)
1747c478bd9Sstevel@tonic-gate error(E_SYSCONF, EXIT);
1757c478bd9Sstevel@tonic-gate else {
1767c478bd9Sstevel@tonic-gate (void) sprintf(Scratch,
1777c478bd9Sstevel@tonic-gate "Error in _sysconfig: line %d", ret);
1787c478bd9Sstevel@tonic-gate log(Scratch);
1797c478bd9Sstevel@tonic-gate error(E_BADSYSCONF, EXIT);
1807c478bd9Sstevel@tonic-gate }
1817c478bd9Sstevel@tonic-gate }
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate sigact.sa_flags = 0;
1847c478bd9Sstevel@tonic-gate sigact.sa_handler = reap;
1857c478bd9Sstevel@tonic-gate (void) sigemptyset(&sigact.sa_mask);
1867c478bd9Sstevel@tonic-gate (void) sigaddset(&sigact.sa_mask, SIGCLD);
1877c478bd9Sstevel@tonic-gate (void) sigaction(SIGCLD, &sigact, &Sigcld);
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate /*
1907c478bd9Sstevel@tonic-gate * establish pipe for PMS to communicate with sac
1917c478bd9Sstevel@tonic-gate */
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate if (access("_sacpipe", 0) != 0) {
1947c478bd9Sstevel@tonic-gate /* not there, create one */
1957c478bd9Sstevel@tonic-gate (void) umask(0);
1967c478bd9Sstevel@tonic-gate if (mknod("_sacpipe", S_IFIFO | 0600, 0) < 0)
1977c478bd9Sstevel@tonic-gate error(E_NOPIPE, EXIT);
1987c478bd9Sstevel@tonic-gate }
1997c478bd9Sstevel@tonic-gate Sfd = open("_sacpipe", O_RDWR);
2007c478bd9Sstevel@tonic-gate if (Sfd < 0)
2017c478bd9Sstevel@tonic-gate error(E_NOPIPE, EXIT);
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate /*
2047c478bd9Sstevel@tonic-gate * establish pipe for sacadm to communicate with sac
2057c478bd9Sstevel@tonic-gate */
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate Cfd = mk_cmd_pipe();
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate /*
2107c478bd9Sstevel@tonic-gate * read in _sactab, but don't start port monitors as a by-product
2117c478bd9Sstevel@tonic-gate * since we may be in recovery - start them explicitly instead
2127c478bd9Sstevel@tonic-gate */
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate read_table(FALSE);
2157c478bd9Sstevel@tonic-gate startpoll();
2167c478bd9Sstevel@tonic-gate startpms();
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate
2207c478bd9Sstevel@tonic-gate /*
2217c478bd9Sstevel@tonic-gate * startpms - start initial set of port monitors
2227c478bd9Sstevel@tonic-gate */
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate
2257c478bd9Sstevel@tonic-gate void
startpms()2267c478bd9Sstevel@tonic-gate startpms()
2277c478bd9Sstevel@tonic-gate {
2287c478bd9Sstevel@tonic-gate struct sactab *sp; /* working pointer */
2297c478bd9Sstevel@tonic-gate int rflag; /* recovery flag */
2307c478bd9Sstevel@tonic-gate pid_t checklock();
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate /*
2337c478bd9Sstevel@tonic-gate * check to see if we're really a recovering SAC (if any port monitors hold
2347c478bd9Sstevel@tonic-gate * locks, assume that we're in recovery), if so, start differently
2357c478bd9Sstevel@tonic-gate */
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate rflag = 0;
2387c478bd9Sstevel@tonic-gate for (sp = Sactab; sp; sp = sp->sc_next) {
2397c478bd9Sstevel@tonic-gate if (checklock(sp)) {
2407c478bd9Sstevel@tonic-gate rflag = 1;
2417c478bd9Sstevel@tonic-gate sp->sc_sstate = sp->sc_pstate = UNKNOWN;
2427c478bd9Sstevel@tonic-gate sp->sc_ok = 1;
2437c478bd9Sstevel@tonic-gate sp->sc_exit = 0;
2447c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, "%s/_pmpipe", sp->sc_tag);
2457c478bd9Sstevel@tonic-gate sp->sc_fd = open(Scratch, O_RDWR);
2467c478bd9Sstevel@tonic-gate if (sp->sc_fd < 0) {
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate /*
2497c478bd9Sstevel@tonic-gate * if we get into here, we're in deep trouble. PM seems to be running
2507c478bd9Sstevel@tonic-gate * and we're trying to recover, but we can't talk to it. Unfortunately,
2517c478bd9Sstevel@tonic-gate * there's not much that can be done other than to try and restore a
2527c478bd9Sstevel@tonic-gate * sane state. By setting sp->sc_ok to 0, this will look like a poll failure
2537c478bd9Sstevel@tonic-gate * and if sp->rs_rsmax > 0, PM will be restarted.
2547c478bd9Sstevel@tonic-gate */
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate (void) sprintf(Scratch,
2577c478bd9Sstevel@tonic-gate "Could not open _pmpipe for port monitor <%s>",
2587c478bd9Sstevel@tonic-gate sp->sc_tag);
2597c478bd9Sstevel@tonic-gate log(Scratch);
2607c478bd9Sstevel@tonic-gate (void) sendsig(sp, SIGTERM);
2617c478bd9Sstevel@tonic-gate sp->sc_ok = 0;
2627c478bd9Sstevel@tonic-gate }
2637c478bd9Sstevel@tonic-gate }
2647c478bd9Sstevel@tonic-gate }
2657c478bd9Sstevel@tonic-gate if (rflag) {
2667c478bd9Sstevel@tonic-gate readutmpx();
2677c478bd9Sstevel@tonic-gate log("SAC in recovery");
2687c478bd9Sstevel@tonic-gate return;
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate /*
2727c478bd9Sstevel@tonic-gate * normal startup
2737c478bd9Sstevel@tonic-gate */
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate for (sp = Sactab; sp; sp = sp->sc_next) {
2767c478bd9Sstevel@tonic-gate if (sp->sc_flags & X_FLAG) {
2777c478bd9Sstevel@tonic-gate /* System Administator specified don't start */
2787c478bd9Sstevel@tonic-gate continue;
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate (void) startpm(sp);
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate
2857c478bd9Sstevel@tonic-gate /*
2867c478bd9Sstevel@tonic-gate * readutmpx - read the utmpx file to find out the ids of running port
2877c478bd9Sstevel@tonic-gate * monitors (only called during a recover start up). Note:
2887c478bd9Sstevel@tonic-gate * after a sac failure, init will inherit all of the port
2897c478bd9Sstevel@tonic-gate * monitors and should get the SIGCLD's if they die (and
2907c478bd9Sstevel@tonic-gate * will clean up). This is mainly for stuck processes,
2917c478bd9Sstevel@tonic-gate * although init would get the SIGCLD when the stuckie gets
2927c478bd9Sstevel@tonic-gate * killed, it doesn't hurt to have the sac check. This is
2937c478bd9Sstevel@tonic-gate * only done once.
2947c478bd9Sstevel@tonic-gate *
2957c478bd9Sstevel@tonic-gate */
2967c478bd9Sstevel@tonic-gate
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate void
readutmpx()2997c478bd9Sstevel@tonic-gate readutmpx()
3007c478bd9Sstevel@tonic-gate {
3017c478bd9Sstevel@tonic-gate struct sactab *sp; /* working pointer */
3027c478bd9Sstevel@tonic-gate struct sactab *savesp; /* rembered port monitor match */
3037c478bd9Sstevel@tonic-gate struct utmpx *uxp; /* working pointer */
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate setutxent();
3067c478bd9Sstevel@tonic-gate while (uxp = getutxent()) {
3077c478bd9Sstevel@tonic-gate /* we're only interested in login processes */
3087c478bd9Sstevel@tonic-gate if (uxp->ut_type != LOGIN_PROCESS)
3097c478bd9Sstevel@tonic-gate continue;
3107c478bd9Sstevel@tonic-gate if (uxp->ut_user[sizeof (uxp->ut_user) - 1] == '\0') {
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate /*
3137c478bd9Sstevel@tonic-gate * possible port monitor and name is short enough to do a normal compare
3147c478bd9Sstevel@tonic-gate */
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate sp = findpm(uxp->ut_user);
3177c478bd9Sstevel@tonic-gate if (sp && (sp->sc_sstate == UNKNOWN)) {
3187c478bd9Sstevel@tonic-gate /* found one */
3197c478bd9Sstevel@tonic-gate (void) memcpy(sp->sc_utid, uxp->ut_id, IDLEN);
3207c478bd9Sstevel@tonic-gate sp->sc_pid = uxp->ut_pid;
3217c478bd9Sstevel@tonic-gate }
3227c478bd9Sstevel@tonic-gate } else {
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate /*
3257c478bd9Sstevel@tonic-gate * possible port monitor name, but it could have been truncated. If
3267c478bd9Sstevel@tonic-gate * a match is found on a unique prefix, then it should be the correct
3277c478bd9Sstevel@tonic-gate * entry. If an ambiguity is found, ignore the entry, init will clean
3287c478bd9Sstevel@tonic-gate * up the entry if it dies.
3297c478bd9Sstevel@tonic-gate */
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate savesp = NULL;
3327c478bd9Sstevel@tonic-gate for (sp = Sactab; sp; sp = sp->sc_next) {
3337c478bd9Sstevel@tonic-gate if (strncmp(uxp->ut_user, sp->sc_tag,
3347c478bd9Sstevel@tonic-gate sizeof (uxp->ut_user)) == 0) {
3357c478bd9Sstevel@tonic-gate if (savesp) {
3367c478bd9Sstevel@tonic-gate /* already found a match */
3377c478bd9Sstevel@tonic-gate savesp = NULL;
3387c478bd9Sstevel@tonic-gate (void) sprintf(Scratch,
3397c478bd9Sstevel@tonic-gate "ambiguous utmpx entry <%.8s>",
3407c478bd9Sstevel@tonic-gate sp->sc_tag);
3417c478bd9Sstevel@tonic-gate log(Scratch);
3427c478bd9Sstevel@tonic-gate break;
3437c478bd9Sstevel@tonic-gate } else {
3447c478bd9Sstevel@tonic-gate savesp = sp;
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate }
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate if (savesp && (savesp->sc_sstate == UNKNOWN)) {
3497c478bd9Sstevel@tonic-gate /* found it */
3507c478bd9Sstevel@tonic-gate (void) memcpy(savesp->sc_utid, uxp->ut_id,
3517c478bd9Sstevel@tonic-gate IDLEN);
3527c478bd9Sstevel@tonic-gate savesp->sc_pid = uxp->ut_pid;
3537c478bd9Sstevel@tonic-gate }
3547c478bd9Sstevel@tonic-gate }
3557c478bd9Sstevel@tonic-gate }
3567c478bd9Sstevel@tonic-gate endutxent();
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate /*
3617c478bd9Sstevel@tonic-gate * startpm - start a particular PM, return code:
3627c478bd9Sstevel@tonic-gate * -1: _pid file locked
3637c478bd9Sstevel@tonic-gate * -2: any other reason
3647c478bd9Sstevel@tonic-gate *
3657c478bd9Sstevel@tonic-gate * args: sp - pointer to sac's port monitor information for
3667c478bd9Sstevel@tonic-gate * designated port monitor
3677c478bd9Sstevel@tonic-gate */
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate int
startpm(struct sactab * sp)3707c478bd9Sstevel@tonic-gate startpm(struct sactab *sp)
3717c478bd9Sstevel@tonic-gate {
3727c478bd9Sstevel@tonic-gate sigset_t cset; /* for signal handling */
3737c478bd9Sstevel@tonic-gate sigset_t tset; /* for signal handling */
3747c478bd9Sstevel@tonic-gate pid_t pid; /* pid of new port monitor */
3757c478bd9Sstevel@tonic-gate pid_t checklock();
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate #ifdef DEBUG
3787c478bd9Sstevel@tonic-gate debug("in startpm");
3797c478bd9Sstevel@tonic-gate #endif
3807c478bd9Sstevel@tonic-gate if (checklock(sp)) {
3817c478bd9Sstevel@tonic-gate (void) sprintf(Scratch,
3827c478bd9Sstevel@tonic-gate "could not start <%s> - _pid file locked", sp->sc_tag);
3837c478bd9Sstevel@tonic-gate log(Scratch);
3847c478bd9Sstevel@tonic-gate return (-1);
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate
3877c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, "%s/_pmpipe", sp->sc_tag);
3887c478bd9Sstevel@tonic-gate if (access(Scratch, 0) != 0) {
3897c478bd9Sstevel@tonic-gate /* not there, create one */
3907c478bd9Sstevel@tonic-gate (void) umask(0);
3917c478bd9Sstevel@tonic-gate if (mknod(Scratch, S_IFIFO | 0600, 0) < 0) {
3927c478bd9Sstevel@tonic-gate (void) sprintf(Scratch,
3937c478bd9Sstevel@tonic-gate "Could not create _pmpipe for port monitor <%s>, errno is %d",
3947c478bd9Sstevel@tonic-gate sp->sc_tag, errno);
3957c478bd9Sstevel@tonic-gate log(Scratch);
3967c478bd9Sstevel@tonic-gate return (-2);
3977c478bd9Sstevel@tonic-gate }
3987c478bd9Sstevel@tonic-gate }
3997c478bd9Sstevel@tonic-gate sp->sc_fd = open(Scratch, O_RDWR);
4007c478bd9Sstevel@tonic-gate if (sp->sc_fd < 0) {
4017c478bd9Sstevel@tonic-gate (void) sprintf(Scratch,
4027c478bd9Sstevel@tonic-gate "Could not open _pmpipe for port monitor <%s>, errno is %d",
4037c478bd9Sstevel@tonic-gate sp->sc_tag, errno);
4047c478bd9Sstevel@tonic-gate log(Scratch);
4057c478bd9Sstevel@tonic-gate return (-2);
4067c478bd9Sstevel@tonic-gate }
4077c478bd9Sstevel@tonic-gate
4087c478bd9Sstevel@tonic-gate /* in case child dies too quickly */
4097c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, NULL, &cset);
4107c478bd9Sstevel@tonic-gate tset = cset;
4117c478bd9Sstevel@tonic-gate (void) sigaddset(&tset, SIGCLD);
4127c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &tset, NULL);
4137c478bd9Sstevel@tonic-gate if ((pid = fork()) < 0) {
4147c478bd9Sstevel@tonic-gate (void) sprintf(Scratch,
4157c478bd9Sstevel@tonic-gate "Could not fork port monitor <%s>", sp->sc_tag);
4167c478bd9Sstevel@tonic-gate log(Scratch);
4177c478bd9Sstevel@tonic-gate return (-2);
4187c478bd9Sstevel@tonic-gate } else if (!pid) {
4197c478bd9Sstevel@tonic-gate startit(sp);
4207c478bd9Sstevel@tonic-gate /* no return */
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate
4237c478bd9Sstevel@tonic-gate /*
4247c478bd9Sstevel@tonic-gate * clean up old utmpx if its there
4257c478bd9Sstevel@tonic-gate */
4267c478bd9Sstevel@tonic-gate
4277c478bd9Sstevel@tonic-gate cleanutx(sp);
4287c478bd9Sstevel@tonic-gate
4297c478bd9Sstevel@tonic-gate /*
4307c478bd9Sstevel@tonic-gate * create a utmpx entry and set initial states
4317c478bd9Sstevel@tonic-gate */
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate account(sp, pid);
4347c478bd9Sstevel@tonic-gate sp->sc_pstate = STARTING;
4357c478bd9Sstevel@tonic-gate if (sp->sc_lstate == NOTRUNNING)
4367c478bd9Sstevel@tonic-gate sp->sc_sstate = (sp->sc_flags & D_FLAG) ? DISABLED : ENABLED;
4377c478bd9Sstevel@tonic-gate else
4387c478bd9Sstevel@tonic-gate sp->sc_sstate = sp->sc_lstate;
4397c478bd9Sstevel@tonic-gate sp->sc_ok = 1;
4407c478bd9Sstevel@tonic-gate sp->sc_exit = 0;
4417c478bd9Sstevel@tonic-gate sp->sc_pid = pid;
4427c478bd9Sstevel@tonic-gate /* ok to take signals now that the table is up-to-table */
4437c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &cset, NULL);
4447c478bd9Sstevel@tonic-gate return (0);
4457c478bd9Sstevel@tonic-gate }
4467c478bd9Sstevel@tonic-gate
4477c478bd9Sstevel@tonic-gate
4487c478bd9Sstevel@tonic-gate /*
4497c478bd9Sstevel@tonic-gate * cleanutx - clean out a utmpx record for a port monitor
4507c478bd9Sstevel@tonic-gate *
4517c478bd9Sstevel@tonic-gate * args: sp - pointer to sac's port monitor information for
4527c478bd9Sstevel@tonic-gate * designated port monitor
4537c478bd9Sstevel@tonic-gate */
4547c478bd9Sstevel@tonic-gate
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate void
cleanutx(struct sactab * sp)4577c478bd9Sstevel@tonic-gate cleanutx(struct sactab *sp)
4587c478bd9Sstevel@tonic-gate {
4597c478bd9Sstevel@tonic-gate int i; /* scratch variable */
4607c478bd9Sstevel@tonic-gate int zerocheck; /* scratch variable */
4617c478bd9Sstevel@tonic-gate char buf[SIZE]; /* scratch buffer */
4627c478bd9Sstevel@tonic-gate pam_handle_t *pamh; /* PAM auth descriptor */
4637c478bd9Sstevel@tonic-gate struct utmpx ut;
4647c478bd9Sstevel@tonic-gate struct utmpx *up;
4657c478bd9Sstevel@tonic-gate int pid;
4667c478bd9Sstevel@tonic-gate char user[sizeof (up->ut_user) + 1];
4677c478bd9Sstevel@tonic-gate char ttyn[sizeof (up->ut_line) + 1];
4687c478bd9Sstevel@tonic-gate char rhost[sizeof (up->ut_host) + 1];
4697c478bd9Sstevel@tonic-gate /*
4707c478bd9Sstevel@tonic-gate * check to see if there is a utmpx entry to clean up (indicated by a non
4717c478bd9Sstevel@tonic-gate * zero utmpx id
4727c478bd9Sstevel@tonic-gate */
4737c478bd9Sstevel@tonic-gate zerocheck = 0;
4747c478bd9Sstevel@tonic-gate for (i = 0; i < IDLEN; ++i) {
4757c478bd9Sstevel@tonic-gate zerocheck += sp->sc_utid[i];
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate if (zerocheck == 0)
4787c478bd9Sstevel@tonic-gate return;
4797c478bd9Sstevel@tonic-gate
4807c478bd9Sstevel@tonic-gate pid = sp->sc_pid;
4817c478bd9Sstevel@tonic-gate setutxent();
4827c478bd9Sstevel@tonic-gate while (up = getutxent()) {
4837c478bd9Sstevel@tonic-gate if (up->ut_pid == pid) {
4847c478bd9Sstevel@tonic-gate if (up->ut_type == DEAD_PROCESS) {
4857c478bd9Sstevel@tonic-gate /*
4867c478bd9Sstevel@tonic-gate * Cleaned up elsewhere.
4877c478bd9Sstevel@tonic-gate */
4887c478bd9Sstevel@tonic-gate break;
4897c478bd9Sstevel@tonic-gate }
4907c478bd9Sstevel@tonic-gate strncpy(user, up->ut_user, sizeof (up->ut_user));
4917c478bd9Sstevel@tonic-gate user[sizeof (up->ut_user)] = '\0';
4927c478bd9Sstevel@tonic-gate strncpy(ttyn, up->ut_line, sizeof (up->ut_line));
4937c478bd9Sstevel@tonic-gate ttyn[sizeof (up->ut_line)] = '\0';
4947c478bd9Sstevel@tonic-gate strncpy(rhost, up->ut_host, sizeof (up->ut_host));
4957c478bd9Sstevel@tonic-gate rhost[sizeof (up->ut_host)] = '\0';
4967c478bd9Sstevel@tonic-gate
4977c478bd9Sstevel@tonic-gate if ((pam_start("sac", user, NULL, &pamh)) ==
4987c478bd9Sstevel@tonic-gate PAM_SUCCESS) {
4997c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_TTY, ttyn);
5007c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_RHOST, rhost);
5017c478bd9Sstevel@tonic-gate (void) pam_close_session(pamh, 0);
5027c478bd9Sstevel@tonic-gate pam_end(pamh, PAM_SUCCESS);
5037c478bd9Sstevel@tonic-gate }
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate up->ut_type = DEAD_PROCESS;
5067c478bd9Sstevel@tonic-gate up->ut_exit.e_termination = WTERMSIG(sp->sc_exit);
5077c478bd9Sstevel@tonic-gate up->ut_exit.e_exit = WEXITSTATUS(sp->sc_exit);
5087c478bd9Sstevel@tonic-gate if (sp->sc_utid != NULL)
5097c478bd9Sstevel@tonic-gate (void) memcpy(up->ut_id, sp->sc_utid,
5107c478bd9Sstevel@tonic-gate sizeof (up->ut_id));
5117c478bd9Sstevel@tonic-gate (void) time(&up->ut_tv.tv_sec);
5127c478bd9Sstevel@tonic-gate if (modutx(up) == NULL) {
5137c478bd9Sstevel@tonic-gate /*
5147c478bd9Sstevel@tonic-gate * Since modutx failed we'll
5157c478bd9Sstevel@tonic-gate * write out the new entry
5167c478bd9Sstevel@tonic-gate * ourselves.
5177c478bd9Sstevel@tonic-gate */
5187c478bd9Sstevel@tonic-gate (void) pututxline(up);
5197c478bd9Sstevel@tonic-gate updwtmpx("wtmpx", up);
5207c478bd9Sstevel@tonic-gate }
5217c478bd9Sstevel@tonic-gate break;
5227c478bd9Sstevel@tonic-gate }
5237c478bd9Sstevel@tonic-gate }
5247c478bd9Sstevel@tonic-gate endutxent();
5257c478bd9Sstevel@tonic-gate }
5267c478bd9Sstevel@tonic-gate
5277c478bd9Sstevel@tonic-gate /*
5287c478bd9Sstevel@tonic-gate * account - create a utmp record for a port monitor
5297c478bd9Sstevel@tonic-gate *
5307c478bd9Sstevel@tonic-gate * args: pid - process id of port monitor
5317c478bd9Sstevel@tonic-gate */
5327c478bd9Sstevel@tonic-gate
5337c478bd9Sstevel@tonic-gate
5347c478bd9Sstevel@tonic-gate void
account(struct sactab * sp,pid_t pid)5357c478bd9Sstevel@tonic-gate account(struct sactab *sp, pid_t pid)
5367c478bd9Sstevel@tonic-gate {
5377c478bd9Sstevel@tonic-gate struct utmpx utmpx; /* prototype utmpx entry */
5387c478bd9Sstevel@tonic-gate struct utmpx *up = &utmpx; /* and a pointer to it */
5397c478bd9Sstevel@tonic-gate
5407c478bd9Sstevel@tonic-gate (void) memset(up, '\0', sizeof (utmpx));
5417c478bd9Sstevel@tonic-gate (void) strncpy(up->ut_user, sp->sc_tag, sizeof (up->ut_user));
5427c478bd9Sstevel@tonic-gate up->ut_pid = pid;
5437c478bd9Sstevel@tonic-gate up->ut_type = LOGIN_PROCESS;
5447c478bd9Sstevel@tonic-gate up->ut_id[0] = 'P';
5457c478bd9Sstevel@tonic-gate up->ut_id[1] = 'M';
5467c478bd9Sstevel@tonic-gate up->ut_id[2] = SC_WILDC;
5477c478bd9Sstevel@tonic-gate up->ut_id[3] = SC_WILDC;
5487c478bd9Sstevel@tonic-gate (void) time(&up->ut_xtime);
5497c478bd9Sstevel@tonic-gate if (makeutx(up) == NULL) {
5507c478bd9Sstevel@tonic-gate log("Could not create utmpx entry");
5517c478bd9Sstevel@tonic-gate (void) memset(sp->sc_utid, '\0', IDLEN);
5527c478bd9Sstevel@tonic-gate } else {
5537c478bd9Sstevel@tonic-gate (void) memcpy(sp->sc_utid, up->ut_id, IDLEN);
5547c478bd9Sstevel@tonic-gate }
5557c478bd9Sstevel@tonic-gate }
5567c478bd9Sstevel@tonic-gate
5577c478bd9Sstevel@tonic-gate
5587c478bd9Sstevel@tonic-gate /*
5597c478bd9Sstevel@tonic-gate * startit - finish starting a particular port monitor, establish environment,
5607c478bd9Sstevel@tonic-gate * etc. (Note: this is the child at this point)
5617c478bd9Sstevel@tonic-gate *
5627c478bd9Sstevel@tonic-gate * args: sp - pointer to sac's port monitor information for
5637c478bd9Sstevel@tonic-gate * designated port monitor
5647c478bd9Sstevel@tonic-gate */
5657c478bd9Sstevel@tonic-gate
5667c478bd9Sstevel@tonic-gate
5677c478bd9Sstevel@tonic-gate void
startit(struct sactab * sp)5687c478bd9Sstevel@tonic-gate startit(struct sactab *sp)
5697c478bd9Sstevel@tonic-gate {
5707c478bd9Sstevel@tonic-gate static char istate[SIZE]; /* place to put ISTATE env var. */
5717c478bd9Sstevel@tonic-gate static char pmtag[SIZE]; /* place to put PMTAG env var. */
5727c478bd9Sstevel@tonic-gate char **argvp; /* arglist for PM */
5737c478bd9Sstevel@tonic-gate int i; /* loop control variable */
5747c478bd9Sstevel@tonic-gate long ndesc; /* # of file descriptors configured */
5757c478bd9Sstevel@tonic-gate int ret; /* return value from doconfig */
5767c478bd9Sstevel@tonic-gate sigset_t cset; /* for signal handling */
5777c478bd9Sstevel@tonic-gate sigset_t tset; /* for signal handling */
5787c478bd9Sstevel@tonic-gate
5797c478bd9Sstevel@tonic-gate /*
5807c478bd9Sstevel@tonic-gate * establish the home directory
5817c478bd9Sstevel@tonic-gate */
5827c478bd9Sstevel@tonic-gate
5837c478bd9Sstevel@tonic-gate if (chdir(sp->sc_tag) < 0) {
5847c478bd9Sstevel@tonic-gate (void) sprintf(Scratch,
5857c478bd9Sstevel@tonic-gate "Cannot chdir to <%s/%s>, port monitor not started",
5867c478bd9Sstevel@tonic-gate HOME, sp->sc_tag);
5877c478bd9Sstevel@tonic-gate log(Scratch);
5887c478bd9Sstevel@tonic-gate exit(1);
5897c478bd9Sstevel@tonic-gate }
5907c478bd9Sstevel@tonic-gate
5917c478bd9Sstevel@tonic-gate /*
5927c478bd9Sstevel@tonic-gate * interpret the configuration script, pass an invalid fd, shouldn't be
5937c478bd9Sstevel@tonic-gate * doing pushes and pops in this script
5947c478bd9Sstevel@tonic-gate */
5957c478bd9Sstevel@tonic-gate
5967c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, NULL, &cset);
5977c478bd9Sstevel@tonic-gate tset = cset;
5987c478bd9Sstevel@tonic-gate (void) sigaddset(&tset, SIGCLD);
5997c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &tset, NULL);
6007c478bd9Sstevel@tonic-gate if ((ret = doconfig(-1, "_config", 0)) != 0) {
6017c478bd9Sstevel@tonic-gate if (ret == -1) {
6027c478bd9Sstevel@tonic-gate (void) sprintf(Scratch,
6037c478bd9Sstevel@tonic-gate "system error in _config script for <%s>",
6047c478bd9Sstevel@tonic-gate sp->sc_tag);
6057c478bd9Sstevel@tonic-gate log(Scratch);
6067c478bd9Sstevel@tonic-gate exit(1);
6077c478bd9Sstevel@tonic-gate } else {
6087c478bd9Sstevel@tonic-gate (void) sprintf(Scratch,
6097c478bd9Sstevel@tonic-gate "Error in _config script for <%s>: line %d",
6107c478bd9Sstevel@tonic-gate sp->sc_tag, ret);
6117c478bd9Sstevel@tonic-gate log(Scratch);
6127c478bd9Sstevel@tonic-gate exit(1);
6137c478bd9Sstevel@tonic-gate }
6147c478bd9Sstevel@tonic-gate }
6157c478bd9Sstevel@tonic-gate
6167c478bd9Sstevel@tonic-gate /*
6177c478bd9Sstevel@tonic-gate * add the promised environment variables
6187c478bd9Sstevel@tonic-gate */
6197c478bd9Sstevel@tonic-gate
6207c478bd9Sstevel@tonic-gate if (sp->sc_lstate == NOTRUNNING)
6217c478bd9Sstevel@tonic-gate (void) sprintf(istate, "ISTATE=%s",
6227c478bd9Sstevel@tonic-gate (sp->sc_flags & D_FLAG) ? "disabled" : "enabled");
6237c478bd9Sstevel@tonic-gate else
6247c478bd9Sstevel@tonic-gate (void) sprintf(istate, "ISTATE=%s",
6257c478bd9Sstevel@tonic-gate (sp->sc_lstate == DISABLED) ? "disabled" : "enabled");
6267c478bd9Sstevel@tonic-gate if (putenv(istate)) {
6277c478bd9Sstevel@tonic-gate (void) sprintf(Scratch,
6287c478bd9Sstevel@tonic-gate "can't expand port monitor <%s> environment",
6297c478bd9Sstevel@tonic-gate sp->sc_tag);
6307c478bd9Sstevel@tonic-gate log(Scratch);
6317c478bd9Sstevel@tonic-gate exit(1);
6327c478bd9Sstevel@tonic-gate }
6337c478bd9Sstevel@tonic-gate (void) sprintf(pmtag, "PMTAG=%s", sp->sc_tag);
6347c478bd9Sstevel@tonic-gate if (putenv(pmtag)) {
6357c478bd9Sstevel@tonic-gate (void) sprintf(Scratch,
6367c478bd9Sstevel@tonic-gate "can't expand port monitor <%s> environment",
6377c478bd9Sstevel@tonic-gate sp->sc_tag);
6387c478bd9Sstevel@tonic-gate log(Scratch);
6397c478bd9Sstevel@tonic-gate exit(1);
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate
6427c478bd9Sstevel@tonic-gate /*
6437c478bd9Sstevel@tonic-gate * build an argv
6447c478bd9Sstevel@tonic-gate */
6457c478bd9Sstevel@tonic-gate
6467c478bd9Sstevel@tonic-gate argvp = mkargv(sp);
6477c478bd9Sstevel@tonic-gate
6487c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, "starting port monitor <%s>", sp->sc_tag);
6497c478bd9Sstevel@tonic-gate log(Scratch);
6507c478bd9Sstevel@tonic-gate ndesc = ulimit(4, 0L);
6517c478bd9Sstevel@tonic-gate for (i = 0; i < ndesc; i++)
6527c478bd9Sstevel@tonic-gate (void) fcntl(i, F_SETFD, 1);
6537c478bd9Sstevel@tonic-gate /* restore orignal handlers and mask */
6547c478bd9Sstevel@tonic-gate (void) sigaction(SIGPOLL, &Sigpoll, NULL);
6557c478bd9Sstevel@tonic-gate (void) sigaction(SIGCLD, &Sigcld, NULL);
6567c478bd9Sstevel@tonic-gate (void) sigaction(SIGALRM, &Sigalrm, NULL);
6577c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &Origmask, NULL);
6587c478bd9Sstevel@tonic-gate (void) execve(argvp[0], argvp, environ);
6597c478bd9Sstevel@tonic-gate (void) sprintf(Scratch, "exec of port monitor <%s> failed", sp->sc_tag);
6607c478bd9Sstevel@tonic-gate log(Scratch);
6617c478bd9Sstevel@tonic-gate exit(1);
6627c478bd9Sstevel@tonic-gate }
6637c478bd9Sstevel@tonic-gate
6647c478bd9Sstevel@tonic-gate
6657c478bd9Sstevel@tonic-gate /*
6667c478bd9Sstevel@tonic-gate * mkargv - Given a pointer to a struct sactab, construct argv
6677c478bd9Sstevel@tonic-gate * for an exec system call.
6687c478bd9Sstevel@tonic-gate *
6697c478bd9Sstevel@tonic-gate * args: sp - pointer to sac's port monitor information for
6707c478bd9Sstevel@tonic-gate * designated port montior
6717c478bd9Sstevel@tonic-gate */
6727c478bd9Sstevel@tonic-gate
6737c478bd9Sstevel@tonic-gate
6747c478bd9Sstevel@tonic-gate #define NARGS 50 /* max # of args */
6757c478bd9Sstevel@tonic-gate
6767c478bd9Sstevel@tonic-gate static char *newargv[NARGS]; /* place for argv list */
6777c478bd9Sstevel@tonic-gate static char *delim = " \t'\""; /* delimiter list */
6787c478bd9Sstevel@tonic-gate
6797c478bd9Sstevel@tonic-gate char **
mkargv(struct sactab * sp)6807c478bd9Sstevel@tonic-gate mkargv(struct sactab *sp)
6817c478bd9Sstevel@tonic-gate {
6827c478bd9Sstevel@tonic-gate char **argvp = newargv; /* scratch pointer */
6837c478bd9Sstevel@tonic-gate char *p = sp->sc_cmd; /* working pointer */
6847c478bd9Sstevel@tonic-gate char delch; /* delimiter seen */
6857c478bd9Sstevel@tonic-gate char *savep; /* scratch pointer */
6867c478bd9Sstevel@tonic-gate char *tp; /* scratch pointer */
6877c478bd9Sstevel@tonic-gate
6887c478bd9Sstevel@tonic-gate *argvp = 0;
6897c478bd9Sstevel@tonic-gate savep = p;
6907c478bd9Sstevel@tonic-gate while (p && *p) {
6917c478bd9Sstevel@tonic-gate if (p = strpbrk(p, delim)) {
6927c478bd9Sstevel@tonic-gate switch (*p) {
6937c478bd9Sstevel@tonic-gate case ' ':
6947c478bd9Sstevel@tonic-gate case '\t':
6957c478bd9Sstevel@tonic-gate /* "normal" cases */
6967c478bd9Sstevel@tonic-gate *p++ = '\0';
6977c478bd9Sstevel@tonic-gate *argvp++ = savep;
6987c478bd9Sstevel@tonic-gate /* zap trailing white space */
6997c478bd9Sstevel@tonic-gate while (isspace(*p))
7007c478bd9Sstevel@tonic-gate p++;
7017c478bd9Sstevel@tonic-gate savep = p;
7027c478bd9Sstevel@tonic-gate break;
7037c478bd9Sstevel@tonic-gate case '"':
7047c478bd9Sstevel@tonic-gate case '\'':
7057c478bd9Sstevel@tonic-gate /* found a string */
7067c478bd9Sstevel@tonic-gate delch = *p; /* remember the delimiter */
7077c478bd9Sstevel@tonic-gate savep = ++p;
7087c478bd9Sstevel@tonic-gate
7097c478bd9Sstevel@tonic-gate /*
7107c478bd9Sstevel@tonic-gate * We work the string in place, embedded instances of the string delimiter,
7117c478bd9Sstevel@tonic-gate * i.e. \" must have the '\' removed. Since we'd have to do a compare to
7127c478bd9Sstevel@tonic-gate * decide if a copy were needed, it's less work to just do the copy, even
7137c478bd9Sstevel@tonic-gate * though it is most likely unnecessary.
7147c478bd9Sstevel@tonic-gate */
7157c478bd9Sstevel@tonic-gate
7167c478bd9Sstevel@tonic-gate tp = p;
7177c478bd9Sstevel@tonic-gate for (;;) {
7187c478bd9Sstevel@tonic-gate if (*p == '\0') {
7197c478bd9Sstevel@tonic-gate (void) sprintf(Scratch,
7207c478bd9Sstevel@tonic-gate "invalid command line, non-terminated string for port monitor %s",
7217c478bd9Sstevel@tonic-gate sp->sc_tag);
7227c478bd9Sstevel@tonic-gate log(Scratch);
7237c478bd9Sstevel@tonic-gate exit(1);
7247c478bd9Sstevel@tonic-gate }
7257c478bd9Sstevel@tonic-gate if (*p == delch) {
7267c478bd9Sstevel@tonic-gate if (*(tp - 1) == '\\') {
7277c478bd9Sstevel@tonic-gate /* \delim */
7287c478bd9Sstevel@tonic-gate *(tp - 1) = *p;
7297c478bd9Sstevel@tonic-gate p++;
7307c478bd9Sstevel@tonic-gate } else { /* end of string */
7317c478bd9Sstevel@tonic-gate *tp = 0;
7327c478bd9Sstevel@tonic-gate *argvp++ = savep;
7337c478bd9Sstevel@tonic-gate p++;
7347c478bd9Sstevel@tonic-gate /* zap trailing white space */
7357c478bd9Sstevel@tonic-gate while (isspace(*p))
7367c478bd9Sstevel@tonic-gate p++;
7377c478bd9Sstevel@tonic-gate savep = p;
7387c478bd9Sstevel@tonic-gate break;
7397c478bd9Sstevel@tonic-gate }
7407c478bd9Sstevel@tonic-gate } else {
7417c478bd9Sstevel@tonic-gate *tp++ = *p++;
7427c478bd9Sstevel@tonic-gate }
7437c478bd9Sstevel@tonic-gate }
7447c478bd9Sstevel@tonic-gate break;
7457c478bd9Sstevel@tonic-gate default:
7467c478bd9Sstevel@tonic-gate log("Internal error in parse routine");
7477c478bd9Sstevel@tonic-gate exit(1);
7487c478bd9Sstevel@tonic-gate }
7497c478bd9Sstevel@tonic-gate }
7507c478bd9Sstevel@tonic-gate else
7517c478bd9Sstevel@tonic-gate *argvp++ = savep;
7527c478bd9Sstevel@tonic-gate }
7537c478bd9Sstevel@tonic-gate *argvp = 0;
7547c478bd9Sstevel@tonic-gate return (newargv);
7557c478bd9Sstevel@tonic-gate }
7567c478bd9Sstevel@tonic-gate
7577c478bd9Sstevel@tonic-gate
7587c478bd9Sstevel@tonic-gate /*
7597c478bd9Sstevel@tonic-gate * pollpms - send out sanity polls, if sc_sstate and sc_pstate are
7607c478bd9Sstevel@tonic-gate * the same (everyone agrees on the state) or if SAC thinks PM
7617c478bd9Sstevel@tonic-gate * should be stopping, send out a status message;
7627c478bd9Sstevel@tonic-gate * otherwise, send out a message indicating the state the SAC
7637c478bd9Sstevel@tonic-gate * thinks the PM should be entering
7647c478bd9Sstevel@tonic-gate */
7657c478bd9Sstevel@tonic-gate
7667c478bd9Sstevel@tonic-gate void
pollpms()7677c478bd9Sstevel@tonic-gate pollpms()
7687c478bd9Sstevel@tonic-gate {
7697c478bd9Sstevel@tonic-gate struct sactab *sp; /* working pointer */
7707c478bd9Sstevel@tonic-gate struct sacmsg sacmsg; /* message to send to PM */
7717c478bd9Sstevel@tonic-gate
7727c478bd9Sstevel@tonic-gate #ifdef DEBUG
7737c478bd9Sstevel@tonic-gate debug("alarm went off");
7747c478bd9Sstevel@tonic-gate #endif
7757c478bd9Sstevel@tonic-gate for (sp = Sactab; sp; sp = sp->sc_next) {
7767c478bd9Sstevel@tonic-gate if (sp->sc_pstate == NOTRUNNING || sp->sc_pstate == FAILED) {
7777c478bd9Sstevel@tonic-gate /* don't bother if no one is home */
7787c478bd9Sstevel@tonic-gate continue;
7797c478bd9Sstevel@tonic-gate }
7807c478bd9Sstevel@tonic-gate if (sp->sc_ok == 0) {
7817c478bd9Sstevel@tonic-gate /* PM has stopped responding */
7827c478bd9Sstevel@tonic-gate pollfail(sp, RESP);
7837c478bd9Sstevel@tonic-gate continue;
7847c478bd9Sstevel@tonic-gate }
7857c478bd9Sstevel@tonic-gate
7867c478bd9Sstevel@tonic-gate /*
7877c478bd9Sstevel@tonic-gate * note - if we're in recovery, a SC_STATUS message is sent
7887c478bd9Sstevel@tonic-gate * (sc_sstate = UNKNOWN and sc_pstate = UNKNOWN)
7897c478bd9Sstevel@tonic-gate */
7907c478bd9Sstevel@tonic-gate
7917c478bd9Sstevel@tonic-gate if (sp->sc_sstate == sp->sc_pstate) {
7927c478bd9Sstevel@tonic-gate sacmsg.sc_type = SC_STATUS;
7937c478bd9Sstevel@tonic-gate sacmsg.sc_size = 0;
7947c478bd9Sstevel@tonic-gate } else {
7957c478bd9Sstevel@tonic-gate switch (sp->sc_sstate) {
7967c478bd9Sstevel@tonic-gate case ENABLED:
7977c478bd9Sstevel@tonic-gate sacmsg.sc_type = SC_ENABLE;
7987c478bd9Sstevel@tonic-gate sacmsg.sc_size = 0;
7997c478bd9Sstevel@tonic-gate break;
8007c478bd9Sstevel@tonic-gate case DISABLED:
8017c478bd9Sstevel@tonic-gate sacmsg.sc_type = SC_DISABLE;
8027c478bd9Sstevel@tonic-gate sacmsg.sc_size = 0;
8037c478bd9Sstevel@tonic-gate break;
8047c478bd9Sstevel@tonic-gate case STARTING:
8057c478bd9Sstevel@tonic-gate case STOPPING:
8067c478bd9Sstevel@tonic-gate case NOTRUNNING:
8077c478bd9Sstevel@tonic-gate case FAILED:
8087c478bd9Sstevel@tonic-gate case UNKNOWN:
8097c478bd9Sstevel@tonic-gate /*
8107c478bd9Sstevel@tonic-gate * if NOTRUNNING or FAILED, PM will probably
8117c478bd9Sstevel@tonic-gate * not respond to poll, that's how we detect
8127c478bd9Sstevel@tonic-gate * that it's gone
8137c478bd9Sstevel@tonic-gate */
8147c478bd9Sstevel@tonic-gate sacmsg.sc_type = SC_STATUS;
8157c478bd9Sstevel@tonic-gate sacmsg.sc_size = 0;
8167c478bd9Sstevel@tonic-gate break;
8177c478bd9Sstevel@tonic-gate default:
8187c478bd9Sstevel@tonic-gate error(E_BADSTATE, EXIT);
8197c478bd9Sstevel@tonic-gate }
8207c478bd9Sstevel@tonic-gate }
8217c478bd9Sstevel@tonic-gate
8227c478bd9Sstevel@tonic-gate /* send the message */
8237c478bd9Sstevel@tonic-gate sendpmmsg(sp, &sacmsg);
8247c478bd9Sstevel@tonic-gate sp->sc_ok = 0;
8257c478bd9Sstevel@tonic-gate }
8267c478bd9Sstevel@tonic-gate (void) alarm(Stime);
8277c478bd9Sstevel@tonic-gate }
8287c478bd9Sstevel@tonic-gate
8297c478bd9Sstevel@tonic-gate
8307c478bd9Sstevel@tonic-gate /*
8317c478bd9Sstevel@tonic-gate * reap - clean up dead children, equivalent to a "fast" poll failure
8327c478bd9Sstevel@tonic-gate *
8337c478bd9Sstevel@tonic-gate * args: signo - signal #
8347c478bd9Sstevel@tonic-gate */
8357c478bd9Sstevel@tonic-gate
8367c478bd9Sstevel@tonic-gate void
reap(int signo)8377c478bd9Sstevel@tonic-gate reap(int signo)
8387c478bd9Sstevel@tonic-gate {
8397c478bd9Sstevel@tonic-gate struct sactab *sp; /* working pointer */
8407c478bd9Sstevel@tonic-gate pid_t pid; /* returned pid from wait */
8417c478bd9Sstevel@tonic-gate int status; /* returned status from wait */
8427c478bd9Sstevel@tonic-gate
8437c478bd9Sstevel@tonic-gate pid = wait(&status);
8447c478bd9Sstevel@tonic-gate for (sp = Sactab; sp; sp = sp->sc_next) {
8457c478bd9Sstevel@tonic-gate if (sp->sc_pid == pid)
8467c478bd9Sstevel@tonic-gate break;
8477c478bd9Sstevel@tonic-gate }
8487c478bd9Sstevel@tonic-gate if (sp == NULL) {
8497c478bd9Sstevel@tonic-gate /* not from a port monitor we know about */
8507c478bd9Sstevel@tonic-gate return;
8517c478bd9Sstevel@tonic-gate }
8527c478bd9Sstevel@tonic-gate sp->sc_exit = status;
8537c478bd9Sstevel@tonic-gate /* only call pollfail for "stuck" and stopping processes */
8547c478bd9Sstevel@tonic-gate if (sp->sc_pstate != NOTRUNNING && sp->sc_pstate != FAILED)
8557c478bd9Sstevel@tonic-gate pollfail(sp, DEATH);
8567c478bd9Sstevel@tonic-gate }
8577c478bd9Sstevel@tonic-gate
8587c478bd9Sstevel@tonic-gate
8597c478bd9Sstevel@tonic-gate /*
8607c478bd9Sstevel@tonic-gate * pollfail - handle the case where a PM stops responding to a sanity poll
8617c478bd9Sstevel@tonic-gate *
8627c478bd9Sstevel@tonic-gate * args: sp - pointer to sac's port monitor information for
8637c478bd9Sstevel@tonic-gate * designated port monitor
8647c478bd9Sstevel@tonic-gate * reason - RESP or DEATH (indicates why pollfail called)
8657c478bd9Sstevel@tonic-gate */
8667c478bd9Sstevel@tonic-gate
8677c478bd9Sstevel@tonic-gate
8687c478bd9Sstevel@tonic-gate void
pollfail(struct sactab * sp,int reason)8697c478bd9Sstevel@tonic-gate pollfail(struct sactab *sp, int reason)
8707c478bd9Sstevel@tonic-gate {
8717c478bd9Sstevel@tonic-gate char buf[SIZE]; /* scratch buffer */
8727c478bd9Sstevel@tonic-gate sigset_t cset; /* for signal handling */
8737c478bd9Sstevel@tonic-gate sigset_t tset; /* for signal handling */
8747c478bd9Sstevel@tonic-gate
8757c478bd9Sstevel@tonic-gate #ifdef DEBUG
8767c478bd9Sstevel@tonic-gate debug("in pollfail");
8777c478bd9Sstevel@tonic-gate #endif
8787c478bd9Sstevel@tonic-gate
8797c478bd9Sstevel@tonic-gate /* first, remove the utmpx entry and clean up any links */
8807c478bd9Sstevel@tonic-gate
8817c478bd9Sstevel@tonic-gate cleanutx(sp);
8827c478bd9Sstevel@tonic-gate
8837c478bd9Sstevel@tonic-gate if (sp->sc_pstate == STOPPING) {
8847c478bd9Sstevel@tonic-gate (void) sprintf(buf, "<%s> has stopped", sp->sc_tag);
8857c478bd9Sstevel@tonic-gate log(buf);
8867c478bd9Sstevel@tonic-gate sp->sc_pstate = NOTRUNNING;
8877c478bd9Sstevel@tonic-gate sp->sc_lstate = NOTRUNNING;
8887c478bd9Sstevel@tonic-gate (void) close(sp->sc_fd);
8897c478bd9Sstevel@tonic-gate } else {
8907c478bd9Sstevel@tonic-gate
8917c478bd9Sstevel@tonic-gate /*
8927c478bd9Sstevel@tonic-gate * PM in trouble - if it's still there, try to put it out of its misery
8937c478bd9Sstevel@tonic-gate * We play with SIGCLD here to that after SIGKILL is sent, the catcher
8947c478bd9Sstevel@tonic-gate * routine reap() is not called until we're ready (note: when a catcher
8957c478bd9Sstevel@tonic-gate * is established for SIGCLD and any zombies are present, the signal is
8967c478bd9Sstevel@tonic-gate * immediately received)
8977c478bd9Sstevel@tonic-gate */
8987c478bd9Sstevel@tonic-gate
8997c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, NULL, &cset);
9007c478bd9Sstevel@tonic-gate tset = cset;
9017c478bd9Sstevel@tonic-gate (void) sigaddset(&tset, SIGCLD);
9027c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &tset, NULL);
9037c478bd9Sstevel@tonic-gate (void) sendsig(sp, SIGKILL);
9047c478bd9Sstevel@tonic-gate if (sp->sc_rscnt < sp->sc_rsmax) {
9057c478bd9Sstevel@tonic-gate /* try to restart it */
9067c478bd9Sstevel@tonic-gate if (reason == RESP)
9077c478bd9Sstevel@tonic-gate (void) sprintf(buf,
9087c478bd9Sstevel@tonic-gate "<%s> stopped responding to sanity polls - trying to restart",
9097c478bd9Sstevel@tonic-gate sp->sc_tag);
9107c478bd9Sstevel@tonic-gate else
9117c478bd9Sstevel@tonic-gate (void) sprintf(buf,
9127c478bd9Sstevel@tonic-gate "<%s> has died - trying to restart",
9137c478bd9Sstevel@tonic-gate sp->sc_tag);
9147c478bd9Sstevel@tonic-gate log(buf);
9157c478bd9Sstevel@tonic-gate sp->sc_rscnt++;
9167c478bd9Sstevel@tonic-gate (void) close(sp->sc_fd);
9177c478bd9Sstevel@tonic-gate (void) startpm(sp);
9187c478bd9Sstevel@tonic-gate } else {
9197c478bd9Sstevel@tonic-gate sp->sc_sstate = sp->sc_pstate = FAILED;
9207c478bd9Sstevel@tonic-gate (void) close(sp->sc_fd);
9217c478bd9Sstevel@tonic-gate (void) sprintf(buf, "<%s> has FAILED", sp->sc_tag);
9227c478bd9Sstevel@tonic-gate log(buf);
9237c478bd9Sstevel@tonic-gate }
9247c478bd9Sstevel@tonic-gate }
9257c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &cset, NULL);
9267c478bd9Sstevel@tonic-gate }
9277c478bd9Sstevel@tonic-gate
9287c478bd9Sstevel@tonic-gate
9297c478bd9Sstevel@tonic-gate /*
9307c478bd9Sstevel@tonic-gate * readpipe - read messages from _sacpipe
9317c478bd9Sstevel@tonic-gate */
9327c478bd9Sstevel@tonic-gate
9337c478bd9Sstevel@tonic-gate
9347c478bd9Sstevel@tonic-gate void
readpipe()9357c478bd9Sstevel@tonic-gate readpipe()
9367c478bd9Sstevel@tonic-gate {
9377c478bd9Sstevel@tonic-gate struct pmmsg pmmsg; /* incoming message */
9387c478bd9Sstevel@tonic-gate struct pmmsg *pp = &pmmsg; /* and a pointer to it */
9397c478bd9Sstevel@tonic-gate struct sactab *sp; /* working pointer */
9407c478bd9Sstevel@tonic-gate int ret; /* return value from read */
9417c478bd9Sstevel@tonic-gate
9427c478bd9Sstevel@tonic-gate /*
9437c478bd9Sstevel@tonic-gate * This routine's main purpose is to maintain the state associated with
9447c478bd9Sstevel@tonic-gate * each of the known port monitors. Because it may be confusing, following
9457c478bd9Sstevel@tonic-gate * is a brief discussion of what is happening. Three different views of
9467c478bd9Sstevel@tonic-gate * a port monitor's state exist: sc_sstate, sc_pstate, and sc_lstate.
9477c478bd9Sstevel@tonic-gate * sc_sstate is the state in which the sac has been instructed to place
9487c478bd9Sstevel@tonic-gate * a port monitor. sc_lstate is essentially a shadow of this field, however,
9497c478bd9Sstevel@tonic-gate * it will only take on the values ENABLED, DISABLED, and NOTRUNNING.
9507c478bd9Sstevel@tonic-gate * sc_lstate is used if a port monitor dies to restart it in the state in
9517c478bd9Sstevel@tonic-gate * which it was last running. sc_pstate is the last state that the port
9527c478bd9Sstevel@tonic-gate * monitor reported itself in. Note that if the administrator specifies
9537c478bd9Sstevel@tonic-gate * a state change, there is a window where sc_sstate and sc_pstate will
9547c478bd9Sstevel@tonic-gate * be different (until the port monitor enacts and acknowledges the change).
9557c478bd9Sstevel@tonic-gate *
9567c478bd9Sstevel@tonic-gate * These states interact with the polling loop to determine which message
9577c478bd9Sstevel@tonic-gate * should be sent to a port monitor. If the states agree, an SC_STATUS
9587c478bd9Sstevel@tonic-gate * is sent. If they disagree, the appropriate message to put the port
9597c478bd9Sstevel@tonic-gate * monitor in the correct state is sent (SC_ENABLE or SC_DISABLE). sc_pstate
9607c478bd9Sstevel@tonic-gate * is the state that is reported back to an AC_STATUS request. Finally,
9617c478bd9Sstevel@tonic-gate * when in recovery (sc_sstate and sc_pstate both = UNKNOWN), the sac will
9627c478bd9Sstevel@tonic-gate * take the port monitor's reported state as the true state. This is the
9637c478bd9Sstevel@tonic-gate * only instance in which a port monitor can cause sc_sstate to change.
9647c478bd9Sstevel@tonic-gate */
9657c478bd9Sstevel@tonic-gate
9667c478bd9Sstevel@tonic-gate for (;;) {
9677c478bd9Sstevel@tonic-gate if (read(Sfd, pp, sizeof (pmmsg)) < 0) {
9687c478bd9Sstevel@tonic-gate if (errno != EINTR)
9697c478bd9Sstevel@tonic-gate error(E_BADREAD, EXIT);
9707c478bd9Sstevel@tonic-gate continue;
9717c478bd9Sstevel@tonic-gate }
9727c478bd9Sstevel@tonic-gate
9737c478bd9Sstevel@tonic-gate while (pp->pm_size) {
9747c478bd9Sstevel@tonic-gate
9757c478bd9Sstevel@tonic-gate /*
9767c478bd9Sstevel@tonic-gate * there's data after the header, unfortunately, we don't understand
9777c478bd9Sstevel@tonic-gate * any of it because only class 1 (no data) messages are defined. Just
9787c478bd9Sstevel@tonic-gate * flush it
9797c478bd9Sstevel@tonic-gate */
9807c478bd9Sstevel@tonic-gate
9817c478bd9Sstevel@tonic-gate ret = read(Sfd, Scratch,
9827c478bd9Sstevel@tonic-gate (pp->pm_size > SIZE) ? (unsigned) SIZE :
9837c478bd9Sstevel@tonic-gate (unsigned) pp->pm_size);
9847c478bd9Sstevel@tonic-gate if (ret < 0) {
9857c478bd9Sstevel@tonic-gate if (errno != EINTR)
9867c478bd9Sstevel@tonic-gate error(E_BADREAD, EXIT);
9877c478bd9Sstevel@tonic-gate continue;
9887c478bd9Sstevel@tonic-gate }
9897c478bd9Sstevel@tonic-gate else
9907c478bd9Sstevel@tonic-gate pp->pm_size -= ret;
9917c478bd9Sstevel@tonic-gate }
9927c478bd9Sstevel@tonic-gate
9937c478bd9Sstevel@tonic-gate sp = findpm(pp->pm_tag);
9947c478bd9Sstevel@tonic-gate if (sp == NULL) {
9957c478bd9Sstevel@tonic-gate log("message from unknown process");
9967c478bd9Sstevel@tonic-gate continue;
9977c478bd9Sstevel@tonic-gate }
9987c478bd9Sstevel@tonic-gate switch (pp->pm_type) {
9997c478bd9Sstevel@tonic-gate case PM_UNKNOWN:
10007c478bd9Sstevel@tonic-gate (void) sprintf(Scratch,
10017c478bd9Sstevel@tonic-gate "port monitor <%s> didn't recognize message",
10027c478bd9Sstevel@tonic-gate sp->sc_tag);
10037c478bd9Sstevel@tonic-gate log(Scratch);
10047c478bd9Sstevel@tonic-gate /* fall through */
10057c478bd9Sstevel@tonic-gate case PM_STATUS:
10067c478bd9Sstevel@tonic-gate /*
10077c478bd9Sstevel@tonic-gate * paranoia check, if port monitor reports garbage
10087c478bd9Sstevel@tonic-gate * state, pretend it said UNKNOWN
10097c478bd9Sstevel@tonic-gate */
10107c478bd9Sstevel@tonic-gate if (!validstate(pp->pm_state)) {
10117c478bd9Sstevel@tonic-gate pp->pm_state = UNKNOWN;
10127c478bd9Sstevel@tonic-gate (void) sprintf(Scratch,
10137c478bd9Sstevel@tonic-gate "port monitor <%s> reporting invalid state",
10147c478bd9Sstevel@tonic-gate sp->sc_tag);
10157c478bd9Sstevel@tonic-gate log(Scratch);
10167c478bd9Sstevel@tonic-gate }
10177c478bd9Sstevel@tonic-gate if (sp->sc_sstate == sp->sc_pstate) {
10187c478bd9Sstevel@tonic-gate /* everyone agrees on the current state */
10197c478bd9Sstevel@tonic-gate if (sp->sc_sstate == UNKNOWN) {
10207c478bd9Sstevel@tonic-gate /* special case for recovery */
10217c478bd9Sstevel@tonic-gate sp->sc_sstate = pp->pm_state;
10227c478bd9Sstevel@tonic-gate sp->sc_pstate = pp->pm_state;
10237c478bd9Sstevel@tonic-gate if (pp->pm_state == ENABLED ||
10247c478bd9Sstevel@tonic-gate pp->pm_state == DISABLED)
10257c478bd9Sstevel@tonic-gate /* sc_lstate NOTRUNNING by default */
10267c478bd9Sstevel@tonic-gate sp->sc_lstate = pp->pm_state;
10277c478bd9Sstevel@tonic-gate }
10287c478bd9Sstevel@tonic-gate if (pp->pm_state != sp->sc_pstate) {
10297c478bd9Sstevel@tonic-gate /*
10307c478bd9Sstevel@tonic-gate * something isn't right here, PM
10317c478bd9Sstevel@tonic-gate * changed state without orders, try
10327c478bd9Sstevel@tonic-gate * to restore to correct state
10337c478bd9Sstevel@tonic-gate */
10347c478bd9Sstevel@tonic-gate sp->sc_pstate = pp->pm_state;
10357c478bd9Sstevel@tonic-gate }
10367c478bd9Sstevel@tonic-gate } else if (sp->sc_sstate == pp->pm_state) {
10377c478bd9Sstevel@tonic-gate /* PM changed to state requested */
10387c478bd9Sstevel@tonic-gate (void) sprintf(Scratch,
10397c478bd9Sstevel@tonic-gate "port monitor <%s> changed state from %s to %s",
10407c478bd9Sstevel@tonic-gate sp->sc_tag, pstate(sp->sc_pstate),
10417c478bd9Sstevel@tonic-gate pstate(pp->pm_state));
10427c478bd9Sstevel@tonic-gate log(Scratch);
10437c478bd9Sstevel@tonic-gate sp->sc_pstate = pp->pm_state;
10447c478bd9Sstevel@tonic-gate } else if (sp->sc_pstate != pp->pm_state) {
10457c478bd9Sstevel@tonic-gate /*
10467c478bd9Sstevel@tonic-gate * something isn't right here, PM isn't
10477c478bd9Sstevel@tonic-gate * in the state it was, nor is it in the
10487c478bd9Sstevel@tonic-gate * state we just tried to put it in, try
10497c478bd9Sstevel@tonic-gate * to restore to correct state if we should
10507c478bd9Sstevel@tonic-gate */
10517c478bd9Sstevel@tonic-gate if (sp->sc_pstate != STOPPING)
10527c478bd9Sstevel@tonic-gate sp->sc_pstate = pp->pm_state;
10537c478bd9Sstevel@tonic-gate }
10547c478bd9Sstevel@tonic-gate break;
10557c478bd9Sstevel@tonic-gate default:
10567c478bd9Sstevel@tonic-gate (void) sprintf(Scratch,
10577c478bd9Sstevel@tonic-gate "port monitor <%s> sent an invalid message - ignoring it",
10587c478bd9Sstevel@tonic-gate sp->sc_tag);
10597c478bd9Sstevel@tonic-gate log(Scratch);
10607c478bd9Sstevel@tonic-gate break;
10617c478bd9Sstevel@tonic-gate }
10627c478bd9Sstevel@tonic-gate /* no matter what, PM did answer the poll */
10637c478bd9Sstevel@tonic-gate sp->sc_ok = 1;
10647c478bd9Sstevel@tonic-gate /* Note the messages it understands */
10657c478bd9Sstevel@tonic-gate sp->sc_maxclass = pp->pm_maxclass;
10667c478bd9Sstevel@tonic-gate }
10677c478bd9Sstevel@tonic-gate }
10687c478bd9Sstevel@tonic-gate
10697c478bd9Sstevel@tonic-gate
10707c478bd9Sstevel@tonic-gate /*
10717c478bd9Sstevel@tonic-gate * validstate - determine if arg s a valid return state from a port monitor
10727c478bd9Sstevel@tonic-gate * return 1 if ok, 0 otherwise
10737c478bd9Sstevel@tonic-gate *
10747c478bd9Sstevel@tonic-gate * args: state - state to be verified
10757c478bd9Sstevel@tonic-gate */
10767c478bd9Sstevel@tonic-gate int
validstate(unchar state)10777c478bd9Sstevel@tonic-gate validstate(unchar state)
10787c478bd9Sstevel@tonic-gate {
10797c478bd9Sstevel@tonic-gate switch (state) {
10807c478bd9Sstevel@tonic-gate case PM_ENABLED:
10817c478bd9Sstevel@tonic-gate case PM_DISABLED:
10827c478bd9Sstevel@tonic-gate case PM_STARTING:
10837c478bd9Sstevel@tonic-gate case PM_STOPPING:
10847c478bd9Sstevel@tonic-gate return (1);
10857c478bd9Sstevel@tonic-gate default:
10867c478bd9Sstevel@tonic-gate return (0);
10877c478bd9Sstevel@tonic-gate }
10887c478bd9Sstevel@tonic-gate }
10897c478bd9Sstevel@tonic-gate
10907c478bd9Sstevel@tonic-gate
10917c478bd9Sstevel@tonic-gate /*
10927c478bd9Sstevel@tonic-gate * mk_cmd_pipe - create the command pipe used by sacadm
10937c478bd9Sstevel@tonic-gate */
10947c478bd9Sstevel@tonic-gate
10957c478bd9Sstevel@tonic-gate int
mk_cmd_pipe()10967c478bd9Sstevel@tonic-gate mk_cmd_pipe()
10977c478bd9Sstevel@tonic-gate {
10987c478bd9Sstevel@tonic-gate int fds[2]; /* pipe endpoints */
10997c478bd9Sstevel@tonic-gate int fd; /* scratch file descriptor */
11007c478bd9Sstevel@tonic-gate
11017c478bd9Sstevel@tonic-gate /* make sure there is a file here to mount on */
11027c478bd9Sstevel@tonic-gate (void) unlink(CMDPIPE);
11037c478bd9Sstevel@tonic-gate fd = open(CMDPIPE, O_RDWR | O_CREAT, 0600);
11047c478bd9Sstevel@tonic-gate if (fd < 0)
11057c478bd9Sstevel@tonic-gate error(E_CMDPIPE, EXIT);
11067c478bd9Sstevel@tonic-gate close(fd);
11077c478bd9Sstevel@tonic-gate if (pipe(fds) < 0)
11087c478bd9Sstevel@tonic-gate error(E_PIPE, EXIT);
11097c478bd9Sstevel@tonic-gate if (fattach(fds[0], CMDPIPE) < 0)
11107c478bd9Sstevel@tonic-gate error(E_FATTACH, EXIT);
11117c478bd9Sstevel@tonic-gate return (fds[1]);
11127c478bd9Sstevel@tonic-gate }
11137c478bd9Sstevel@tonic-gate
11147c478bd9Sstevel@tonic-gate
11157c478bd9Sstevel@tonic-gate /*
11167c478bd9Sstevel@tonic-gate * startpoll - enable polling on command pipe by setting up to catch SIGPOLL
11177c478bd9Sstevel@tonic-gate */
11187c478bd9Sstevel@tonic-gate
11197c478bd9Sstevel@tonic-gate
11207c478bd9Sstevel@tonic-gate void
startpoll()11217c478bd9Sstevel@tonic-gate startpoll()
11227c478bd9Sstevel@tonic-gate {
11237c478bd9Sstevel@tonic-gate struct sigaction sigact; /* for signal handling */
11247c478bd9Sstevel@tonic-gate
11257c478bd9Sstevel@tonic-gate if (ioctl(Cfd, I_SETSIG, S_INPUT) < 0)
11267c478bd9Sstevel@tonic-gate error(E_SETSIG, EXIT);
11277c478bd9Sstevel@tonic-gate sigact.sa_flags = 0;
11287c478bd9Sstevel@tonic-gate sigact.sa_handler = sigpoll;
11297c478bd9Sstevel@tonic-gate (void) sigemptyset(&sigact.sa_mask);
11307c478bd9Sstevel@tonic-gate (void) sigaddset(&sigact.sa_mask, SIGPOLL);
11317c478bd9Sstevel@tonic-gate (void) sigaction(SIGPOLL, &sigact, &Sigpoll);
11327c478bd9Sstevel@tonic-gate }
1133