xref: /onnv-gate/usr/src/cmd/saf/misc.c (revision 334:249936f45018)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
230Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*334Sdp /*
25*334Sdp  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
26*334Sdp  * Use is subject to license terms.
27*334Sdp  */
280Sstevel@tonic-gate 
29*334Sdp #pragma ident	"%Z%%M%	%I%	%E% SMI"
300Sstevel@tonic-gate 
310Sstevel@tonic-gate 
32*334Sdp #include <stdio.h>
33*334Sdp #include <unistd.h>
34*334Sdp #include <stdlib.h>
35*334Sdp #include <fcntl.h>
36*334Sdp #include <sys/types.h>
37*334Sdp #include <sys/stropts.h>
38*334Sdp #include <signal.h>
39*334Sdp #include <sys/stat.h>
40*334Sdp #include <poll.h>
41*334Sdp #include "misc.h"
42*334Sdp #include "msgs.h"
43*334Sdp #include "extern.h"
44*334Sdp #include <sac.h>
45*334Sdp #include "adm.h"
46*334Sdp #include "structs.h"
470Sstevel@tonic-gate 
480Sstevel@tonic-gate 
490Sstevel@tonic-gate /*
500Sstevel@tonic-gate  * findpm - find a port monitor entry
510Sstevel@tonic-gate  *
520Sstevel@tonic-gate  *	args:	tag - tag of desired port monitor
530Sstevel@tonic-gate  */
540Sstevel@tonic-gate 
550Sstevel@tonic-gate 
560Sstevel@tonic-gate struct sactab *
findpm(tag)570Sstevel@tonic-gate findpm(tag)
580Sstevel@tonic-gate register char *tag;
590Sstevel@tonic-gate {
600Sstevel@tonic-gate 	register struct sactab *sp;	/* working pointer */
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 	for (sp = Sactab; sp; sp = sp->sc_next) {
630Sstevel@tonic-gate 		if (!strcmp(tag, sp->sc_tag))
640Sstevel@tonic-gate 			return(sp);
650Sstevel@tonic-gate 	}
660Sstevel@tonic-gate 	return(NULL);
670Sstevel@tonic-gate }
680Sstevel@tonic-gate 
690Sstevel@tonic-gate 
700Sstevel@tonic-gate /*
710Sstevel@tonic-gate  * sigpoll - handle messages coming in on the command pipe (SIGPOLL signal
720Sstevel@tonic-gate  *		handler)
730Sstevel@tonic-gate  */
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 
760Sstevel@tonic-gate void
sigpoll()770Sstevel@tonic-gate sigpoll()
780Sstevel@tonic-gate {
790Sstevel@tonic-gate 	struct pollfd fds;			/* array of fds to poll */
800Sstevel@tonic-gate 	struct admcmd cmd;			/* incoming command */
810Sstevel@tonic-gate 	register struct admcmd *ap = &cmd;	/* and a pointer to it */
820Sstevel@tonic-gate 	struct admack ack;			/* acknowledgment */
830Sstevel@tonic-gate 	register struct admack *ak = &ack;	/* and a pointer to it */
840Sstevel@tonic-gate 	register struct sactab *sp;		/* working pointer */
850Sstevel@tonic-gate 	struct sacmsg sacmsg;			/* message to port monitor */
860Sstevel@tonic-gate 	char **data;				/* "dumped" sactab */
870Sstevel@tonic-gate 	char *p;				/* scratch pointer */
880Sstevel@tonic-gate 	register int i;				/* loop control variable */
890Sstevel@tonic-gate 	int ret;				/* return value */
900Sstevel@tonic-gate 	sigset_t cset;				/* for signal handling */
910Sstevel@tonic-gate 	sigset_t tset;				/* for signal handling */
920Sstevel@tonic-gate 
930Sstevel@tonic-gate # ifdef DEBUG
940Sstevel@tonic-gate 	debug("in sigpoll");
950Sstevel@tonic-gate # endif
960Sstevel@tonic-gate 	fds.fd = Cfd;
970Sstevel@tonic-gate 	fds.events = POLLIN;
980Sstevel@tonic-gate 	fds.revents = 0;
990Sstevel@tonic-gate 	if (poll(&fds, 1, 0) < 0)
1000Sstevel@tonic-gate 		error(E_POLL, EXIT);
1010Sstevel@tonic-gate 	switch (fds.revents) {
1020Sstevel@tonic-gate 	case POLLIN:
1030Sstevel@tonic-gate 		if (read(Cfd, ap, sizeof(struct admcmd)) < 0) {
1040Sstevel@tonic-gate 			error(E_READ, EXIT);
1050Sstevel@tonic-gate 		}
1060Sstevel@tonic-gate 		switch (ap->ac_mtype) {
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate /*
1090Sstevel@tonic-gate  * request to start a port monitor
1100Sstevel@tonic-gate  */
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 		case AC_START:
1130Sstevel@tonic-gate # ifdef DEBUG
1140Sstevel@tonic-gate 			(void) sprintf(Scratch, "Got AC_START for <%s>", ap->ac_tag);
1150Sstevel@tonic-gate 			log(Scratch);
1160Sstevel@tonic-gate # endif
1170Sstevel@tonic-gate 			if ((sp = findpm(ap->ac_tag)) == NULL) {
1180Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
1190Sstevel@tonic-gate 				ak->ak_resp = AK_NOPM;
1200Sstevel@tonic-gate 				ak->ak_size = 0;
1210Sstevel@tonic-gate 				sendack(ak);
1220Sstevel@tonic-gate 				break;
1230Sstevel@tonic-gate 			}
1240Sstevel@tonic-gate 			switch (sp->sc_sstate) {
1250Sstevel@tonic-gate 			case UNKNOWN:
1260Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
1270Sstevel@tonic-gate 				ak->ak_resp = AK_RECOVER;
1280Sstevel@tonic-gate 				ak->ak_size = 0;
1290Sstevel@tonic-gate 				sendack(ak);
1300Sstevel@tonic-gate 				break;
1310Sstevel@tonic-gate 			case FAILED:
1320Sstevel@tonic-gate 			case NOTRUNNING:
1330Sstevel@tonic-gate 				sp->sc_rscnt = 0;	/* fresh start in life */
1340Sstevel@tonic-gate 				if (ret = startpm(sp)) {
1350Sstevel@tonic-gate 					ak->ak_pid = ap->ac_pid;
1360Sstevel@tonic-gate 					if (ret == -1)
1370Sstevel@tonic-gate 						ak->ak_resp = AK_PMLOCK;
1380Sstevel@tonic-gate 					else
1390Sstevel@tonic-gate 						ak->ak_resp = AK_REQFAIL;
1400Sstevel@tonic-gate 					ak->ak_size = 0;
1410Sstevel@tonic-gate 					sendack(ak);
1420Sstevel@tonic-gate 					break;
1430Sstevel@tonic-gate 				}
1440Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
1450Sstevel@tonic-gate 				ak->ak_resp = AK_ACK;
1460Sstevel@tonic-gate 				ak->ak_size = 0;
1470Sstevel@tonic-gate 				sendack(ak);
1480Sstevel@tonic-gate 				break;
1490Sstevel@tonic-gate 			case ENABLED:
1500Sstevel@tonic-gate 			case DISABLED:
1510Sstevel@tonic-gate 			case STARTING:
1520Sstevel@tonic-gate 			case STOPPING:
1530Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
1540Sstevel@tonic-gate 				ak->ak_resp = AK_PMRUN;
1550Sstevel@tonic-gate 				ak->ak_size = 0;
1560Sstevel@tonic-gate 				sendack(ak);
1570Sstevel@tonic-gate 				break;
1580Sstevel@tonic-gate 			}
1590Sstevel@tonic-gate 			break;
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate /*
1620Sstevel@tonic-gate  * request to kill a port monitor
1630Sstevel@tonic-gate  */
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 		case AC_KILL:
1660Sstevel@tonic-gate # ifdef DEBUG
1670Sstevel@tonic-gate 			(void) sprintf(Scratch, "Got AC_KILL for <%s>", ap->ac_tag);
1680Sstevel@tonic-gate 			log(Scratch);
1690Sstevel@tonic-gate # endif
1700Sstevel@tonic-gate 			if ((sp = findpm(ap->ac_tag)) == NULL) {
1710Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
1720Sstevel@tonic-gate 				ak->ak_resp = AK_NOPM;
1730Sstevel@tonic-gate 				ak->ak_size = 0;
1740Sstevel@tonic-gate 				sendack(ak);
1750Sstevel@tonic-gate 				break;
1760Sstevel@tonic-gate 			}
1770Sstevel@tonic-gate 			switch (sp->sc_sstate) {
1780Sstevel@tonic-gate 			case UNKNOWN:
1790Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
1800Sstevel@tonic-gate 				ak->ak_resp = AK_RECOVER;
1810Sstevel@tonic-gate 				ak->ak_size = 0;
1820Sstevel@tonic-gate 				sendack(ak);
1830Sstevel@tonic-gate 				break;
1840Sstevel@tonic-gate 			case NOTRUNNING:
1850Sstevel@tonic-gate 			case FAILED:
1860Sstevel@tonic-gate 			case STOPPING:
1870Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
1880Sstevel@tonic-gate 				ak->ak_resp = AK_PMNOTRUN;
1890Sstevel@tonic-gate 				ak->ak_size = 0;
1900Sstevel@tonic-gate 				sendack(ak);
1910Sstevel@tonic-gate 				break;
1920Sstevel@tonic-gate 			case STARTING:
1930Sstevel@tonic-gate 			case ENABLED:
1940Sstevel@tonic-gate 			case DISABLED:
1950Sstevel@tonic-gate 				(void) sigprocmask(SIG_SETMASK, NULL, &cset);
1960Sstevel@tonic-gate 				tset = cset;
1970Sstevel@tonic-gate 				(void) sigaddset(&tset, SIGALRM);
1980Sstevel@tonic-gate 				(void) sigaddset(&tset, SIGCLD);
1990Sstevel@tonic-gate 				(void) sigprocmask(SIG_SETMASK, &tset, NULL);
2000Sstevel@tonic-gate 				if (sendsig(sp, SIGTERM)) {
2010Sstevel@tonic-gate 					(void) sprintf(Scratch, "could not send SIGTERM to <%s>", sp->sc_tag);
2020Sstevel@tonic-gate 					log(Scratch);
2030Sstevel@tonic-gate 					ak->ak_pid = ap->ac_pid;
2040Sstevel@tonic-gate 					ak->ak_resp = AK_NOCONTACT;
2050Sstevel@tonic-gate 					ak->ak_size = 0;
2060Sstevel@tonic-gate 					sendack(ak);
2070Sstevel@tonic-gate 					(void) sigprocmask(SIG_SETMASK, &cset, NULL);
2080Sstevel@tonic-gate 					break;
2090Sstevel@tonic-gate 				}
2100Sstevel@tonic-gate 				/* signal sent ok */
2110Sstevel@tonic-gate 				sp->sc_lstate = NOTRUNNING;
2120Sstevel@tonic-gate 				sp->sc_sstate = NOTRUNNING;
2130Sstevel@tonic-gate 				sp->sc_pstate = STOPPING;
2140Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
2150Sstevel@tonic-gate 				ak->ak_resp = AK_ACK;
2160Sstevel@tonic-gate 				ak->ak_size = 0;
2170Sstevel@tonic-gate 				sendack(ak);
2180Sstevel@tonic-gate 				(void) sprintf(Scratch, "terminating <%s>", sp->sc_tag);
2190Sstevel@tonic-gate 				log(Scratch);
2200Sstevel@tonic-gate 				(void) sigprocmask(SIG_SETMASK, &cset, NULL);
2210Sstevel@tonic-gate 				break;
2220Sstevel@tonic-gate 			}
2230Sstevel@tonic-gate 			break;
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate /*
2260Sstevel@tonic-gate  * request to enable a port monitor
2270Sstevel@tonic-gate  */
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 		case AC_ENABLE:
2300Sstevel@tonic-gate # ifdef DEBUG
2310Sstevel@tonic-gate 			(void) sprintf(Scratch, "Got AC_ENABLE for <%s>", ap->ac_tag);
2320Sstevel@tonic-gate 			log(Scratch);
2330Sstevel@tonic-gate # endif
2340Sstevel@tonic-gate 			if ((sp = findpm(ap->ac_tag)) == NULL) {
2350Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
2360Sstevel@tonic-gate 				ak->ak_resp = AK_NOPM;
2370Sstevel@tonic-gate 				ak->ak_size = 0;
2380Sstevel@tonic-gate 				sendack(ak);
2390Sstevel@tonic-gate 				break;
2400Sstevel@tonic-gate 			}
2410Sstevel@tonic-gate 			switch (sp->sc_sstate) {
2420Sstevel@tonic-gate 			case UNKNOWN:
2430Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
2440Sstevel@tonic-gate 				ak->ak_resp = AK_RECOVER;
2450Sstevel@tonic-gate 				ak->ak_size = 0;
2460Sstevel@tonic-gate 				sendack(ak);
2470Sstevel@tonic-gate 				break;
2480Sstevel@tonic-gate 			case NOTRUNNING:
2490Sstevel@tonic-gate 			case FAILED:
2500Sstevel@tonic-gate 			case STOPPING:
2510Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
2520Sstevel@tonic-gate 				ak->ak_resp = AK_PMNOTRUN;
2530Sstevel@tonic-gate 				ak->ak_size = 0;
2540Sstevel@tonic-gate 				sendack(ak);
2550Sstevel@tonic-gate 				break;
2560Sstevel@tonic-gate 			case STARTING:
2570Sstevel@tonic-gate 			case DISABLED:
2580Sstevel@tonic-gate 				sacmsg.sc_type = SC_ENABLE;
2590Sstevel@tonic-gate 				sacmsg.sc_size = 0;
2600Sstevel@tonic-gate 				sp->sc_sstate = ENABLED;
2610Sstevel@tonic-gate 				sp->sc_lstate = ENABLED;
2620Sstevel@tonic-gate 				sendpmmsg(sp, &sacmsg);
2630Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
2640Sstevel@tonic-gate 				ak->ak_resp = AK_ACK;
2650Sstevel@tonic-gate 				ak->ak_size = 0;
2660Sstevel@tonic-gate 				sendack(ak);
2670Sstevel@tonic-gate 				break;
2680Sstevel@tonic-gate 			case ENABLED:
2690Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
2700Sstevel@tonic-gate 				ak->ak_resp = AK_ACK;
2710Sstevel@tonic-gate 				ak->ak_size = 0;
2720Sstevel@tonic-gate 				sendack(ak);
2730Sstevel@tonic-gate 				break;
2740Sstevel@tonic-gate 			}
2750Sstevel@tonic-gate 			break;
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate /*
2780Sstevel@tonic-gate  * request to disable a port monitor
2790Sstevel@tonic-gate  */
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 		case AC_DISABLE:
2820Sstevel@tonic-gate # ifdef DEBUG
2830Sstevel@tonic-gate 			(void) sprintf(Scratch, "Got AC_DISABLE for <%s>", ap->ac_tag);
2840Sstevel@tonic-gate 			log(Scratch);
2850Sstevel@tonic-gate # endif
2860Sstevel@tonic-gate 			if ((sp = findpm(ap->ac_tag)) == NULL) {
2870Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
2880Sstevel@tonic-gate 				ak->ak_resp = AK_NOPM;
2890Sstevel@tonic-gate 				ak->ak_size = 0;
2900Sstevel@tonic-gate 				sendack(ak);
2910Sstevel@tonic-gate 				break;
2920Sstevel@tonic-gate 			}
2930Sstevel@tonic-gate 			switch (sp->sc_sstate) {
2940Sstevel@tonic-gate 			case UNKNOWN:
2950Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
2960Sstevel@tonic-gate 				ak->ak_resp = AK_RECOVER;
2970Sstevel@tonic-gate 				ak->ak_size = 0;
2980Sstevel@tonic-gate 				sendack(ak);
2990Sstevel@tonic-gate 				break;
3000Sstevel@tonic-gate 			case NOTRUNNING:
3010Sstevel@tonic-gate 			case FAILED:
3020Sstevel@tonic-gate 			case STOPPING:
3030Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
3040Sstevel@tonic-gate 				ak->ak_resp = AK_PMNOTRUN;
3050Sstevel@tonic-gate 				ak->ak_size = 0;
3060Sstevel@tonic-gate 				sendack(ak);
3070Sstevel@tonic-gate 				break;
3080Sstevel@tonic-gate 			case STARTING:
3090Sstevel@tonic-gate 			case ENABLED:
3100Sstevel@tonic-gate 				sacmsg.sc_type = SC_DISABLE;
3110Sstevel@tonic-gate 				sacmsg.sc_size = 0;
3120Sstevel@tonic-gate 				sp->sc_sstate = DISABLED;
3130Sstevel@tonic-gate 				sp->sc_lstate = DISABLED;
3140Sstevel@tonic-gate 				sendpmmsg(sp, &sacmsg);
3150Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
3160Sstevel@tonic-gate 				ak->ak_resp = AK_ACK;
3170Sstevel@tonic-gate 				ak->ak_size = 0;
3180Sstevel@tonic-gate 				sendack(ak);
3190Sstevel@tonic-gate 				break;
3200Sstevel@tonic-gate 			case DISABLED:
3210Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
3220Sstevel@tonic-gate 				ak->ak_resp = AK_ACK;
3230Sstevel@tonic-gate 				ak->ak_size = 0;
3240Sstevel@tonic-gate 				sendack(ak);
3250Sstevel@tonic-gate 				break;
3260Sstevel@tonic-gate 			}
3270Sstevel@tonic-gate 			break;
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate /*
3300Sstevel@tonic-gate  * request for port monitor status information
3310Sstevel@tonic-gate  */
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 		case AC_STATUS:
3340Sstevel@tonic-gate # ifdef DEBUG
3350Sstevel@tonic-gate 			log("Got AC_STATUS");
3360Sstevel@tonic-gate # endif
3370Sstevel@tonic-gate 			/* get all the info in one convenient place */
3380Sstevel@tonic-gate 			data = dump_table();
3390Sstevel@tonic-gate 			if ((data == NULL) && (Nentries > 0)) {
3400Sstevel@tonic-gate 				/* something bad happened in dump_table */
3410Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
3420Sstevel@tonic-gate 				ak->ak_resp = AK_REQFAIL;
3430Sstevel@tonic-gate 				ak->ak_size = 0;
3440Sstevel@tonic-gate 				sendack(ak);
3450Sstevel@tonic-gate 				break;
3460Sstevel@tonic-gate 			}
3470Sstevel@tonic-gate 			/* count how big it is */
3480Sstevel@tonic-gate 			ak->ak_size = 0;
3490Sstevel@tonic-gate 			for (i = 0; i < Nentries; ++i)
3500Sstevel@tonic-gate 				ak->ak_size += strlen(data[i]);
3510Sstevel@tonic-gate # ifdef DEBUG
3520Sstevel@tonic-gate 			(void) sprintf(Scratch, "ak_size is %d", ak->ak_size);
3530Sstevel@tonic-gate 			debug(Scratch);
3540Sstevel@tonic-gate # endif
3550Sstevel@tonic-gate 			/* get a contiguous chunk */
3560Sstevel@tonic-gate 			if ((p = malloc((unsigned) (ak->ak_size + 1))) == NULL) {
3570Sstevel@tonic-gate 				error(E_MALLOC, CONT);
3580Sstevel@tonic-gate 				for (i = 0; i < Nentries; ++i)
3590Sstevel@tonic-gate 					free(data[i]);
3600Sstevel@tonic-gate 				free((char *) data);
3610Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
3620Sstevel@tonic-gate 				ak->ak_resp = AK_REQFAIL;
3630Sstevel@tonic-gate 				ak->ak_size = 0;
3640Sstevel@tonic-gate 				sendack(ak);
3650Sstevel@tonic-gate 				break;
3660Sstevel@tonic-gate 			}
3670Sstevel@tonic-gate 			/* condense the data into the contiguous chunk */
3680Sstevel@tonic-gate 			*p = '\0';
3690Sstevel@tonic-gate 			for (i = 0; i < Nentries; ++i) {
3700Sstevel@tonic-gate 				(void) strcat(p, data[i]);
3710Sstevel@tonic-gate 				free(data[i]);
3720Sstevel@tonic-gate 			}
3730Sstevel@tonic-gate # ifdef DEBUG
3740Sstevel@tonic-gate 			debug(p);
3750Sstevel@tonic-gate # endif
3760Sstevel@tonic-gate 			if (data)
3770Sstevel@tonic-gate 				free((char *) data);
3780Sstevel@tonic-gate 			/* ak->ak_size was set above */
3790Sstevel@tonic-gate 			ak->ak_pid = ap->ac_pid;
3800Sstevel@tonic-gate 			ak->ak_resp = AK_ACK;
3810Sstevel@tonic-gate 			sendack(ak);
3820Sstevel@tonic-gate 			if (ak->ak_size)
3830Sstevel@tonic-gate 				if (write(Cfd, p, (unsigned) ak->ak_size) != ak->ak_size)
3840Sstevel@tonic-gate 					log("could not send info");
3850Sstevel@tonic-gate 			free(p);
3860Sstevel@tonic-gate 			break;
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate /*
3890Sstevel@tonic-gate  * request for sac to read sactab
3900Sstevel@tonic-gate  */
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 		case AC_SACREAD:
3930Sstevel@tonic-gate # ifdef DEBUG
3940Sstevel@tonic-gate 			log("Got AC_SACREAD");
3950Sstevel@tonic-gate # endif
3960Sstevel@tonic-gate 			ak->ak_pid = ap->ac_pid;
3970Sstevel@tonic-gate 			ak->ak_resp = AK_ACK;
3980Sstevel@tonic-gate 			ak->ak_size = 0;
3990Sstevel@tonic-gate 			read_table(TRUE);
4000Sstevel@tonic-gate 			sendack(ak);
4010Sstevel@tonic-gate 			break;
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate /*
4040Sstevel@tonic-gate  * request for port monitor to read _pmtab
4050Sstevel@tonic-gate  */
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate 		case AC_PMREAD:
4080Sstevel@tonic-gate # ifdef DEBUG
4090Sstevel@tonic-gate 			(void) sprintf(Scratch, "Got AC_PMREAD for <%s>", ap->ac_tag);
4100Sstevel@tonic-gate 			log(Scratch);
4110Sstevel@tonic-gate # endif
4120Sstevel@tonic-gate 			if ((sp = findpm(ap->ac_tag)) == NULL) {
4130Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
4140Sstevel@tonic-gate 				ak->ak_resp = AK_NOPM;
4150Sstevel@tonic-gate 				ak->ak_size = 0;
4160Sstevel@tonic-gate 				sendack(ak);
4170Sstevel@tonic-gate 				break;
4180Sstevel@tonic-gate 			}
4190Sstevel@tonic-gate 			switch (sp->sc_sstate) {
4200Sstevel@tonic-gate 			case UNKNOWN:
4210Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
4220Sstevel@tonic-gate 				ak->ak_resp = AK_RECOVER;
4230Sstevel@tonic-gate 				ak->ak_size = 0;
4240Sstevel@tonic-gate 				sendack(ak);
4250Sstevel@tonic-gate 				break;
4260Sstevel@tonic-gate 			case NOTRUNNING:
4270Sstevel@tonic-gate 			case FAILED:
4280Sstevel@tonic-gate 			case STOPPING:
4290Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
4300Sstevel@tonic-gate 				ak->ak_resp = AK_PMNOTRUN;
4310Sstevel@tonic-gate 				ak->ak_size = 0;
4320Sstevel@tonic-gate 				sendack(ak);
4330Sstevel@tonic-gate 				break;
4340Sstevel@tonic-gate 			case STARTING:
4350Sstevel@tonic-gate 			case ENABLED:
4360Sstevel@tonic-gate 			case DISABLED:
4370Sstevel@tonic-gate 				sacmsg.sc_type = SC_READDB;
4380Sstevel@tonic-gate 				sacmsg.sc_size = 0;
4390Sstevel@tonic-gate 				sendpmmsg(sp, &sacmsg);
4400Sstevel@tonic-gate 				ak->ak_pid = ap->ac_pid;
4410Sstevel@tonic-gate 				ak->ak_resp = AK_ACK;
4420Sstevel@tonic-gate 				ak->ak_size = 0;
4430Sstevel@tonic-gate 				sendack(ak);
4440Sstevel@tonic-gate 				break;
4450Sstevel@tonic-gate 			}
4460Sstevel@tonic-gate 			break;
4470Sstevel@tonic-gate /*
4480Sstevel@tonic-gate  * garbled message
4490Sstevel@tonic-gate  */
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 		default:
4520Sstevel@tonic-gate 			(void) sprintf(Scratch, "Got unknown message for <%s>", ap->ac_tag);
4530Sstevel@tonic-gate 			log(Scratch);
4540Sstevel@tonic-gate 			ak->ak_pid = ap->ac_pid;
4550Sstevel@tonic-gate 			ak->ak_resp = AK_UNKNOWN;
4560Sstevel@tonic-gate 			ak->ak_size = 0;
4570Sstevel@tonic-gate 			sendack(ak);
4580Sstevel@tonic-gate 			break;
4590Sstevel@tonic-gate 		}
4600Sstevel@tonic-gate 		break;
4610Sstevel@tonic-gate 	default:
4620Sstevel@tonic-gate 		error(E_POLL, EXIT);
4630Sstevel@tonic-gate 	}
4640Sstevel@tonic-gate }
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate /*
4680Sstevel@tonic-gate  * sendack - send a response to the administrative command
4690Sstevel@tonic-gate  *
4700Sstevel@tonic-gate  *	args:	ap - pointer to acknowlegment message
4710Sstevel@tonic-gate  */
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate void
sendack(ap)4740Sstevel@tonic-gate sendack(ap)
4750Sstevel@tonic-gate struct admack *ap;
4760Sstevel@tonic-gate {
4770Sstevel@tonic-gate # ifdef DEBUG
4780Sstevel@tonic-gate 	debug("in sendack");
4790Sstevel@tonic-gate # endif
4800Sstevel@tonic-gate 	if (write(Cfd, ap, sizeof(struct admack)) != sizeof(struct admack))
4810Sstevel@tonic-gate 		log("Could not send ack");
4820Sstevel@tonic-gate }
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate /*
4860Sstevel@tonic-gate  * sendpmmsg - send a message to a PM.  Note: sc_size is always 0 in
4870Sstevel@tonic-gate  *	       this version so just send the header.
4880Sstevel@tonic-gate  *
4890Sstevel@tonic-gate  *	args:	sp - pointer to sac's port monitor information for
4900Sstevel@tonic-gate  *		     designated port monitor
4910Sstevel@tonic-gate  *		sm - pointer to message to send
4920Sstevel@tonic-gate  */
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate void
sendpmmsg(sp,sm)4950Sstevel@tonic-gate sendpmmsg(sp, sm)
4960Sstevel@tonic-gate register struct sactab *sp;
4970Sstevel@tonic-gate register struct sacmsg *sm;
4980Sstevel@tonic-gate {
4990Sstevel@tonic-gate 	char buf[SIZE];			/* scratch buffer */
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate # ifdef DEBUG
5020Sstevel@tonic-gate 	debug("in sendpmmsg");
5030Sstevel@tonic-gate # endif
5040Sstevel@tonic-gate 	if (write(sp->sc_fd, sm, sizeof(struct sacmsg)) != sizeof(struct sacmsg)) {
5050Sstevel@tonic-gate 		(void) sprintf(buf, "message to <%s> failed", sp->sc_tag);
5060Sstevel@tonic-gate 		log(buf);
5070Sstevel@tonic-gate 	}
5080Sstevel@tonic-gate }
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate /*
5110Sstevel@tonic-gate  * sendsig - send a signal to the port monitor
5120Sstevel@tonic-gate  *
5130Sstevel@tonic-gate  *	args:	sp - pointer to sac's port monitor infomation for
5140Sstevel@tonic-gate  *		     designated port monitor
5150Sstevel@tonic-gate  *		signo - signal number to send
5160Sstevel@tonic-gate  */
5170Sstevel@tonic-gate 
518*334Sdp int
sendsig(struct sactab * sp,int signo)519*334Sdp sendsig(struct sactab *sp, int signo)
5200Sstevel@tonic-gate {
5210Sstevel@tonic-gate 	pid_t pid;	/* pid of designated port monitor */
5220Sstevel@tonic-gate 	pid_t checklock();
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate # ifdef DEBUG
5250Sstevel@tonic-gate 	(void) sprintf(Scratch, "in sendsig - sending signo %d to %s", signo, sp->sc_tag);
5260Sstevel@tonic-gate 	debug(Scratch);
5270Sstevel@tonic-gate # endif
5280Sstevel@tonic-gate 	if (pid = checklock(sp)) {
5290Sstevel@tonic-gate 		if (kill(pid, signo) < 0) {
5300Sstevel@tonic-gate # ifdef DEBUG
5310Sstevel@tonic-gate 			debug("in sendsig - kill failed");
5320Sstevel@tonic-gate # endif
5330Sstevel@tonic-gate 			return(-1);
5340Sstevel@tonic-gate 		}
5350Sstevel@tonic-gate 		else
5360Sstevel@tonic-gate 			return(0);
5370Sstevel@tonic-gate 	}
5380Sstevel@tonic-gate 	else {
5390Sstevel@tonic-gate # ifdef DEBUG
5400Sstevel@tonic-gate 		debug("in sendsig - checklock failed");
5410Sstevel@tonic-gate # endif
5420Sstevel@tonic-gate 		return(-1);
5430Sstevel@tonic-gate 	}
5440Sstevel@tonic-gate }
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate /*
5480Sstevel@tonic-gate  * checklock - check to see if a _pid file is locked
5490Sstevel@tonic-gate  *		if so, return pid in file, else 0
5500Sstevel@tonic-gate  *
5510Sstevel@tonic-gate  *	args:	sp - pointer to sac's port monitor infomation for
5520Sstevel@tonic-gate  *		     designated port monitor
5530Sstevel@tonic-gate  */
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate pid_t
checklock(sp)5560Sstevel@tonic-gate checklock(sp)
5570Sstevel@tonic-gate register struct sactab *sp;
5580Sstevel@tonic-gate {
5590Sstevel@tonic-gate 	int fd;			/* scratch file descriptor */
5600Sstevel@tonic-gate 	char buf[SIZE];		/* scratch buffer */
5610Sstevel@tonic-gate 	int ret;		/* return value */
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate # ifdef DEBUG
5640Sstevel@tonic-gate 	debug("in checklock");
5650Sstevel@tonic-gate # endif
5660Sstevel@tonic-gate 	(void) sprintf(Scratch, "%s/%s/_pid", HOME, sp->sc_tag);
5670Sstevel@tonic-gate 	fd = open(Scratch, O_RDONLY);
5680Sstevel@tonic-gate 	if (fd < 0) {
5690Sstevel@tonic-gate 		(void) sprintf(Scratch, "can not open _pid file for <%s>", sp->sc_tag);
5700Sstevel@tonic-gate 		log(Scratch);
5710Sstevel@tonic-gate 		return((pid_t)0);
5720Sstevel@tonic-gate 	}
5730Sstevel@tonic-gate 	if (lockf(fd, F_TEST, 0) < 0) {
5740Sstevel@tonic-gate 		if ((ret = read(fd, buf, SIZE - 1)) < 0) {
5750Sstevel@tonic-gate 			(void) close(fd);
5760Sstevel@tonic-gate 			return((pid_t)0);
5770Sstevel@tonic-gate 		}
5780Sstevel@tonic-gate 		(void) close(fd);
5790Sstevel@tonic-gate 		/* in case pid wasn't null-terminated */
5800Sstevel@tonic-gate 		buf[ret] = '\0';
5810Sstevel@tonic-gate 		return((pid_t)atol(buf));
5820Sstevel@tonic-gate 	}
5830Sstevel@tonic-gate 	(void) close(fd);
5840Sstevel@tonic-gate 	return((pid_t)0);
5850Sstevel@tonic-gate }
586