4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
26 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
30 #pragma ident "%Z%%M% %I% %E% SMI"
39 #include <sys/types.h>
41 #include <sys/stropts.h>
52 #include <security/pam_appl.h>
54 #define RESP 1 /* pollfail via no response to sanity poll */
55 #define DEATH 2 /* pollfail via child death */
57 /* signal whose dispositions will be changed */
59 static struct sigaction Sigpoll
; /* SIGPOLL */
60 static struct sigaction Sigcld
; /* SIGCLD */
61 static struct sigaction Sigalrm
; /* SIGALRM */
62 static sigset_t Origmask
; /* original signal mask */
65 void initialize(void);
68 int startpm(struct sactab
*);
69 void cleanutx(struct sactab
*);
70 void account(struct sactab
*, pid_t
);
71 void startit(struct sactab
*);
72 char **mkargv(struct sactab
*);
75 void pollfail(struct sactab
*, int);
77 int validstate(unchar
);
78 int mk_cmd_pipe(void);
84 * main - scan args for sac, initialize everything, and wait for commands
85 * from sacadm via the command pipe
89 main(int argc
, char *argv
[])
91 int c
; /* place to hold options */
92 struct sigaction sigact
; /* for signal handling */
94 (void) sigprocmask(SIG_SETMASK
, NULL
, &Origmask
);
98 while ((c
= getopt(argc
, argv
, "t:")) != -1) {
103 Stime
= atoi(optarg
);
116 sigact
.sa_handler
= pollpms
;
117 (void) sigemptyset(&sigact
.sa_mask
);
118 (void) sigaddset(&sigact
.sa_mask
, SIGALRM
);
119 (void) sigaction(SIGALRM
, &sigact
, &Sigalrm
);
122 * minimize time spent in STARTING or UNKNOWN, pollpms() sets alarm
132 * usage - output a usage message on the console
138 FILE *fp
; /* scratch file pointer */
140 fp
= fopen("/dev/console", "w");
142 (void) fprintf(fp
, "SAC: Usage: sac -t sanity_interval\n");
148 * initialize - initialization stuff
155 int ret
; /* return code from doconfig() */
156 struct sigaction sigact
; /* for signal handling */
159 log("*** SAC starting ***");
162 log("Debugging turned on");
165 error(E_CHDIR
, EXIT
);
168 * pass an invalid fd, shouldn't be doing pushes and pops in this per-system
169 * configuration script (_sysconfig)
172 if ((ret
= doconfig(-1, SYSCONFIG
, 0)) != 0) {
174 error(E_SYSCONF
, EXIT
);
176 (void) sprintf(Scratch
,
177 "Error in _sysconfig: line %d", ret
);
179 error(E_BADSYSCONF
, EXIT
);
184 sigact
.sa_handler
= reap
;
185 (void) sigemptyset(&sigact
.sa_mask
);
186 (void) sigaddset(&sigact
.sa_mask
, SIGCLD
);
187 (void) sigaction(SIGCLD
, &sigact
, &Sigcld
);
190 * establish pipe for PMS to communicate with sac
193 if (access("_sacpipe", 0) != 0) {
194 /* not there, create one */
196 if (mknod("_sacpipe", S_IFIFO
| 0600, 0) < 0)
197 error(E_NOPIPE
, EXIT
);
199 Sfd
= open("_sacpipe", O_RDWR
);
201 error(E_NOPIPE
, EXIT
);
204 * establish pipe for sacadm to communicate with sac
210 * read in _sactab, but don't start port monitors as a by-product
211 * since we may be in recovery - start them explicitly instead
221 * startpms - start initial set of port monitors
228 struct sactab
*sp
; /* working pointer */
229 int rflag
; /* recovery flag */
233 * check to see if we're really a recovering SAC (if any port monitors hold
234 * locks, assume that we're in recovery), if so, start differently
238 for (sp
= Sactab
; sp
; sp
= sp
->sc_next
) {
241 sp
->sc_sstate
= sp
->sc_pstate
= UNKNOWN
;
244 (void) sprintf(Scratch
, "%s/_pmpipe", sp
->sc_tag
);
245 sp
->sc_fd
= open(Scratch
, O_RDWR
);
249 * if we get into here, we're in deep trouble. PM seems to be running
250 * and we're trying to recover, but we can't talk to it. Unfortunately,
251 * there's not much that can be done other than to try and restore a
252 * sane state. By setting sp->sc_ok to 0, this will look like a poll failure
253 * and if sp->rs_rsmax > 0, PM will be restarted.
256 (void) sprintf(Scratch
,
257 "Could not open _pmpipe for port monitor <%s>",
260 (void) sendsig(sp
, SIGTERM
);
267 log("SAC in recovery");
275 for (sp
= Sactab
; sp
; sp
= sp
->sc_next
) {
276 if (sp
->sc_flags
& X_FLAG
) {
277 /* System Administator specified don't start */
286 * readutmpx - read the utmpx file to find out the ids of running port
287 * monitors (only called during a recover start up). Note:
288 * after a sac failure, init will inherit all of the port
289 * monitors and should get the SIGCLD's if they die (and
290 * will clean up). This is mainly for stuck processes,
291 * although init would get the SIGCLD when the stuckie gets
292 * killed, it doesn't hurt to have the sac check. This is
301 struct sactab
*sp
; /* working pointer */
302 struct sactab
*savesp
; /* rembered port monitor match */
303 struct utmpx
*uxp
; /* working pointer */
306 while (uxp
= getutxent()) {
307 /* we're only interested in login processes */
308 if (uxp
->ut_type
!= LOGIN_PROCESS
)
310 if (uxp
->ut_user
[sizeof (uxp
->ut_user
) - 1] == '\0') {
313 * possible port monitor and name is short enough to do a normal compare
316 sp
= findpm(uxp
->ut_user
);
317 if (sp
&& (sp
->sc_sstate
== UNKNOWN
)) {
319 (void) memcpy(sp
->sc_utid
, uxp
->ut_id
, IDLEN
);
320 sp
->sc_pid
= uxp
->ut_pid
;
325 * possible port monitor name, but it could have been truncated. If
326 * a match is found on a unique prefix, then it should be the correct
327 * entry. If an ambiguity is found, ignore the entry, init will clean
328 * up the entry if it dies.
332 for (sp
= Sactab
; sp
; sp
= sp
->sc_next
) {
333 if (strncmp(uxp
->ut_user
, sp
->sc_tag
,
334 sizeof (uxp
->ut_user
)) == 0) {
336 /* already found a match */
338 (void) sprintf(Scratch
,
339 "ambiguous utmpx entry <%.8s>",
348 if (savesp
&& (savesp
->sc_sstate
== UNKNOWN
)) {
350 (void) memcpy(savesp
->sc_utid
, uxp
->ut_id
,
352 savesp
->sc_pid
= uxp
->ut_pid
;
361 * startpm - start a particular PM, return code:
362 * -1: _pid file locked
363 * -2: any other reason
365 * args: sp - pointer to sac's port monitor information for
366 * designated port monitor
370 startpm(struct sactab
*sp
)
372 sigset_t cset
; /* for signal handling */
373 sigset_t tset
; /* for signal handling */
374 pid_t pid
; /* pid of new port monitor */
381 (void) sprintf(Scratch
,
382 "could not start <%s> - _pid file locked", sp
->sc_tag
);
387 (void) sprintf(Scratch
, "%s/_pmpipe", sp
->sc_tag
);
388 if (access(Scratch
, 0) != 0) {
389 /* not there, create one */
391 if (mknod(Scratch
, S_IFIFO
| 0600, 0) < 0) {
392 (void) sprintf(Scratch
,
393 "Could not create _pmpipe for port monitor <%s>, errno is %d",
399 sp
->sc_fd
= open(Scratch
, O_RDWR
);
401 (void) sprintf(Scratch
,
402 "Could not open _pmpipe for port monitor <%s>, errno is %d",
408 /* in case child dies too quickly */
409 (void) sigprocmask(SIG_SETMASK
, NULL
, &cset
);
411 (void) sigaddset(&tset
, SIGCLD
);
412 (void) sigprocmask(SIG_SETMASK
, &tset
, NULL
);
413 if ((pid
= fork()) < 0) {
414 (void) sprintf(Scratch
,
415 "Could not fork port monitor <%s>", sp
->sc_tag
);
424 * clean up old utmpx if its there
430 * create a utmpx entry and set initial states
434 sp
->sc_pstate
= STARTING
;
435 if (sp
->sc_lstate
== NOTRUNNING
)
436 sp
->sc_sstate
= (sp
->sc_flags
& D_FLAG
) ? DISABLED
: ENABLED
;
438 sp
->sc_sstate
= sp
->sc_lstate
;
442 /* ok to take signals now that the table is up-to-table */
443 (void) sigprocmask(SIG_SETMASK
, &cset
, NULL
);
449 * cleanutx - clean out a utmpx record for a port monitor
451 * args: sp - pointer to sac's port monitor information for
452 * designated port monitor
457 cleanutx(struct sactab
*sp
)
459 int i
; /* scratch variable */
460 int zerocheck
; /* scratch variable */
461 char buf
[SIZE
]; /* scratch buffer */
462 pam_handle_t
*pamh
; /* PAM auth descriptor */
466 char user
[sizeof (up
->ut_user
) + 1];
467 char ttyn
[sizeof (up
->ut_line
) + 1];
468 char rhost
[sizeof (up
->ut_host
) + 1];
470 * check to see if there is a utmpx entry to clean up (indicated by a non
474 for (i
= 0; i
< IDLEN
; ++i
) {
475 zerocheck
+= sp
->sc_utid
[i
];
482 while (up
= getutxent()) {
483 if (up
->ut_pid
== pid
) {
484 if (up
->ut_type
== DEAD_PROCESS
) {
486 * Cleaned up elsewhere.
490 strncpy(user
, up
->ut_user
, sizeof (up
->ut_user
));
491 user
[sizeof (up
->ut_user
)] = '\0';
492 strncpy(ttyn
, up
->ut_line
, sizeof (up
->ut_line
));
493 ttyn
[sizeof (up
->ut_line
)] = '\0';
494 strncpy(rhost
, up
->ut_host
, sizeof (up
->ut_host
));
495 rhost
[sizeof (up
->ut_host
)] = '\0';
497 if ((pam_start("sac", user
, NULL
, &pamh
)) ==
499 (void) pam_set_item(pamh
, PAM_TTY
, ttyn
);
500 (void) pam_set_item(pamh
, PAM_RHOST
, rhost
);
501 (void) pam_close_session(pamh
, 0);
502 pam_end(pamh
, PAM_SUCCESS
);
505 up
->ut_type
= DEAD_PROCESS
;
506 up
->ut_exit
.e_termination
= WTERMSIG(sp
->sc_exit
);
507 up
->ut_exit
.e_exit
= WEXITSTATUS(sp
->sc_exit
);
508 if (sp
->sc_utid
!= NULL
)
509 (void) memcpy(up
->ut_id
, sp
->sc_utid
,
511 (void) time(&up
->ut_tv
.tv_sec
);
512 if (modutx(up
) == NULL
) {
514 * Since modutx failed we'll
515 * write out the new entry
518 (void) pututxline(up
);
519 updwtmpx("wtmpx", up
);
528 * account - create a utmp record for a port monitor
530 * args: pid - process id of port monitor
535 account(struct sactab
*sp
, pid_t pid
)
537 struct utmpx utmpx
; /* prototype utmpx entry */
538 struct utmpx
*up
= &utmpx
; /* and a pointer to it */
540 (void) memset(up
, '\0', sizeof (utmpx
));
541 (void) strncpy(up
->ut_user
, sp
->sc_tag
, sizeof (up
->ut_user
));
543 up
->ut_type
= LOGIN_PROCESS
;
546 up
->ut_id
[2] = SC_WILDC
;
547 up
->ut_id
[3] = SC_WILDC
;
548 (void) time(&up
->ut_xtime
);
549 if (makeutx(up
) == NULL
) {
550 log("Could not create utmpx entry");
551 (void) memset(sp
->sc_utid
, '\0', IDLEN
);
553 (void) memcpy(sp
->sc_utid
, up
->ut_id
, IDLEN
);
559 * startit - finish starting a particular port monitor, establish environment,
560 * etc. (Note: this is the child at this point)
562 * args: sp - pointer to sac's port monitor information for
563 * designated port monitor
568 startit(struct sactab
*sp
)
570 static char istate
[SIZE
]; /* place to put ISTATE env var. */
571 static char pmtag
[SIZE
]; /* place to put PMTAG env var. */
572 char **argvp
; /* arglist for PM */
573 int i
; /* loop control variable */
574 long ndesc
; /* # of file descriptors configured */
575 int ret
; /* return value from doconfig */
576 sigset_t cset
; /* for signal handling */
577 sigset_t tset
; /* for signal handling */
580 * establish the home directory
583 if (chdir(sp
->sc_tag
) < 0) {
584 (void) sprintf(Scratch
,
585 "Cannot chdir to <%s/%s>, port monitor not started",
592 * interpret the configuration script, pass an invalid fd, shouldn't be
593 * doing pushes and pops in this script
596 (void) sigprocmask(SIG_SETMASK
, NULL
, &cset
);
598 (void) sigaddset(&tset
, SIGCLD
);
599 (void) sigprocmask(SIG_SETMASK
, &tset
, NULL
);
600 if ((ret
= doconfig(-1, "_config", 0)) != 0) {
602 (void) sprintf(Scratch
,
603 "system error in _config script for <%s>",
608 (void) sprintf(Scratch
,
609 "Error in _config script for <%s>: line %d",
617 * add the promised environment variables
620 if (sp
->sc_lstate
== NOTRUNNING
)
621 (void) sprintf(istate
, "ISTATE=%s",
622 (sp
->sc_flags
& D_FLAG
) ? "disabled" : "enabled");
624 (void) sprintf(istate
, "ISTATE=%s",
625 (sp
->sc_lstate
== DISABLED
) ? "disabled" : "enabled");
626 if (putenv(istate
)) {
627 (void) sprintf(Scratch
,
628 "can't expand port monitor <%s> environment",
633 (void) sprintf(pmtag
, "PMTAG=%s", sp
->sc_tag
);
635 (void) sprintf(Scratch
,
636 "can't expand port monitor <%s> environment",
648 (void) sprintf(Scratch
, "starting port monitor <%s>", sp
->sc_tag
);
650 ndesc
= ulimit(4, 0L);
651 for (i
= 0; i
< ndesc
; i
++)
652 (void) fcntl(i
, F_SETFD
, 1);
653 /* restore orignal handlers and mask */
654 (void) sigaction(SIGPOLL
, &Sigpoll
, NULL
);
655 (void) sigaction(SIGCLD
, &Sigcld
, NULL
);
656 (void) sigaction(SIGALRM
, &Sigalrm
, NULL
);
657 (void) sigprocmask(SIG_SETMASK
, &Origmask
, NULL
);
658 (void) execve(argvp
[0], argvp
, environ
);
659 (void) sprintf(Scratch
, "exec of port monitor <%s> failed", sp
->sc_tag
);
666 * mkargv - Given a pointer to a struct sactab, construct argv
667 * for an exec system call.
669 * args: sp - pointer to sac's port monitor information for
670 * designated port montior
674 #define NARGS 50 /* max # of args */
676 static char *newargv
[NARGS
]; /* place for argv list */
677 static char *delim
= " \t'\""; /* delimiter list */
680 mkargv(struct sactab
*sp
)
682 char **argvp
= newargv
; /* scratch pointer */
683 char *p
= sp
->sc_cmd
; /* working pointer */
684 char delch
; /* delimiter seen */
685 char *savep
; /* scratch pointer */
686 char *tp
; /* scratch pointer */
691 if (p
= strpbrk(p
, delim
)) {
698 /* zap trailing white space */
706 delch
= *p
; /* remember the delimiter */
710 * We work the string in place, embedded instances of the string delimiter,
711 * i.e. \" must have the '\' removed. Since we'd have to do a compare to
712 * decide if a copy were needed, it's less work to just do the copy, even
713 * though it is most likely unnecessary.
719 (void) sprintf(Scratch
,
720 "invalid command line, non-terminated string for port monitor %s",
726 if (*(tp
- 1) == '\\') {
730 } else { /* end of string */
734 /* zap trailing white space */
746 log("Internal error in parse routine");
759 * pollpms - send out sanity polls, if sc_sstate and sc_pstate are
760 * the same (everyone agrees on the state) or if SAC thinks PM
761 * should be stopping, send out a status message;
762 * otherwise, send out a message indicating the state the SAC
763 * thinks the PM should be entering
769 struct sactab
*sp
; /* working pointer */
770 struct sacmsg sacmsg
; /* message to send to PM */
773 debug("alarm went off");
775 for (sp
= Sactab
; sp
; sp
= sp
->sc_next
) {
776 if (sp
->sc_pstate
== NOTRUNNING
|| sp
->sc_pstate
== FAILED
) {
777 /* don't bother if no one is home */
780 if (sp
->sc_ok
== 0) {
781 /* PM has stopped responding */
787 * note - if we're in recovery, a SC_STATUS message is sent
788 * (sc_sstate = UNKNOWN and sc_pstate = UNKNOWN)
791 if (sp
->sc_sstate
== sp
->sc_pstate
) {
792 sacmsg
.sc_type
= SC_STATUS
;
795 switch (sp
->sc_sstate
) {
797 sacmsg
.sc_type
= SC_ENABLE
;
801 sacmsg
.sc_type
= SC_DISABLE
;
810 * if NOTRUNNING or FAILED, PM will probably
811 * not respond to poll, that's how we detect
814 sacmsg
.sc_type
= SC_STATUS
;
818 error(E_BADSTATE
, EXIT
);
822 /* send the message */
823 sendpmmsg(sp
, &sacmsg
);
831 * reap - clean up dead children, equivalent to a "fast" poll failure
833 * args: signo - signal #
839 struct sactab
*sp
; /* working pointer */
840 pid_t pid
; /* returned pid from wait */
841 int status
; /* returned status from wait */
844 for (sp
= Sactab
; sp
; sp
= sp
->sc_next
) {
845 if (sp
->sc_pid
== pid
)
849 /* not from a port monitor we know about */
852 sp
->sc_exit
= status
;
853 /* only call pollfail for "stuck" and stopping processes */
854 if (sp
->sc_pstate
!= NOTRUNNING
&& sp
->sc_pstate
!= FAILED
)
860 * pollfail - handle the case where a PM stops responding to a sanity poll
862 * args: sp - pointer to sac's port monitor information for
863 * designated port monitor
864 * reason - RESP or DEATH (indicates why pollfail called)
869 pollfail(struct sactab
*sp
, int reason
)
871 char buf
[SIZE
]; /* scratch buffer */
872 sigset_t cset
; /* for signal handling */
873 sigset_t tset
; /* for signal handling */
876 debug("in pollfail");
879 /* first, remove the utmpx entry and clean up any links */
883 if (sp
->sc_pstate
== STOPPING
) {
884 (void) sprintf(buf
, "<%s> has stopped", sp
->sc_tag
);
886 sp
->sc_pstate
= NOTRUNNING
;
887 sp
->sc_lstate
= NOTRUNNING
;
888 (void) close(sp
->sc_fd
);
892 * PM in trouble - if it's still there, try to put it out of its misery
893 * We play with SIGCLD here to that after SIGKILL is sent, the catcher
894 * routine reap() is not called until we're ready (note: when a catcher
895 * is established for SIGCLD and any zombies are present, the signal is
896 * immediately received)
899 (void) sigprocmask(SIG_SETMASK
, NULL
, &cset
);
901 (void) sigaddset(&tset
, SIGCLD
);
902 (void) sigprocmask(SIG_SETMASK
, &tset
, NULL
);
903 (void) sendsig(sp
, SIGKILL
);
904 if (sp
->sc_rscnt
< sp
->sc_rsmax
) {
905 /* try to restart it */
908 "<%s> stopped responding to sanity polls - trying to restart",
912 "<%s> has died - trying to restart",
916 (void) close(sp
->sc_fd
);
919 sp
->sc_sstate
= sp
->sc_pstate
= FAILED
;
920 (void) close(sp
->sc_fd
);
921 (void) sprintf(buf
, "<%s> has FAILED", sp
->sc_tag
);
925 (void) sigprocmask(SIG_SETMASK
, &cset
, NULL
);
930 * readpipe - read messages from _sacpipe
937 struct pmmsg pmmsg
; /* incoming message */
938 struct pmmsg
*pp
= &pmmsg
; /* and a pointer to it */
939 struct sactab
*sp
; /* working pointer */
940 int ret
; /* return value from read */
943 * This routine's main purpose is to maintain the state associated with
944 * each of the known port monitors. Because it may be confusing, following
945 * is a brief discussion of what is happening. Three different views of
946 * a port monitor's state exist: sc_sstate, sc_pstate, and sc_lstate.
947 * sc_sstate is the state in which the sac has been instructed to place
948 * a port monitor. sc_lstate is essentially a shadow of this field, however,
949 * it will only take on the values ENABLED, DISABLED, and NOTRUNNING.
950 * sc_lstate is used if a port monitor dies to restart it in the state in
951 * which it was last running. sc_pstate is the last state that the port
952 * monitor reported itself in. Note that if the administrator specifies
953 * a state change, there is a window where sc_sstate and sc_pstate will
954 * be different (until the port monitor enacts and acknowledges the change).
956 * These states interact with the polling loop to determine which message
957 * should be sent to a port monitor. If the states agree, an SC_STATUS
958 * is sent. If they disagree, the appropriate message to put the port
959 * monitor in the correct state is sent (SC_ENABLE or SC_DISABLE). sc_pstate
960 * is the state that is reported back to an AC_STATUS request. Finally,
961 * when in recovery (sc_sstate and sc_pstate both = UNKNOWN), the sac will
962 * take the port monitor's reported state as the true state. This is the
963 * only instance in which a port monitor can cause sc_sstate to change.
967 if (read(Sfd
, pp
, sizeof (pmmsg
)) < 0) {
969 error(E_BADREAD
, EXIT
);
973 while (pp
->pm_size
) {
976 * there's data after the header, unfortunately, we don't understand
977 * any of it because only class 1 (no data) messages are defined. Just
981 ret
= read(Sfd
, Scratch
,
982 (pp
->pm_size
> SIZE
) ? (unsigned) SIZE
:
983 (unsigned) pp
->pm_size
);
986 error(E_BADREAD
, EXIT
);
993 sp
= findpm(pp
->pm_tag
);
995 log("message from unknown process");
998 switch (pp
->pm_type
) {
1000 (void) sprintf(Scratch
,
1001 "port monitor <%s> didn't recognize message",
1007 * paranoia check, if port monitor reports garbage
1008 * state, pretend it said UNKNOWN
1010 if (!validstate(pp
->pm_state
)) {
1011 pp
->pm_state
= UNKNOWN
;
1012 (void) sprintf(Scratch
,
1013 "port monitor <%s> reporting invalid state",
1017 if (sp
->sc_sstate
== sp
->sc_pstate
) {
1018 /* everyone agrees on the current state */
1019 if (sp
->sc_sstate
== UNKNOWN
) {
1020 /* special case for recovery */
1021 sp
->sc_sstate
= pp
->pm_state
;
1022 sp
->sc_pstate
= pp
->pm_state
;
1023 if (pp
->pm_state
== ENABLED
||
1024 pp
->pm_state
== DISABLED
)
1025 /* sc_lstate NOTRUNNING by default */
1026 sp
->sc_lstate
= pp
->pm_state
;
1028 if (pp
->pm_state
!= sp
->sc_pstate
) {
1030 * something isn't right here, PM
1031 * changed state without orders, try
1032 * to restore to correct state
1034 sp
->sc_pstate
= pp
->pm_state
;
1036 } else if (sp
->sc_sstate
== pp
->pm_state
) {
1037 /* PM changed to state requested */
1038 (void) sprintf(Scratch
,
1039 "port monitor <%s> changed state from %s to %s",
1040 sp
->sc_tag
, pstate(sp
->sc_pstate
),
1041 pstate(pp
->pm_state
));
1043 sp
->sc_pstate
= pp
->pm_state
;
1044 } else if (sp
->sc_pstate
!= pp
->pm_state
) {
1046 * something isn't right here, PM isn't
1047 * in the state it was, nor is it in the
1048 * state we just tried to put it in, try
1049 * to restore to correct state if we should
1051 if (sp
->sc_pstate
!= STOPPING
)
1052 sp
->sc_pstate
= pp
->pm_state
;
1056 (void) sprintf(Scratch
,
1057 "port monitor <%s> sent an invalid message - ignoring it",
1062 /* no matter what, PM did answer the poll */
1064 /* Note the messages it understands */
1065 sp
->sc_maxclass
= pp
->pm_maxclass
;
1071 * validstate - determine if arg s a valid return state from a port monitor
1072 * return 1 if ok, 0 otherwise
1074 * args: state - state to be verified
1077 validstate(unchar state
)
1092 * mk_cmd_pipe - create the command pipe used by sacadm
1098 int fds
[2]; /* pipe endpoints */
1099 int fd
; /* scratch file descriptor */
1101 /* make sure there is a file here to mount on */
1102 (void) unlink(CMDPIPE
);
1103 fd
= open(CMDPIPE
, O_RDWR
| O_CREAT
, 0600);
1105 error(E_CMDPIPE
, EXIT
);
1108 error(E_PIPE
, EXIT
);
1109 if (fattach(fds
[0], CMDPIPE
) < 0)
1110 error(E_FATTACH
, EXIT
);
1116 * startpoll - enable polling on command pipe by setting up to catch SIGPOLL
1123 struct sigaction sigact
; /* for signal handling */
1125 if (ioctl(Cfd
, I_SETSIG
, S_INPUT
) < 0)
1126 error(E_SETSIG
, EXIT
);
1127 sigact
.sa_flags
= 0;
1128 sigact
.sa_handler
= sigpoll
;
1129 (void) sigemptyset(&sigact
.sa_mask
);
1130 (void) sigaddset(&sigact
.sa_mask
, SIGPOLL
);
1131 (void) sigaction(SIGPOLL
, &sigact
, &Sigpoll
);