xref: /titanic_51/usr/src/cmd/saf/sacadm.c (revision 22c9e08b20c7848675e1e097ca3fcbcf8b549fba)
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
5*22c9e08bSsn199410  * Common Development and Distribution License (the "License").
6*22c9e08bSsn199410  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*22c9e08bSsn199410  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
2334e48580Sdp  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
277c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
287c478bd9Sstevel@tonic-gate 
2934e48580Sdp #pragma ident	"%Z%%M%	%I%	%E% SMI"
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <stdio.h>
3334e48580Sdp #include <stdlib.h>
3434e48580Sdp #include <strings.h>
357c478bd9Sstevel@tonic-gate #include <fcntl.h>
367c478bd9Sstevel@tonic-gate #include <errno.h>
377c478bd9Sstevel@tonic-gate #include <sys/types.h>
38*22c9e08bSsn199410 #include <sys/wait.h>
397c478bd9Sstevel@tonic-gate #include <sys/stat.h>
407c478bd9Sstevel@tonic-gate #include <signal.h>
417c478bd9Sstevel@tonic-gate #include <unistd.h>
427c478bd9Sstevel@tonic-gate #include <sac.h>
43*22c9e08bSsn199410 #include <spawn.h>
447c478bd9Sstevel@tonic-gate #include "misc.h"
457c478bd9Sstevel@tonic-gate #include "structs.h"
467c478bd9Sstevel@tonic-gate #include "adm.h"
477c478bd9Sstevel@tonic-gate #include "extern.h"
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate /*
517c478bd9Sstevel@tonic-gate  * functions
527c478bd9Sstevel@tonic-gate  */
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate char	*pflags();
557c478bd9Sstevel@tonic-gate char	*getfield();
567c478bd9Sstevel@tonic-gate void	add_pm();
577c478bd9Sstevel@tonic-gate void	cleandirs();
587c478bd9Sstevel@tonic-gate void	rem_pm();
597c478bd9Sstevel@tonic-gate void	start_pm();
607c478bd9Sstevel@tonic-gate void	kill_pm();
617c478bd9Sstevel@tonic-gate void	enable_pm();
627c478bd9Sstevel@tonic-gate void	disable_pm();
637c478bd9Sstevel@tonic-gate void	list_pms();
647c478bd9Sstevel@tonic-gate void	read_db();
657c478bd9Sstevel@tonic-gate void	sendcmd();
667c478bd9Sstevel@tonic-gate void	checkresp();
677c478bd9Sstevel@tonic-gate void	single_print();
687c478bd9Sstevel@tonic-gate void	catch();
697c478bd9Sstevel@tonic-gate void	usage();
70*22c9e08bSsn199410 static	int invoke_rm(char *);
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate # define START		0x1	/* -s seen */
737c478bd9Sstevel@tonic-gate # define KILL		0x2	/* -k seen */
747c478bd9Sstevel@tonic-gate # define ENABLE		0x4	/* -e seen */
757c478bd9Sstevel@tonic-gate # define DISABLE	0x8	/* -d seen */
767c478bd9Sstevel@tonic-gate # define PLIST		0x10	/* -l seen */
777c478bd9Sstevel@tonic-gate # define LIST		0x20	/* -L seen */
787c478bd9Sstevel@tonic-gate # define DBREAD		0x40	/* -x seen */
797c478bd9Sstevel@tonic-gate # define CONFIG		0x80	/* -G seen */
807c478bd9Sstevel@tonic-gate # define PCONFIG	0x100	/* -g seen */
817c478bd9Sstevel@tonic-gate # define ADD		0x200	/* -a or other required options seen */
827c478bd9Sstevel@tonic-gate # define REMOVE		0x400	/* -r seen */
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate  * common error messages
867c478bd9Sstevel@tonic-gate  */
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate # define NOTPRIV	"User not privileged for operation"
897c478bd9Sstevel@tonic-gate # define SACERR		"Can not contact SAC"
907c478bd9Sstevel@tonic-gate # define BADINP		"Embedded newlines not allowed"
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate int	Saferrno;	/* internal `errno' for exit */
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate /*
977c478bd9Sstevel@tonic-gate  * main - scan args for sacadm and call appropriate handling code
987c478bd9Sstevel@tonic-gate  */
997c478bd9Sstevel@tonic-gate 
10034e48580Sdp int
10134e48580Sdp main(int argc, char *argv[])
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate 	int c;			/* option letter */
1047c478bd9Sstevel@tonic-gate 	uid_t uid;		/* invoker's real uid */
1057c478bd9Sstevel@tonic-gate 	int ret;		/* return code from check_version */
1067c478bd9Sstevel@tonic-gate 	int flag = 0;		/* flag to record requested operations */
1077c478bd9Sstevel@tonic-gate 	int errflg = 0;		/* error indicator */
1087c478bd9Sstevel@tonic-gate 	int version = -1;	/* argument to -v */
1097c478bd9Sstevel@tonic-gate 	int count = 0;		/* argument to -n */
1107c478bd9Sstevel@tonic-gate 	int badcnt = 0;		/* count of bad args to -f */
1117c478bd9Sstevel@tonic-gate 	int sawaflag = 0;	/* true if actually saw -a */
1127c478bd9Sstevel@tonic-gate 	int conflag = 0;	/* true if output should be in condensed form */
1137c478bd9Sstevel@tonic-gate 	long flags = 0;		/* arguments to -f */
1147c478bd9Sstevel@tonic-gate 	FILE *fp;		/* scratch file pointer */
1157c478bd9Sstevel@tonic-gate 	char *pmtag = NULL;	/* argument to -p */
1167c478bd9Sstevel@tonic-gate 	char *type = NULL;	/* argument to -t */
1177c478bd9Sstevel@tonic-gate 	char *script = NULL;	/* argument to -z */
1187c478bd9Sstevel@tonic-gate 	char *command = NULL;	/* argument to -c */
1197c478bd9Sstevel@tonic-gate 	char *comment = " ";	/* argument to -y */
1207c478bd9Sstevel@tonic-gate 	char badargs[BADFARGSIZE];	/* place to hold bad args to -f */
1217c478bd9Sstevel@tonic-gate 	char buf[SIZE];		/* scratch buffer */
1227c478bd9Sstevel@tonic-gate 	register char *p;	/* scratch pointer */
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	if (argc == 1)
1257c478bd9Sstevel@tonic-gate 		usage(argv[0]);
1267c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "ac:def:GgkLln:p:rst:v:xy:z:")) != -1) {
1277c478bd9Sstevel@tonic-gate 		switch (c) {
1287c478bd9Sstevel@tonic-gate 		case 'a':
1297c478bd9Sstevel@tonic-gate 			flag |= ADD;
1307c478bd9Sstevel@tonic-gate 			sawaflag = 1;
1317c478bd9Sstevel@tonic-gate 			break;
1327c478bd9Sstevel@tonic-gate 		case 'c':
1337c478bd9Sstevel@tonic-gate 			flag |= ADD;
1347c478bd9Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
1357c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
1367c478bd9Sstevel@tonic-gate 				error(BADINP);
1377c478bd9Sstevel@tonic-gate 			}
1387c478bd9Sstevel@tonic-gate 			command = optarg;
1397c478bd9Sstevel@tonic-gate 			if (*command != '/') {
1407c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
1417c478bd9Sstevel@tonic-gate 				error("command must be a full pathname");
1427c478bd9Sstevel@tonic-gate 			}
1437c478bd9Sstevel@tonic-gate 			break;
1447c478bd9Sstevel@tonic-gate 		case 'd':
1457c478bd9Sstevel@tonic-gate 			flag |= DISABLE;
1467c478bd9Sstevel@tonic-gate 			break;
1477c478bd9Sstevel@tonic-gate 		case 'e':
1487c478bd9Sstevel@tonic-gate 			flag |= ENABLE;
1497c478bd9Sstevel@tonic-gate 			break;
1507c478bd9Sstevel@tonic-gate 		case 'f':
1517c478bd9Sstevel@tonic-gate 			flag |= ADD;
1527c478bd9Sstevel@tonic-gate 			while (*optarg) {
1537c478bd9Sstevel@tonic-gate 				switch (*optarg++) {
1547c478bd9Sstevel@tonic-gate 				case 'd':
1557c478bd9Sstevel@tonic-gate 					flags |= D_FLAG;
1567c478bd9Sstevel@tonic-gate 					break;
1577c478bd9Sstevel@tonic-gate 				case 'x':
1587c478bd9Sstevel@tonic-gate 					flags |= X_FLAG;
1597c478bd9Sstevel@tonic-gate 					break;
1607c478bd9Sstevel@tonic-gate 				default:
1617c478bd9Sstevel@tonic-gate 					if (badcnt < (BADFARGSIZE -1))
1627c478bd9Sstevel@tonic-gate 					    badargs[badcnt++] = *(optarg - 1);
1637c478bd9Sstevel@tonic-gate 					break;
1647c478bd9Sstevel@tonic-gate 				}
1657c478bd9Sstevel@tonic-gate 			}
1667c478bd9Sstevel@tonic-gate 			/* null terminate just in case anything is there */
1677c478bd9Sstevel@tonic-gate 			badargs[badcnt] = '\0';
1687c478bd9Sstevel@tonic-gate 			break;
1697c478bd9Sstevel@tonic-gate 		case 'G':
1707c478bd9Sstevel@tonic-gate 			flag |= CONFIG;
1717c478bd9Sstevel@tonic-gate 			break;
1727c478bd9Sstevel@tonic-gate 		case 'g':
1737c478bd9Sstevel@tonic-gate 			flag |= PCONFIG;
1747c478bd9Sstevel@tonic-gate 			break;
1757c478bd9Sstevel@tonic-gate 		case 'k':
1767c478bd9Sstevel@tonic-gate 			flag |= KILL;
1777c478bd9Sstevel@tonic-gate 			break;
1787c478bd9Sstevel@tonic-gate 		case 'L':
1797c478bd9Sstevel@tonic-gate 			flag |= LIST;
1807c478bd9Sstevel@tonic-gate 			break;
1817c478bd9Sstevel@tonic-gate 		case 'l':
1827c478bd9Sstevel@tonic-gate 			flag |= PLIST;
1837c478bd9Sstevel@tonic-gate 			break;
1847c478bd9Sstevel@tonic-gate 		case 'n':
1857c478bd9Sstevel@tonic-gate 			flag |= ADD;
1867c478bd9Sstevel@tonic-gate 			count = atoi(optarg);
1877c478bd9Sstevel@tonic-gate 			if (count < 0) {
1887c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
1897c478bd9Sstevel@tonic-gate 				error("restart count can not be negative");
1907c478bd9Sstevel@tonic-gate 			}
1917c478bd9Sstevel@tonic-gate 			break;
1927c478bd9Sstevel@tonic-gate 		case 'p':
1937c478bd9Sstevel@tonic-gate 			pmtag = optarg;
1947c478bd9Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
1957c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
1967c478bd9Sstevel@tonic-gate 				error(BADINP);
1977c478bd9Sstevel@tonic-gate 			}
1987c478bd9Sstevel@tonic-gate 			if (strlen(pmtag) > PMTAGSIZE) {
1997c478bd9Sstevel@tonic-gate 				pmtag[PMTAGSIZE] = '\0';
2007c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "tag too long, truncated to <%s>\n", pmtag);
2017c478bd9Sstevel@tonic-gate 			}
2027c478bd9Sstevel@tonic-gate 			for (p = pmtag; *p; p++) {
2037c478bd9Sstevel@tonic-gate 				if (!isalnum(*p)) {
2047c478bd9Sstevel@tonic-gate 					Saferrno = E_BADARGS;
2057c478bd9Sstevel@tonic-gate 					error("port monitor tag must be alphanumeric");
2067c478bd9Sstevel@tonic-gate 				}
2077c478bd9Sstevel@tonic-gate 			}
2087c478bd9Sstevel@tonic-gate 			break;
2097c478bd9Sstevel@tonic-gate 		case 'r':
2107c478bd9Sstevel@tonic-gate 			flag |= REMOVE;
2117c478bd9Sstevel@tonic-gate 			break;
2127c478bd9Sstevel@tonic-gate 		case 's':
2137c478bd9Sstevel@tonic-gate 			flag |= START;
2147c478bd9Sstevel@tonic-gate 			break;
2157c478bd9Sstevel@tonic-gate 		case 't':
2167c478bd9Sstevel@tonic-gate 			type = optarg;
2177c478bd9Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
2187c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
2197c478bd9Sstevel@tonic-gate 				error(BADINP);
2207c478bd9Sstevel@tonic-gate 			}
2217c478bd9Sstevel@tonic-gate 			if (strlen(type) > PMTYPESIZE) {
2227c478bd9Sstevel@tonic-gate 				type[PMTYPESIZE] = '\0';
2237c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "type too long, truncated to <%s>\n", type);
2247c478bd9Sstevel@tonic-gate 			}
2257c478bd9Sstevel@tonic-gate 			for (p = type; *p; p++) {
2267c478bd9Sstevel@tonic-gate 				if (!isalnum(*p)) {
2277c478bd9Sstevel@tonic-gate 					Saferrno = E_BADARGS;
2287c478bd9Sstevel@tonic-gate 					error("port monitor type must be alphanumeric");
2297c478bd9Sstevel@tonic-gate 				}
2307c478bd9Sstevel@tonic-gate 			}
2317c478bd9Sstevel@tonic-gate 			break;
2327c478bd9Sstevel@tonic-gate 		case 'v':
2337c478bd9Sstevel@tonic-gate 			flag |= ADD;
2347c478bd9Sstevel@tonic-gate 			version = atoi(optarg);
2357c478bd9Sstevel@tonic-gate 			if (version < 0) {
2367c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
2377c478bd9Sstevel@tonic-gate 				error("version number can not be negative");
2387c478bd9Sstevel@tonic-gate 			}
2397c478bd9Sstevel@tonic-gate 			break;
2407c478bd9Sstevel@tonic-gate 		case 'x':
2417c478bd9Sstevel@tonic-gate 			flag |= DBREAD;
2427c478bd9Sstevel@tonic-gate 			break;
2437c478bd9Sstevel@tonic-gate 		case 'y':
2447c478bd9Sstevel@tonic-gate 			flag |= ADD;
2457c478bd9Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
2467c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
2477c478bd9Sstevel@tonic-gate 				error(BADINP);
2487c478bd9Sstevel@tonic-gate 			}
2497c478bd9Sstevel@tonic-gate 			comment = optarg;
2507c478bd9Sstevel@tonic-gate 			break;
2517c478bd9Sstevel@tonic-gate 		case 'z':
2527c478bd9Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
2537c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
2547c478bd9Sstevel@tonic-gate 				error(BADINP);
2557c478bd9Sstevel@tonic-gate 			}
2567c478bd9Sstevel@tonic-gate 			script = optarg;
2577c478bd9Sstevel@tonic-gate 			break;
2587c478bd9Sstevel@tonic-gate 		case '?':
2597c478bd9Sstevel@tonic-gate 			errflg++;
2607c478bd9Sstevel@tonic-gate 		}
2617c478bd9Sstevel@tonic-gate 	}
2627c478bd9Sstevel@tonic-gate 	if (errflg || (optind < argc))
2637c478bd9Sstevel@tonic-gate 		usage(argv[0]);
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	if (badcnt) {
2667c478bd9Sstevel@tonic-gate 		/* bad flags were given to -f */
2677c478bd9Sstevel@tonic-gate 		Saferrno = E_BADARGS;
2687c478bd9Sstevel@tonic-gate 		(void) sprintf(buf,
2697c478bd9Sstevel@tonic-gate 		    "Invalid request, %s are not valid arguments for \"-f\"",
2707c478bd9Sstevel@tonic-gate 			badargs);
2717c478bd9Sstevel@tonic-gate 		error(buf);
2727c478bd9Sstevel@tonic-gate 	}
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	if ((ret = check_version(VERSION, SACTAB)) == 1) {
2757c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
2767c478bd9Sstevel@tonic-gate 		error("_sactab version number is incorrect");
2777c478bd9Sstevel@tonic-gate 	}
2787c478bd9Sstevel@tonic-gate 	else if (ret == 2) {
2797c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "could not open %s", SACTAB);
2807c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
2817c478bd9Sstevel@tonic-gate 		error(buf);
2827c478bd9Sstevel@tonic-gate 	}
2837c478bd9Sstevel@tonic-gate 	else if (ret == 3) {
2847c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "%s file is corrupt", SACTAB);
2857c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
2867c478bd9Sstevel@tonic-gate 		error(buf);
2877c478bd9Sstevel@tonic-gate 	}
2887c478bd9Sstevel@tonic-gate 	uid = getuid();
2897c478bd9Sstevel@tonic-gate 	switch (flag) {
2907c478bd9Sstevel@tonic-gate 	case ADD:
2917c478bd9Sstevel@tonic-gate 		if (uid) {
2927c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
2937c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
2947c478bd9Sstevel@tonic-gate 		}
2957c478bd9Sstevel@tonic-gate 		if (!sawaflag || !pmtag || !type || !command || (version < 0))
2967c478bd9Sstevel@tonic-gate 			usage(argv[0]);
2977c478bd9Sstevel@tonic-gate 		add_pm(pmtag, type, command, version, flags, count, script, comment);
2987c478bd9Sstevel@tonic-gate 		break;
2997c478bd9Sstevel@tonic-gate 	case REMOVE:
3007c478bd9Sstevel@tonic-gate 		if (uid) {
3017c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3027c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
3037c478bd9Sstevel@tonic-gate 		}
3047c478bd9Sstevel@tonic-gate 		if (!pmtag || type || script)
3057c478bd9Sstevel@tonic-gate 			usage(argv[0]);
3067c478bd9Sstevel@tonic-gate 		rem_pm(pmtag);
3077c478bd9Sstevel@tonic-gate 		break;
3087c478bd9Sstevel@tonic-gate 	case START:
3097c478bd9Sstevel@tonic-gate 		if (uid) {
3107c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3117c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
3127c478bd9Sstevel@tonic-gate 		}
3137c478bd9Sstevel@tonic-gate 		if (!pmtag || type || script)
3147c478bd9Sstevel@tonic-gate 			usage(argv[0]);
3157c478bd9Sstevel@tonic-gate 		start_pm(pmtag);
3167c478bd9Sstevel@tonic-gate 		break;
3177c478bd9Sstevel@tonic-gate 	case KILL:
3187c478bd9Sstevel@tonic-gate 		if (uid) {
3197c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3207c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
3217c478bd9Sstevel@tonic-gate 		}
3227c478bd9Sstevel@tonic-gate 		if (!pmtag || type || script)
3237c478bd9Sstevel@tonic-gate 			usage(argv[0]);
3247c478bd9Sstevel@tonic-gate 		kill_pm(pmtag);
3257c478bd9Sstevel@tonic-gate 		break;
3267c478bd9Sstevel@tonic-gate 	case ENABLE:
3277c478bd9Sstevel@tonic-gate 		if (uid) {
3287c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3297c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
3307c478bd9Sstevel@tonic-gate 		}
3317c478bd9Sstevel@tonic-gate 		if (!pmtag || type || script)
3327c478bd9Sstevel@tonic-gate 			usage(argv[0]);
3337c478bd9Sstevel@tonic-gate 		enable_pm(pmtag);
3347c478bd9Sstevel@tonic-gate 		break;
3357c478bd9Sstevel@tonic-gate 	case DISABLE:
3367c478bd9Sstevel@tonic-gate 		if (uid) {
3377c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3387c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
3397c478bd9Sstevel@tonic-gate 		}
3407c478bd9Sstevel@tonic-gate 		if (!pmtag || type || script)
3417c478bd9Sstevel@tonic-gate 			usage(argv[0]);
3427c478bd9Sstevel@tonic-gate 		disable_pm(pmtag);
3437c478bd9Sstevel@tonic-gate 		break;
3447c478bd9Sstevel@tonic-gate 	case LIST:
3457c478bd9Sstevel@tonic-gate 		conflag = 1;
3467c478bd9Sstevel@tonic-gate 		/* fall through */
3477c478bd9Sstevel@tonic-gate 	case PLIST:
3487c478bd9Sstevel@tonic-gate 		if ((pmtag && type) || script)
3497c478bd9Sstevel@tonic-gate 			usage(argv[0]);
3507c478bd9Sstevel@tonic-gate 		list_pms(pmtag, type, conflag);
3517c478bd9Sstevel@tonic-gate 		break;
3527c478bd9Sstevel@tonic-gate 	case DBREAD:
3537c478bd9Sstevel@tonic-gate 		if (uid) {
3547c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3557c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
3567c478bd9Sstevel@tonic-gate 		}
3577c478bd9Sstevel@tonic-gate 		if (type || script)
3587c478bd9Sstevel@tonic-gate 			usage(argv[0]);
3597c478bd9Sstevel@tonic-gate 		read_db(pmtag);
3607c478bd9Sstevel@tonic-gate 		break;
3617c478bd9Sstevel@tonic-gate 	case CONFIG:
3627c478bd9Sstevel@tonic-gate 		if (script && uid) {
3637c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3647c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
3657c478bd9Sstevel@tonic-gate 		}
3667c478bd9Sstevel@tonic-gate 		if (type || pmtag)
3677c478bd9Sstevel@tonic-gate 			usage(argv[0]);
3687c478bd9Sstevel@tonic-gate 		(void) do_config(script, "_sysconfig");
3697c478bd9Sstevel@tonic-gate 		break;
3707c478bd9Sstevel@tonic-gate 	case PCONFIG:
3717c478bd9Sstevel@tonic-gate 		if (script && uid) {
3727c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3737c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
3747c478bd9Sstevel@tonic-gate 		}
3757c478bd9Sstevel@tonic-gate 		if (!pmtag || type)
3767c478bd9Sstevel@tonic-gate 			usage(argv[0]);
3777c478bd9Sstevel@tonic-gate 		fp = fopen(SACTAB, "r");
3787c478bd9Sstevel@tonic-gate 		if (fp == NULL) {
3797c478bd9Sstevel@tonic-gate 			Saferrno = E_SYSERR;
3807c478bd9Sstevel@tonic-gate 			error("Could not open _sactab");
3817c478bd9Sstevel@tonic-gate 		}
3827c478bd9Sstevel@tonic-gate 		if (!find_pm(fp, pmtag)) {
3837c478bd9Sstevel@tonic-gate 			Saferrno = E_NOEXIST;
3847c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "Invalid request, %s does not exist", pmtag);
3857c478bd9Sstevel@tonic-gate 			error(buf);
3867c478bd9Sstevel@tonic-gate 		}
3877c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
3887c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "%s/_config", pmtag);
3897c478bd9Sstevel@tonic-gate 		(void) do_config(script, buf);
3907c478bd9Sstevel@tonic-gate 		break;
3917c478bd9Sstevel@tonic-gate 	default:
3927c478bd9Sstevel@tonic-gate 		/* we only get here if more than one flag bit was set */
3937c478bd9Sstevel@tonic-gate 		usage(argv[0]);
3947c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
3957c478bd9Sstevel@tonic-gate 	}
3967c478bd9Sstevel@tonic-gate 	quit();
3977c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
39834e48580Sdp 	return (0);
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate /*
4037c478bd9Sstevel@tonic-gate  * usage - print out a usage message
4047c478bd9Sstevel@tonic-gate  *
4057c478bd9Sstevel@tonic-gate  *	args:	cmdname - the name command was invoked with
4067c478bd9Sstevel@tonic-gate  */
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate void
4097c478bd9Sstevel@tonic-gate usage(cmdname)
4107c478bd9Sstevel@tonic-gate char *cmdname;
4117c478bd9Sstevel@tonic-gate {
4127c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "Usage:\t%s -a -p pmtag -t type -c cmd -v ver [ -f dx ] [ -n count ]\n", cmdname);
4137c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t\t[ -y comment ] [ -z script]\n");
4147c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -r -p pmtag\n", cmdname);
4157c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -s -p pmtag\n", cmdname);
4167c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -k -p pmtag\n", cmdname);
4177c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -e -p pmtag\n", cmdname);
4187c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -d -p pmtag\n", cmdname);
4197c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -l [ -p pmtag | -t type ]\n", cmdname);
4207c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -L [ -p pmtag | -t type ]\n", cmdname);
4217c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -g -p pmtag [ -z script ]\n", cmdname);
4227c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -G [ -z script ]\n", cmdname);
4237c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -x [ -p pmtag ]\n", cmdname);
4247c478bd9Sstevel@tonic-gate 	Saferrno = E_BADARGS;
4257c478bd9Sstevel@tonic-gate 	quit();
4267c478bd9Sstevel@tonic-gate }
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate /*
4307c478bd9Sstevel@tonic-gate  * add_pm - add a port monitor entry
4317c478bd9Sstevel@tonic-gate  *
4327c478bd9Sstevel@tonic-gate  *	args:	tag - port monitor's tag
4337c478bd9Sstevel@tonic-gate  *		type - port monitor's type
4347c478bd9Sstevel@tonic-gate  *		command - command string to invoke port monitor
4357c478bd9Sstevel@tonic-gate  *		version - version number of port monitor's pmtab
4367c478bd9Sstevel@tonic-gate  *		flags - port monitor flags
4377c478bd9Sstevel@tonic-gate  *		count - restart count
4387c478bd9Sstevel@tonic-gate  *		script - port monitor's configuration script
4397c478bd9Sstevel@tonic-gate  *		comment - comment describing port monitor
4407c478bd9Sstevel@tonic-gate  */
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate void
4437c478bd9Sstevel@tonic-gate add_pm(tag, type, command, version, flags, count, script, comment)
4447c478bd9Sstevel@tonic-gate char *tag;
4457c478bd9Sstevel@tonic-gate char *type;
4467c478bd9Sstevel@tonic-gate char *command;
4477c478bd9Sstevel@tonic-gate int version;
4487c478bd9Sstevel@tonic-gate long flags;
4497c478bd9Sstevel@tonic-gate int count;
4507c478bd9Sstevel@tonic-gate char *script;
4517c478bd9Sstevel@tonic-gate char *comment;
4527c478bd9Sstevel@tonic-gate {
4537c478bd9Sstevel@tonic-gate 	FILE *fp;		/* file pointer for _sactab */
4547c478bd9Sstevel@tonic-gate 	int fd;			/* scratch file descriptor */
4557c478bd9Sstevel@tonic-gate 	struct stat statbuf;	/* file status info */
4567c478bd9Sstevel@tonic-gate 	char buf[SIZE];		/* scratch buffer */
4577c478bd9Sstevel@tonic-gate 	char fname[SIZE];	/* scratch buffer for building names */
4587c478bd9Sstevel@tonic-gate 	register int i;		/* scratch variable */
459*22c9e08bSsn199410 	int retval = 0;		/* return value from invoke_rm() function */
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 	fp = fopen(SACTAB, "r");
4627c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
4637c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
4647c478bd9Sstevel@tonic-gate 		error("Could not open _sactab");
4657c478bd9Sstevel@tonic-gate 	}
4667c478bd9Sstevel@tonic-gate 	if (find_pm(fp, tag)) {
4677c478bd9Sstevel@tonic-gate 		Saferrno = E_DUP;
4687c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s already exists", tag);
4697c478bd9Sstevel@tonic-gate 		error(buf);
4707c478bd9Sstevel@tonic-gate 	}
4717c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate /*
4747c478bd9Sstevel@tonic-gate  * create the directories for it if needed and put in initial files
4757c478bd9Sstevel@tonic-gate  * (/etc/saf and /var/saf)
4767c478bd9Sstevel@tonic-gate  */
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	for (i = 0; i < 2; i++) {
4797c478bd9Sstevel@tonic-gate 		/* i == 0 do /etc/saf i == 1 do /var/saf */
4807c478bd9Sstevel@tonic-gate 		(void) sprintf(fname, "%s/%s", (i == 0 ) ? HOME : ALTHOME, tag);
4817c478bd9Sstevel@tonic-gate 		if (access(fname, 0) == 0) {
4827c478bd9Sstevel@tonic-gate 			/* something is there, find out what it is */
4837c478bd9Sstevel@tonic-gate 			if (stat(fname, &statbuf) < 0) {
4847c478bd9Sstevel@tonic-gate 				Saferrno = E_SYSERR;
4857c478bd9Sstevel@tonic-gate 				(void) sprintf(buf, "could not stat <%s>", fname);
4867c478bd9Sstevel@tonic-gate 				error(buf);
4877c478bd9Sstevel@tonic-gate 			}
4887c478bd9Sstevel@tonic-gate 			if ((statbuf.st_mode & S_IFMT) != S_IFDIR) {
4897c478bd9Sstevel@tonic-gate 				Saferrno = E_SYSERR;
4907c478bd9Sstevel@tonic-gate 				(void) sprintf(buf, "<%s> exists and is not a directory", fname);
4917c478bd9Sstevel@tonic-gate 				error(buf);
4927c478bd9Sstevel@tonic-gate 			}
4937c478bd9Sstevel@tonic-gate 			/* note: this removes the directory too */
494*22c9e08bSsn199410 			if ((retval = invoke_rm(fname)) != 0) {
4957c478bd9Sstevel@tonic-gate 				Saferrno = E_SYSERR;
496*22c9e08bSsn199410 				if (snprintf(buf, sizeof (buf),
497*22c9e08bSsn199410 				    "could not remove files under <%s>",
498*22c9e08bSsn199410 				    fname) >= sizeof (buf)) {
499*22c9e08bSsn199410 					snprintf(buf, sizeof (buf),
500*22c9e08bSsn199410 					    "tag too long");
501*22c9e08bSsn199410 				}
5027c478bd9Sstevel@tonic-gate 				error(buf);
5037c478bd9Sstevel@tonic-gate 			}
5047c478bd9Sstevel@tonic-gate 		}
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate /*
5077c478bd9Sstevel@tonic-gate  * create the directory
5087c478bd9Sstevel@tonic-gate  */
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 		if (mkdir(fname, 0755) < 0) {
5117c478bd9Sstevel@tonic-gate 			Saferrno = E_SYSERR;
5127c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "could not create directory <%s>", fname);
5137c478bd9Sstevel@tonic-gate 			cleandirs(tag);
5147c478bd9Sstevel@tonic-gate 			error(buf);
5157c478bd9Sstevel@tonic-gate 		}
5167c478bd9Sstevel@tonic-gate 	}
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate /*
5197c478bd9Sstevel@tonic-gate  * put in the config script, if specified
5207c478bd9Sstevel@tonic-gate  */
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	if (script) {
5237c478bd9Sstevel@tonic-gate 		(void) sprintf(fname, "%s/_config", tag);
5247c478bd9Sstevel@tonic-gate 		if (do_config(script, fname)) {
5257c478bd9Sstevel@tonic-gate 			cleandirs(tag);
5267c478bd9Sstevel@tonic-gate 			/* do_config put out any messages */
5277c478bd9Sstevel@tonic-gate 			quit();
5287c478bd9Sstevel@tonic-gate 		}
5297c478bd9Sstevel@tonic-gate 	}
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate /*
5327c478bd9Sstevel@tonic-gate  * create the communications pipe, but first make sure that the
5337c478bd9Sstevel@tonic-gate  * permissions we specify are what we get
5347c478bd9Sstevel@tonic-gate  */
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate 	(void) umask(0);
5377c478bd9Sstevel@tonic-gate 	(void) sprintf(fname, "%s/%s/_pmpipe", HOME, tag);
5387c478bd9Sstevel@tonic-gate 	if (mknod(fname, S_IFIFO | 0600, 0) < 0) {
5397c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
5407c478bd9Sstevel@tonic-gate 		cleandirs(tag);
5417c478bd9Sstevel@tonic-gate 		error("could not create communications pipe");
5427c478bd9Sstevel@tonic-gate 	}
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate /*
5457c478bd9Sstevel@tonic-gate  * create the _pid file
5467c478bd9Sstevel@tonic-gate  */
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 	(void) sprintf(fname, "%s/%s/_pid", HOME, tag);
5497c478bd9Sstevel@tonic-gate 	if ((fd = creat(fname, 0644)) < 0) {
5507c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
5517c478bd9Sstevel@tonic-gate 		cleandirs(tag);
5527c478bd9Sstevel@tonic-gate 		error("could not create _pid file");
5537c478bd9Sstevel@tonic-gate 	}
5547c478bd9Sstevel@tonic-gate 	(void) close(fd);
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate /*
5577c478bd9Sstevel@tonic-gate  * create the _pmtab file
5587c478bd9Sstevel@tonic-gate  */
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	(void) sprintf(fname, "%s/%s/_pmtab", HOME, tag);
5617c478bd9Sstevel@tonic-gate 	if ((fd = creat(fname, 0644)) < 0) {
5627c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
5637c478bd9Sstevel@tonic-gate 		cleandirs(tag);
5647c478bd9Sstevel@tonic-gate 		error("could not create _pmtab file");
5657c478bd9Sstevel@tonic-gate 	}
5667c478bd9Sstevel@tonic-gate 	(void) sprintf(buf, "%s%d\n", VSTR, version);
5677c478bd9Sstevel@tonic-gate 	if (write(fd, buf, (unsigned) strlen(buf)) != strlen(buf)) {
5687c478bd9Sstevel@tonic-gate 		(void) close(fd);
5697c478bd9Sstevel@tonic-gate 		(void) unlink(fname);
5707c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
5717c478bd9Sstevel@tonic-gate 		cleandirs(tag);
5727c478bd9Sstevel@tonic-gate 		error("error initializing _pmtab");
5737c478bd9Sstevel@tonic-gate 	}
5747c478bd9Sstevel@tonic-gate 	(void) close(fd);
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate /*
5777c478bd9Sstevel@tonic-gate  * isolate the command name, but remember it since strtok() trashes it
5787c478bd9Sstevel@tonic-gate  */
5797c478bd9Sstevel@tonic-gate 
580*22c9e08bSsn199410 	if (strlcpy(buf, command, sizeof (buf)) >= sizeof (buf)) {
581*22c9e08bSsn199410 		Saferrno = E_SYSERR;
582*22c9e08bSsn199410 		cleandirs(tag);
583*22c9e08bSsn199410 		error("command string too long");
584*22c9e08bSsn199410 	}
585*22c9e08bSsn199410 
5867c478bd9Sstevel@tonic-gate 	(void) strtok(command, " \t");
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate /*
5897c478bd9Sstevel@tonic-gate  * check out the command - let addition succeed if it doesn't exist (assume
5907c478bd9Sstevel@tonic-gate  * it will be added later); fail anything else
5917c478bd9Sstevel@tonic-gate  */
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	if (access(command, 0) == 0) {
5947c478bd9Sstevel@tonic-gate 		if (stat(command, &statbuf) < 0) {
5957c478bd9Sstevel@tonic-gate 			Saferrno = E_SYSERR;
5967c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "Could not stat <%s>\n", command);
5977c478bd9Sstevel@tonic-gate 			cleandirs(tag);
5987c478bd9Sstevel@tonic-gate 			quit();
5997c478bd9Sstevel@tonic-gate 		}
6007c478bd9Sstevel@tonic-gate 		if (!(statbuf.st_mode & 0111)) {
6017c478bd9Sstevel@tonic-gate 			Saferrno = E_BADARGS;
6027c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s not executable\n", command);
6037c478bd9Sstevel@tonic-gate 			cleandirs(tag);
6047c478bd9Sstevel@tonic-gate 			quit();
6057c478bd9Sstevel@tonic-gate 		}
6067c478bd9Sstevel@tonic-gate 		if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
6077c478bd9Sstevel@tonic-gate 			Saferrno = E_BADARGS;
6087c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s not a regular file\n", command);
6097c478bd9Sstevel@tonic-gate 			cleandirs(tag);
6107c478bd9Sstevel@tonic-gate 			quit();
6117c478bd9Sstevel@tonic-gate 		}
6127c478bd9Sstevel@tonic-gate 	}
6137c478bd9Sstevel@tonic-gate 	else {
6147c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "warning - %s does not exist\n", command);
6157c478bd9Sstevel@tonic-gate 	}
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate /*
6187c478bd9Sstevel@tonic-gate  * add the line
6197c478bd9Sstevel@tonic-gate  */
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 	fp = fopen(SACTAB, "a");
6227c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
6237c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
6247c478bd9Sstevel@tonic-gate 		cleandirs(tag);
6257c478bd9Sstevel@tonic-gate 		error("Could not open _sactab");
6267c478bd9Sstevel@tonic-gate 	}
6277c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "%s:%s:%s:%d:%s\t#%s\n", tag, type,
6287c478bd9Sstevel@tonic-gate 		(flags ? pflags(flags, FALSE) : ""), count, buf,
6297c478bd9Sstevel@tonic-gate 		(comment ? comment : ""));
6307c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate /*
6347c478bd9Sstevel@tonic-gate  * tell the SAC to read _sactab if its there (i.e. single user)
6357c478bd9Sstevel@tonic-gate  */
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 	if (sac_home())
6387c478bd9Sstevel@tonic-gate 		read_db(NULL);
6397c478bd9Sstevel@tonic-gate 	return;
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate /*
6447c478bd9Sstevel@tonic-gate  * cleandirs - remove anything that might have been created (i.e. failed
6457c478bd9Sstevel@tonic-gate  *	addition.  Saferrno is set elsewhere; this is strictly an attempt
6467c478bd9Sstevel@tonic-gate  *	to clean up what mess we've left, so don't check to see if the
6477c478bd9Sstevel@tonic-gate  *	cleanup worked.
6487c478bd9Sstevel@tonic-gate  *
6497c478bd9Sstevel@tonic-gate  *	args:	tag - tag of port monitor whose trees should be removed
6507c478bd9Sstevel@tonic-gate  */
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate void
6537c478bd9Sstevel@tonic-gate cleandirs(tag)
6547c478bd9Sstevel@tonic-gate char *tag;
6557c478bd9Sstevel@tonic-gate {
6567c478bd9Sstevel@tonic-gate 	char buf[SIZE];		/* scratch buffer */
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 	/* note: this removes the directory too, first zap /etc/saf/<tag> */
659*22c9e08bSsn199410 	if (snprintf(buf, sizeof (buf), "%s/%s", HOME, tag) >= sizeof (buf))
660*22c9e08bSsn199410 		(void) fprintf(stderr, "tag too long\n");
661*22c9e08bSsn199410 	else
662*22c9e08bSsn199410 		(void) invoke_rm(buf);
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 	/* now remove /var/saf/<tag> */
665*22c9e08bSsn199410 	if (snprintf(buf, sizeof (buf), "%s/%s", ALTHOME, tag) >= sizeof (buf))
666*22c9e08bSsn199410 		(void) fprintf(stderr, "tag too long\n");
667*22c9e08bSsn199410 	else
6687c478bd9Sstevel@tonic-gate 		(void) rmdir(buf);
6697c478bd9Sstevel@tonic-gate }
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate /*
6737c478bd9Sstevel@tonic-gate  * rem_pm - remove a port monitor
6747c478bd9Sstevel@tonic-gate  *
6757c478bd9Sstevel@tonic-gate  *	args:	tag - tag of port monitor to be removed
6767c478bd9Sstevel@tonic-gate  */
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate void
6797c478bd9Sstevel@tonic-gate rem_pm(tag)
6807c478bd9Sstevel@tonic-gate char *tag;
6817c478bd9Sstevel@tonic-gate {
6827c478bd9Sstevel@tonic-gate 	FILE *fp;		/* file pointer for _sactab */
6837c478bd9Sstevel@tonic-gate 	FILE *tfp;		/* file pointer for temp file */
6847c478bd9Sstevel@tonic-gate 	int line;		/* line number entry is on */
6857c478bd9Sstevel@tonic-gate 	char *tname;		/* temp file name */
6867c478bd9Sstevel@tonic-gate 	char buf[SIZE];		/* scratch buffer */
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 	fp = fopen(SACTAB, "r");
6897c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
6907c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
6917c478bd9Sstevel@tonic-gate 		error("Could not open _sactab");
6927c478bd9Sstevel@tonic-gate 	}
6937c478bd9Sstevel@tonic-gate 	if ((line = find_pm(fp, tag)) == 0) {
6947c478bd9Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
6957c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist", tag);
6967c478bd9Sstevel@tonic-gate 		error(buf);
6977c478bd9Sstevel@tonic-gate 	}
6987c478bd9Sstevel@tonic-gate 	tname = make_tempname("_sactab");
6997c478bd9Sstevel@tonic-gate 	tfp = open_temp(tname);
7007c478bd9Sstevel@tonic-gate 	if (line != 1) {
7017c478bd9Sstevel@tonic-gate 		if (copy_file(fp, tfp, 1, line - 1)) {
7027c478bd9Sstevel@tonic-gate 			(void) unlink(tname);
7037c478bd9Sstevel@tonic-gate 			Saferrno = E_SYSERR;
7047c478bd9Sstevel@tonic-gate 			error("error accessing temp file");
7057c478bd9Sstevel@tonic-gate 		}
7067c478bd9Sstevel@tonic-gate 	}
7077c478bd9Sstevel@tonic-gate 	if (copy_file(fp, tfp, line + 1, -1)) {
7087c478bd9Sstevel@tonic-gate 		(void) unlink(tname);
7097c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
7107c478bd9Sstevel@tonic-gate 		error("error accessing temp file");
7117c478bd9Sstevel@tonic-gate 	}
7127c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
7137c478bd9Sstevel@tonic-gate 	if (fclose(tfp) == EOF) {
7147c478bd9Sstevel@tonic-gate 		(void) unlink(tname);
7157c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
7167c478bd9Sstevel@tonic-gate 		error("error closing tempfile");
7177c478bd9Sstevel@tonic-gate 	}
7187c478bd9Sstevel@tonic-gate 	/* note - replace only returns if successful */
7197c478bd9Sstevel@tonic-gate 	replace("_sactab", tname);
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate /*
7227c478bd9Sstevel@tonic-gate  * tell the SAC to read _sactab if its there (i.e. single user)
7237c478bd9Sstevel@tonic-gate  */
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 	if (sac_home())
7267c478bd9Sstevel@tonic-gate 		read_db(NULL);
7277c478bd9Sstevel@tonic-gate 	return;
7287c478bd9Sstevel@tonic-gate }
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate /*
7327c478bd9Sstevel@tonic-gate  * start_pm - start a particular port monitor
7337c478bd9Sstevel@tonic-gate  *
7347c478bd9Sstevel@tonic-gate  *	args:	tag - tag of port monitor to be started
7357c478bd9Sstevel@tonic-gate  */
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate void
7387c478bd9Sstevel@tonic-gate start_pm(tag)
7397c478bd9Sstevel@tonic-gate char *tag;
7407c478bd9Sstevel@tonic-gate {
7417c478bd9Sstevel@tonic-gate 	struct admcmd cmd;			/* command structure */
7427c478bd9Sstevel@tonic-gate 	register struct admcmd *ap = &cmd;	/* and a pointer to it */
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 	ap->ac_mtype = AC_START;
7457c478bd9Sstevel@tonic-gate 	(void) strcpy(ap->ac_tag, tag);
7467c478bd9Sstevel@tonic-gate 	ap->ac_pid = getpid();
7477c478bd9Sstevel@tonic-gate 	sendcmd(ap, NULL, tag);
7487c478bd9Sstevel@tonic-gate 	return;
7497c478bd9Sstevel@tonic-gate }
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate /*
7537c478bd9Sstevel@tonic-gate  * kill_pm - stop a particular port monitor
7547c478bd9Sstevel@tonic-gate  *
7557c478bd9Sstevel@tonic-gate  *	args:	tag - tag of port monitor to be stopped
7567c478bd9Sstevel@tonic-gate  */
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate void
7597c478bd9Sstevel@tonic-gate kill_pm(tag)
7607c478bd9Sstevel@tonic-gate char *tag;
7617c478bd9Sstevel@tonic-gate {
7627c478bd9Sstevel@tonic-gate 	struct admcmd cmd;			/* command structure */
7637c478bd9Sstevel@tonic-gate 	register struct admcmd *ap = &cmd;	/* and a pointer to it */
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 	ap->ac_mtype = AC_KILL;
7667c478bd9Sstevel@tonic-gate 	(void) strcpy(ap->ac_tag, tag);
7677c478bd9Sstevel@tonic-gate 	ap->ac_pid = getpid();
7687c478bd9Sstevel@tonic-gate 	sendcmd(ap, NULL, tag);
7697c478bd9Sstevel@tonic-gate 	return;
7707c478bd9Sstevel@tonic-gate }
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate 
7737c478bd9Sstevel@tonic-gate /*
7747c478bd9Sstevel@tonic-gate  * enable_pm - enable a particular port monitor
7757c478bd9Sstevel@tonic-gate  *
7767c478bd9Sstevel@tonic-gate  *	args:	tag - tag of port monitor to be enabled
7777c478bd9Sstevel@tonic-gate  */
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate void
7807c478bd9Sstevel@tonic-gate enable_pm(tag)
7817c478bd9Sstevel@tonic-gate char *tag;
7827c478bd9Sstevel@tonic-gate {
7837c478bd9Sstevel@tonic-gate 	struct admcmd cmd;			/* command structure */
7847c478bd9Sstevel@tonic-gate 	register struct admcmd *ap = &cmd;	/* and a pointer to it */
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate 	ap->ac_mtype = AC_ENABLE;
7877c478bd9Sstevel@tonic-gate 	(void) strcpy(ap->ac_tag, tag);
7887c478bd9Sstevel@tonic-gate 	ap->ac_pid = getpid();
7897c478bd9Sstevel@tonic-gate 	sendcmd(ap, NULL, tag);
7907c478bd9Sstevel@tonic-gate 	return;
7917c478bd9Sstevel@tonic-gate }
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate /*
7957c478bd9Sstevel@tonic-gate  * disable_pm - disable a particular port monitor
7967c478bd9Sstevel@tonic-gate  *
7977c478bd9Sstevel@tonic-gate  *	args:	tag - tag of port monitor to be disabled
7987c478bd9Sstevel@tonic-gate  */
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate void
8017c478bd9Sstevel@tonic-gate disable_pm(tag)
8027c478bd9Sstevel@tonic-gate char *tag;
8037c478bd9Sstevel@tonic-gate {
8047c478bd9Sstevel@tonic-gate 	struct admcmd cmd;			/* command structure */
8057c478bd9Sstevel@tonic-gate 	register struct admcmd *ap = &cmd;	/* and a pointer to it */
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate 	ap->ac_mtype = AC_DISABLE;
8087c478bd9Sstevel@tonic-gate 	(void) strcpy(ap->ac_tag, tag);
8097c478bd9Sstevel@tonic-gate 	ap->ac_pid = getpid();
8107c478bd9Sstevel@tonic-gate 	sendcmd(ap, NULL, tag);
8117c478bd9Sstevel@tonic-gate 	return;
8127c478bd9Sstevel@tonic-gate }
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate /*
8167c478bd9Sstevel@tonic-gate  * read_db - tell SAC or a port monitor to read its administrative file.
8177c478bd9Sstevel@tonic-gate  *
8187c478bd9Sstevel@tonic-gate  *	args:	tag - tag of port monitor that should read its administrative
8197c478bd9Sstevel@tonic-gate  *		      file.  If NULL, it means SAC should.
8207c478bd9Sstevel@tonic-gate  */
8217c478bd9Sstevel@tonic-gate 
8227c478bd9Sstevel@tonic-gate void
8237c478bd9Sstevel@tonic-gate read_db(tag)
8247c478bd9Sstevel@tonic-gate char *tag;
8257c478bd9Sstevel@tonic-gate {
8267c478bd9Sstevel@tonic-gate 	struct admcmd cmd;			/* command structure */
8277c478bd9Sstevel@tonic-gate 	register struct admcmd *ap = &cmd;	/* and a pointer to it */
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate 	ap->ac_mtype = (tag) ? AC_PMREAD : AC_SACREAD;
8307c478bd9Sstevel@tonic-gate 	if (tag)
8317c478bd9Sstevel@tonic-gate 		(void) strcpy(ap->ac_tag, tag);
8327c478bd9Sstevel@tonic-gate 	ap->ac_pid = getpid();
8337c478bd9Sstevel@tonic-gate 	sendcmd(ap, NULL, tag);
8347c478bd9Sstevel@tonic-gate 	return;
8357c478bd9Sstevel@tonic-gate }
8367c478bd9Sstevel@tonic-gate 
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate /*
8397c478bd9Sstevel@tonic-gate  * list_pms - request information about port monitors from SAC and output
8407c478bd9Sstevel@tonic-gate  *		requested info
8417c478bd9Sstevel@tonic-gate  *
8427c478bd9Sstevel@tonic-gate  *	args:	pmtag - tag of port monitor to be listed (may be null)
8437c478bd9Sstevel@tonic-gate  *		pmtype - type of port monitors to be listed (may be null)
8447c478bd9Sstevel@tonic-gate  *		oflag - true if output should be easily parseable
8457c478bd9Sstevel@tonic-gate  */
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate void
8487c478bd9Sstevel@tonic-gate list_pms(pmtag, pmtype, oflag)
8497c478bd9Sstevel@tonic-gate char *pmtag;
8507c478bd9Sstevel@tonic-gate char *pmtype;
8517c478bd9Sstevel@tonic-gate int oflag;
8527c478bd9Sstevel@tonic-gate {
8537c478bd9Sstevel@tonic-gate 	struct admcmd acmd;			/* command structure */
8547c478bd9Sstevel@tonic-gate 	register struct admcmd *ap = &acmd;	/* and a pointer to it */
8557c478bd9Sstevel@tonic-gate 	int nprint = 0;				/* count # of PMs printed */
8567c478bd9Sstevel@tonic-gate 	char *p;				/* scratch pointer */
8577c478bd9Sstevel@tonic-gate 	char *tag;				/* returned tag */
8587c478bd9Sstevel@tonic-gate 	char *type;				/* returned type */
8597c478bd9Sstevel@tonic-gate 	char *flags;				/* returned flags */
8607c478bd9Sstevel@tonic-gate 	char *rsmax;				/* returned restart count */
8617c478bd9Sstevel@tonic-gate 	char *state;				/* returned state */
8627c478bd9Sstevel@tonic-gate 	char *cmd;				/* returned command string */
8637c478bd9Sstevel@tonic-gate 	char *comment;				/* returned comment string */
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate /*
8667c478bd9Sstevel@tonic-gate  * if sac isn't there (single user), provide info direct from _sactab
8677c478bd9Sstevel@tonic-gate  * note: when this routine returns, the process exits, so there is no
8687c478bd9Sstevel@tonic-gate  * need to free up any memory
8697c478bd9Sstevel@tonic-gate  */
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate 	p = NULL;
8727c478bd9Sstevel@tonic-gate 	if (sac_home()) {
8737c478bd9Sstevel@tonic-gate 		ap->ac_mtype = AC_STATUS;
8747c478bd9Sstevel@tonic-gate 		ap->ac_tag[0] = '\0';
8757c478bd9Sstevel@tonic-gate 		ap->ac_pid = getpid();
8767c478bd9Sstevel@tonic-gate 		sendcmd(ap, &p, NULL);
8777c478bd9Sstevel@tonic-gate 	}
8787c478bd9Sstevel@tonic-gate 	else {
8797c478bd9Sstevel@tonic-gate 		single_print(&p);
8807c478bd9Sstevel@tonic-gate 	}
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate /*
8837c478bd9Sstevel@tonic-gate  * SAC sends back info in condensed form, we have to separate it out
8847c478bd9Sstevel@tonic-gate  * fields come in ':' separated, records are separated by newlines
8857c478bd9Sstevel@tonic-gate  */
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 	while (p && *p) {
8887c478bd9Sstevel@tonic-gate 		tag = getfield(&p, ':');	/* PM tag */
8897c478bd9Sstevel@tonic-gate 		type = getfield(&p, ':');	/* PM type */
8907c478bd9Sstevel@tonic-gate 		flags = getfield(&p, ':');	/* flags */
8917c478bd9Sstevel@tonic-gate 		rsmax = getfield(&p, ':');	/* restart count */
8927c478bd9Sstevel@tonic-gate 		state = pstate((unchar) atoi(getfield(&p, ':')));	/* state in nice output format */
8937c478bd9Sstevel@tonic-gate 		cmd = getfield(&p, ':');	/* command */
8947c478bd9Sstevel@tonic-gate 		comment = getfield(&p, '\n');	/* comment */
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate /*
8987c478bd9Sstevel@tonic-gate  * print out if no selectors specified, else check to see if
8997c478bd9Sstevel@tonic-gate  * a selector matched
9007c478bd9Sstevel@tonic-gate  */
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 		if ((!pmtag && !pmtype) || (pmtag && !strcmp(pmtag, tag)) || (pmtype && !strcmp(pmtype, type))) {
9037c478bd9Sstevel@tonic-gate 			if (oflag) {
9047c478bd9Sstevel@tonic-gate 				(void) printf("%s:%s:%s:%s:%s:%s#%s\n", tag, type, pflags(atol(flags), FALSE),
9057c478bd9Sstevel@tonic-gate 						rsmax, state, cmd, comment);
9067c478bd9Sstevel@tonic-gate 			}
9077c478bd9Sstevel@tonic-gate 			else {
9087c478bd9Sstevel@tonic-gate 				if (nprint == 0) {
9097c478bd9Sstevel@tonic-gate 					(void) printf("PMTAG          PMTYPE         FLGS RCNT STATUS     COMMAND\n");
9107c478bd9Sstevel@tonic-gate 				}
9117c478bd9Sstevel@tonic-gate 				(void) printf("%-14s %-14s %-4s %-4s %-10s %s #%s\n", tag, type, pflags(atol(flags), TRUE),
9127c478bd9Sstevel@tonic-gate 						rsmax, state, cmd, comment);
9137c478bd9Sstevel@tonic-gate 			}
9147c478bd9Sstevel@tonic-gate 			nprint++;
9157c478bd9Sstevel@tonic-gate 		}
9167c478bd9Sstevel@tonic-gate 	}
9177c478bd9Sstevel@tonic-gate 	/*
9187c478bd9Sstevel@tonic-gate 	 * if we didn't find any valid ones, indicate an error (note: 1 and
9197c478bd9Sstevel@tonic-gate 	 * only 1 of the if statements should be true)
9207c478bd9Sstevel@tonic-gate 	 */
9217c478bd9Sstevel@tonic-gate 	if (nprint == 0) {
9227c478bd9Sstevel@tonic-gate 		if (pmtype)
9237c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "Invalid request, %s does not exist\n", pmtype);
9247c478bd9Sstevel@tonic-gate 		else if (pmtag)
9257c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "Invalid request, %s does not exist\n", pmtag);
9267c478bd9Sstevel@tonic-gate 		else if (!pmtag && !pmtype)
9277c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "No port monitors defined\n");
9287c478bd9Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
9297c478bd9Sstevel@tonic-gate 	}
9307c478bd9Sstevel@tonic-gate 	return;
9317c478bd9Sstevel@tonic-gate }
9327c478bd9Sstevel@tonic-gate 
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate /*
9357c478bd9Sstevel@tonic-gate  * getfield - retrieve and return a field from the sac "status" string (input
9367c478bd9Sstevel@tonic-gate  *	argument is modified to point to next field as a side-effect)
9377c478bd9Sstevel@tonic-gate  *
9387c478bd9Sstevel@tonic-gate  *	args:	p - address of remaining portion of string
9397c478bd9Sstevel@tonic-gate  *		sepchar - field terminator character
9407c478bd9Sstevel@tonic-gate  */
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate char *
9437c478bd9Sstevel@tonic-gate getfield(p, sepchar)
9447c478bd9Sstevel@tonic-gate char **p;
9457c478bd9Sstevel@tonic-gate char sepchar;
9467c478bd9Sstevel@tonic-gate {
9477c478bd9Sstevel@tonic-gate 	char *savep;	/* for saving argument */
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate 	savep = *p;
9507c478bd9Sstevel@tonic-gate 	*p = strchr(*p, sepchar);
9517c478bd9Sstevel@tonic-gate 	if (*p == NULL) {
9527c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
9537c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Improper message from SAC\n");
9547c478bd9Sstevel@tonic-gate 		return(NULL);
9557c478bd9Sstevel@tonic-gate 	}
9567c478bd9Sstevel@tonic-gate 	**p = '\0';
9577c478bd9Sstevel@tonic-gate 	(*p)++;
9587c478bd9Sstevel@tonic-gate 	return(savep);
9597c478bd9Sstevel@tonic-gate }
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate /*
9637c478bd9Sstevel@tonic-gate  * single_print - print out _sactab if sac not at home (should only happen
9647c478bd9Sstevel@tonic-gate  *	in single user mode
9657c478bd9Sstevel@tonic-gate  *
9667c478bd9Sstevel@tonic-gate  *	args:	p - address of pointer where formatted data should be
9677c478bd9Sstevel@tonic-gate  *		    placed (space allocated here)
9687c478bd9Sstevel@tonic-gate  */
9697c478bd9Sstevel@tonic-gate 
9707c478bd9Sstevel@tonic-gate void
9717c478bd9Sstevel@tonic-gate single_print(p)
9727c478bd9Sstevel@tonic-gate char **p;
9737c478bd9Sstevel@tonic-gate {
9747c478bd9Sstevel@tonic-gate 	FILE *fp;				/* file pointer for _sactab */
9757c478bd9Sstevel@tonic-gate 	struct stat statbuf;			/* file status info */
9767c478bd9Sstevel@tonic-gate 	register char *tp1;			/* scratch pointer */
9777c478bd9Sstevel@tonic-gate 	register char *tp2;			/* scratch pointer */
9787c478bd9Sstevel@tonic-gate 	struct sactab stab;			/* place to hold parsed info */
9797c478bd9Sstevel@tonic-gate 	register struct sactab *sp = &stab;	/* and a pointer to it */
9807c478bd9Sstevel@tonic-gate 	char buf[SIZE];				/* scratch buffer */
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate 	fp = fopen(SACTAB, "r");
9837c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
9847c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
9857c478bd9Sstevel@tonic-gate 		error("Could not open _sactab");
9867c478bd9Sstevel@tonic-gate 	}
9877c478bd9Sstevel@tonic-gate 	if (fstat(fileno(fp), &statbuf) < 0) {
9887c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
9897c478bd9Sstevel@tonic-gate 		error("could not stat _sactab");
9907c478bd9Sstevel@tonic-gate 	}
9917c478bd9Sstevel@tonic-gate 
9927c478bd9Sstevel@tonic-gate /*
9937c478bd9Sstevel@tonic-gate  * allocate space to build return string, twice file size should be more
9947c478bd9Sstevel@tonic-gate  * than enough (and make sure it's zero'ed out)
9957c478bd9Sstevel@tonic-gate  */
9967c478bd9Sstevel@tonic-gate 
9977c478bd9Sstevel@tonic-gate 	tp1 = calloc(2 * statbuf.st_size, sizeof(char));
9987c478bd9Sstevel@tonic-gate 	if (tp1 == NULL) {
9997c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
10007c478bd9Sstevel@tonic-gate 		error("could not allocate storage");
10017c478bd9Sstevel@tonic-gate 	}
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate /*
10047c478bd9Sstevel@tonic-gate  * read the file and build the string
10057c478bd9Sstevel@tonic-gate  */
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate 	while (fgets(buf, SIZE, fp)) {
10087c478bd9Sstevel@tonic-gate 		tp2 = trim(buf);
10097c478bd9Sstevel@tonic-gate 		if (*tp2 == '\0')
10107c478bd9Sstevel@tonic-gate 			continue;
10117c478bd9Sstevel@tonic-gate 		parse(tp2, &stab);
10127c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "%s:%s:%d:%d:%d:%s:%s\n", sp->sc_tag, sp->sc_type,
10137c478bd9Sstevel@tonic-gate 			sp->sc_flags, sp->sc_rsmax, SSTATE, sp->sc_cmd, sp->sc_comment);
10147c478bd9Sstevel@tonic-gate 		(void) strcat(tp1, buf);
10157c478bd9Sstevel@tonic-gate 		free(sp->sc_cmd);
10167c478bd9Sstevel@tonic-gate 		free(sp->sc_comment);
10177c478bd9Sstevel@tonic-gate 	}
10187c478bd9Sstevel@tonic-gate 	if (!feof(fp)) {
10197c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
10207c478bd9Sstevel@tonic-gate 		error("error reading _sactab");
10217c478bd9Sstevel@tonic-gate 	}
10227c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
10237c478bd9Sstevel@tonic-gate 
10247c478bd9Sstevel@tonic-gate /*
10257c478bd9Sstevel@tonic-gate  * point at the just-built string
10267c478bd9Sstevel@tonic-gate  */
10277c478bd9Sstevel@tonic-gate 
10287c478bd9Sstevel@tonic-gate 	*p = tp1;
10297c478bd9Sstevel@tonic-gate 	return;
10307c478bd9Sstevel@tonic-gate }
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate 
10337c478bd9Sstevel@tonic-gate /*
10347c478bd9Sstevel@tonic-gate  * openpipe - open up command pipe to SAC
10357c478bd9Sstevel@tonic-gate  */
10367c478bd9Sstevel@tonic-gate 
103734e48580Sdp int
10387c478bd9Sstevel@tonic-gate openpipe()
10397c478bd9Sstevel@tonic-gate {
10407c478bd9Sstevel@tonic-gate 	int fd;		/* file descriptor associated with command pipe */
10417c478bd9Sstevel@tonic-gate 
10427c478bd9Sstevel@tonic-gate 	fd = open(CMDPIPE, O_RDWR);
10437c478bd9Sstevel@tonic-gate 	if (fd < 0) {
10447c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
10457c478bd9Sstevel@tonic-gate 		error(SACERR);
10467c478bd9Sstevel@tonic-gate 	}
10477c478bd9Sstevel@tonic-gate 
10487c478bd9Sstevel@tonic-gate /*
10497c478bd9Sstevel@tonic-gate  * lock pipe to insure serial access, lock will disappear if process dies
10507c478bd9Sstevel@tonic-gate  */
10517c478bd9Sstevel@tonic-gate 
10527c478bd9Sstevel@tonic-gate 	if (lockf(fd, F_LOCK, 0) < 0) {
10537c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
10547c478bd9Sstevel@tonic-gate 		error("unable to lock command pipe");
10557c478bd9Sstevel@tonic-gate 	}
10567c478bd9Sstevel@tonic-gate 	return(fd);
10577c478bd9Sstevel@tonic-gate }
10587c478bd9Sstevel@tonic-gate 
10597c478bd9Sstevel@tonic-gate 
10607c478bd9Sstevel@tonic-gate /*
10617c478bd9Sstevel@tonic-gate  * sendcmd - send a command to the SAC
10627c478bd9Sstevel@tonic-gate  *
10637c478bd9Sstevel@tonic-gate  *	args:	ap - pointer to command to send
10647c478bd9Sstevel@tonic-gate  *		info - pointer to return information from the SAC
10657c478bd9Sstevel@tonic-gate  *		tag - tag of port monitor to which the command applies (may
10667c478bd9Sstevel@tonic-gate  *		      be NULL)
10677c478bd9Sstevel@tonic-gate  */
10687c478bd9Sstevel@tonic-gate 
10697c478bd9Sstevel@tonic-gate void
10707c478bd9Sstevel@tonic-gate sendcmd(ap, info, tag)
10717c478bd9Sstevel@tonic-gate struct admcmd *ap;
10727c478bd9Sstevel@tonic-gate char **info;
10737c478bd9Sstevel@tonic-gate char *tag;
10747c478bd9Sstevel@tonic-gate {
10757c478bd9Sstevel@tonic-gate 	int fd;		/* file descriptor of command pipe */
10767c478bd9Sstevel@tonic-gate 
10777c478bd9Sstevel@tonic-gate 	fd = openpipe();
10787c478bd9Sstevel@tonic-gate 	if (write(fd, ap, sizeof(struct admcmd)) < 0) {
10797c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
10807c478bd9Sstevel@tonic-gate 		error(SACERR);
10817c478bd9Sstevel@tonic-gate 	}
10827c478bd9Sstevel@tonic-gate 	checkresp(fd, info, tag);
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate /*
10857c478bd9Sstevel@tonic-gate  * unlock the command pipe - not really necessary since we're about to close
10867c478bd9Sstevel@tonic-gate  */
10877c478bd9Sstevel@tonic-gate 
10887c478bd9Sstevel@tonic-gate 	(void) lockf(fd, F_ULOCK, 0);
10897c478bd9Sstevel@tonic-gate 	(void) close(fd);
10907c478bd9Sstevel@tonic-gate 	return;
10917c478bd9Sstevel@tonic-gate }
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate 
10947c478bd9Sstevel@tonic-gate /*
10957c478bd9Sstevel@tonic-gate  * checkresp - check the SAC's response to our command
10967c478bd9Sstevel@tonic-gate  *
10977c478bd9Sstevel@tonic-gate  *	args:	fd - file descriptor of command pipe
10987c478bd9Sstevel@tonic-gate  *		info - pointer to return and info send along by SAC
10997c478bd9Sstevel@tonic-gate  *		tag - tag of port monitor that the command had been
11007c478bd9Sstevel@tonic-gate  *		      for, only used for error reporting
11017c478bd9Sstevel@tonic-gate  */
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate void
11047c478bd9Sstevel@tonic-gate checkresp(fd, info, tag)
11057c478bd9Sstevel@tonic-gate int fd;
11067c478bd9Sstevel@tonic-gate char **info;
11077c478bd9Sstevel@tonic-gate char *tag;
11087c478bd9Sstevel@tonic-gate {
11097c478bd9Sstevel@tonic-gate 	struct admack ack;			/* acknowledgment struct */
11107c478bd9Sstevel@tonic-gate 	register struct admack *ak = &ack;	/* and a pointer to it */
11117c478bd9Sstevel@tonic-gate 	pid_t pid;				/* my pid */
11127c478bd9Sstevel@tonic-gate 	struct sigaction sigact;		/* signal handler setup */
11137c478bd9Sstevel@tonic-gate 
11147c478bd9Sstevel@tonic-gate /*
11157c478bd9Sstevel@tonic-gate  * make sure this ack is meant for me, put an alarm around the read
11167c478bd9Sstevel@tonic-gate  * so we don't hang out forever.
11177c478bd9Sstevel@tonic-gate  */
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate 	pid = getpid();
11207c478bd9Sstevel@tonic-gate 	sigact.sa_flags = 0;
11217c478bd9Sstevel@tonic-gate 	sigact.sa_handler = catch;
11227c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&sigact.sa_mask);
11237c478bd9Sstevel@tonic-gate 	(void) sigaddset(&sigact.sa_mask, SIGALRM);
11247c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGALRM, &sigact, NULL);
11257c478bd9Sstevel@tonic-gate 	(void) alarm(10);
11267c478bd9Sstevel@tonic-gate 	do {
11277c478bd9Sstevel@tonic-gate 		if (read(fd, ak, sizeof(ack)) != sizeof(ack)) {
11287c478bd9Sstevel@tonic-gate 			Saferrno = E_SACNOTRUN;
11297c478bd9Sstevel@tonic-gate 			error(SACERR);
11307c478bd9Sstevel@tonic-gate 		}
11317c478bd9Sstevel@tonic-gate 	} while (pid != ak->ak_pid);
11327c478bd9Sstevel@tonic-gate 	(void) alarm(0);
11337c478bd9Sstevel@tonic-gate 
11347c478bd9Sstevel@tonic-gate /*
11357c478bd9Sstevel@tonic-gate  * check out what happened
11367c478bd9Sstevel@tonic-gate  */
11377c478bd9Sstevel@tonic-gate 
11387c478bd9Sstevel@tonic-gate 	switch (ak->ak_resp) {
11397c478bd9Sstevel@tonic-gate 	case AK_ACK:
11407c478bd9Sstevel@tonic-gate 		/* everything was A-OK */
11417c478bd9Sstevel@tonic-gate 		if (info && ak->ak_size) {
11427c478bd9Sstevel@tonic-gate 			/* there is return info and a place to put it */
11437c478bd9Sstevel@tonic-gate 			if ((*info = malloc((unsigned) (ak->ak_size + 1))) == NULL) {
11447c478bd9Sstevel@tonic-gate 				Saferrno = E_SYSERR;
11457c478bd9Sstevel@tonic-gate 				error("could not allocate storage");
11467c478bd9Sstevel@tonic-gate 			}
11477c478bd9Sstevel@tonic-gate 			if (read(fd, *info, (unsigned) ak->ak_size) != ak->ak_size) {
11487c478bd9Sstevel@tonic-gate 				Saferrno = E_SYSERR;
11497c478bd9Sstevel@tonic-gate 				error(SACERR);
11507c478bd9Sstevel@tonic-gate 			}
11517c478bd9Sstevel@tonic-gate 			/* make sure "string" is null-terminated */
11527c478bd9Sstevel@tonic-gate 			(*info)[ak->ak_size] = '\0';
11537c478bd9Sstevel@tonic-gate 		}
11547c478bd9Sstevel@tonic-gate 		return;
11557c478bd9Sstevel@tonic-gate 	/* something went wrong - see what */
11567c478bd9Sstevel@tonic-gate 	case AK_PMRUN:
11577c478bd9Sstevel@tonic-gate 		Saferrno = E_PMRUN;
11587c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Port monitor, %s, is already running\n", tag);
11597c478bd9Sstevel@tonic-gate 		break;
11607c478bd9Sstevel@tonic-gate 	case AK_PMNOTRUN:
11617c478bd9Sstevel@tonic-gate 		Saferrno = E_PMNOTRUN;
11627c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Port monitor, %s, is not running\n", tag);
11637c478bd9Sstevel@tonic-gate 		break;
11647c478bd9Sstevel@tonic-gate 	case AK_NOPM:
11657c478bd9Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
11667c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Invalid request, %s does not exist\n", tag);
11677c478bd9Sstevel@tonic-gate 		break;
11687c478bd9Sstevel@tonic-gate 	case AK_UNKNOWN:
11697c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11707c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Internal error - sent invalid command\n");
11717c478bd9Sstevel@tonic-gate 		break;
11727c478bd9Sstevel@tonic-gate 	case AK_NOCONTACT:
11737c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11747c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Could not contact %s\n", tag);
11757c478bd9Sstevel@tonic-gate 		break;
11767c478bd9Sstevel@tonic-gate 	case AK_PMLOCK:
11777c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11787c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Could not start %s - _pid file locked\n", tag);
11797c478bd9Sstevel@tonic-gate 		break;
11807c478bd9Sstevel@tonic-gate 	case AK_RECOVER:
11817c478bd9Sstevel@tonic-gate 		Saferrno = E_RECOVER;
11827c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Port monitor, %s, is in recovery\n", tag);
11837c478bd9Sstevel@tonic-gate 		break;
11847c478bd9Sstevel@tonic-gate 	case AK_REQFAIL:
11857c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11867c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "This request could not be completed - see sac log file for details\n");
11877c478bd9Sstevel@tonic-gate 		break;
11887c478bd9Sstevel@tonic-gate 	default:
11897c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11907c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "unknown response\n");
11917c478bd9Sstevel@tonic-gate 		break;
11927c478bd9Sstevel@tonic-gate 	}
11937c478bd9Sstevel@tonic-gate }
11947c478bd9Sstevel@tonic-gate 
11957c478bd9Sstevel@tonic-gate 
11967c478bd9Sstevel@tonic-gate /*
11977c478bd9Sstevel@tonic-gate  * catch - catcher for SIGALRM, don't need to do anything
11987c478bd9Sstevel@tonic-gate  */
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate void
12017c478bd9Sstevel@tonic-gate catch()
12027c478bd9Sstevel@tonic-gate {
12037c478bd9Sstevel@tonic-gate }
12047c478bd9Sstevel@tonic-gate 
12057c478bd9Sstevel@tonic-gate 
12067c478bd9Sstevel@tonic-gate /*
12077c478bd9Sstevel@tonic-gate  * pflags - put port monitor flags into intelligible form for output
12087c478bd9Sstevel@tonic-gate  *
12097c478bd9Sstevel@tonic-gate  *	args:	flags - binary representation of flags
12107c478bd9Sstevel@tonic-gate  *		dflag - true if a "-" should be returned if no flags
12117c478bd9Sstevel@tonic-gate  */
12127c478bd9Sstevel@tonic-gate 
12137c478bd9Sstevel@tonic-gate char *
12147c478bd9Sstevel@tonic-gate pflags(flags, dflag)
12157c478bd9Sstevel@tonic-gate long flags;
12167c478bd9Sstevel@tonic-gate int dflag;
12177c478bd9Sstevel@tonic-gate {
12187c478bd9Sstevel@tonic-gate 	register int i;			/* scratch counter */
12197c478bd9Sstevel@tonic-gate 	static char buf[SIZE];		/* formatted flags */
12207c478bd9Sstevel@tonic-gate 
12217c478bd9Sstevel@tonic-gate 	if (flags == 0) {
12227c478bd9Sstevel@tonic-gate 		if (dflag)
12237c478bd9Sstevel@tonic-gate 			return("-");
12247c478bd9Sstevel@tonic-gate 		else
12257c478bd9Sstevel@tonic-gate 			return("");
12267c478bd9Sstevel@tonic-gate 	}
12277c478bd9Sstevel@tonic-gate 	i = 0;
12287c478bd9Sstevel@tonic-gate 	if (flags & D_FLAG) {
12297c478bd9Sstevel@tonic-gate 		buf[i++] = 'd';
12307c478bd9Sstevel@tonic-gate 		flags &= ~D_FLAG;
12317c478bd9Sstevel@tonic-gate 	}
12327c478bd9Sstevel@tonic-gate 	if (flags & X_FLAG) {
12337c478bd9Sstevel@tonic-gate 		buf[i++] = 'x';
12347c478bd9Sstevel@tonic-gate 		flags &= ~X_FLAG;
12357c478bd9Sstevel@tonic-gate 	}
12367c478bd9Sstevel@tonic-gate 	if (flags) {
12377c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Bad information from SAC\n");
12387c478bd9Sstevel@tonic-gate 		exit(1);
12397c478bd9Sstevel@tonic-gate 	}
12407c478bd9Sstevel@tonic-gate 	buf[i] = '\0';
12417c478bd9Sstevel@tonic-gate 	return(buf);
12427c478bd9Sstevel@tonic-gate }
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate 
12457c478bd9Sstevel@tonic-gate /*
12467c478bd9Sstevel@tonic-gate  * sac_home - returns true is sac has a lock on its logfile, false
12477c478bd9Sstevel@tonic-gate  *	otherwise (useful to avoid errors for administrative actions in
12487c478bd9Sstevel@tonic-gate  *	single user mode)
12497c478bd9Sstevel@tonic-gate  */
12507c478bd9Sstevel@tonic-gate 
125134e48580Sdp int
12527c478bd9Sstevel@tonic-gate sac_home()
12537c478bd9Sstevel@tonic-gate {
12547c478bd9Sstevel@tonic-gate 	int fd;		/* fd to sac logfile */
12557c478bd9Sstevel@tonic-gate 
12567c478bd9Sstevel@tonic-gate 	fd = open(LOGFILE, O_RDONLY);
12577c478bd9Sstevel@tonic-gate 	if (fd < 0) {
12587c478bd9Sstevel@tonic-gate 		fprintf(stderr, "warning - could not ascertain sac status\n");
12597c478bd9Sstevel@tonic-gate 		return(FALSE);
12607c478bd9Sstevel@tonic-gate 	}
12617c478bd9Sstevel@tonic-gate 	if (lockf(fd, F_TEST, 0) < 0) {
12627c478bd9Sstevel@tonic-gate 		/* everything is ok */
12637c478bd9Sstevel@tonic-gate 		(void) close(fd);
12647c478bd9Sstevel@tonic-gate 		return(TRUE);
12657c478bd9Sstevel@tonic-gate 	}
12667c478bd9Sstevel@tonic-gate 	else {
12677c478bd9Sstevel@tonic-gate 		/* no one home */
12687c478bd9Sstevel@tonic-gate 		(void) close(fd);
12697c478bd9Sstevel@tonic-gate 		return(FALSE);
12707c478bd9Sstevel@tonic-gate 	}
12717c478bd9Sstevel@tonic-gate }
1272*22c9e08bSsn199410 
1273*22c9e08bSsn199410 /*
1274*22c9e08bSsn199410  * invoke_rm - deletes the argument directory and all its files/subdirectories
1275*22c9e08bSsn199410  */
1276*22c9e08bSsn199410 static int
1277*22c9e08bSsn199410 invoke_rm(char *fname)
1278*22c9e08bSsn199410 {
1279*22c9e08bSsn199410 	pid_t cpid;		/* process ID of the child process */
1280*22c9e08bSsn199410 	int cstatus;		/* status of child process */
1281*22c9e08bSsn199410 	char *argvec[4];
1282*22c9e08bSsn199410 
1283*22c9e08bSsn199410 	argvec[0] = "rm";
1284*22c9e08bSsn199410 	argvec[1] = "-rf";
1285*22c9e08bSsn199410 	argvec[2] = fname;
1286*22c9e08bSsn199410 	argvec[3] = NULL;
1287*22c9e08bSsn199410 
1288*22c9e08bSsn199410 	if (posix_spawn(&cpid, "/usr/bin/rm", NULL, NULL,
1289*22c9e08bSsn199410 	    (char *const *)argvec, NULL))
1290*22c9e08bSsn199410 		return (-1);
1291*22c9e08bSsn199410 	if (waitpid(cpid, &cstatus, 0) == -1)
1292*22c9e08bSsn199410 		return (-1);
1293*22c9e08bSsn199410 
1294*22c9e08bSsn199410 	return ((WIFEXITED(cstatus) == 0) ? 99 : WEXITSTATUS(cstatus));
1295*22c9e08bSsn199410 }
1296