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