xref: /onnv-gate/usr/src/cmd/saf/pmadm.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 /*
23*334Sdp  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
310Sstevel@tonic-gate 
32*334Sdp #include <stdio.h>
33*334Sdp #include <stdlib.h>
34*334Sdp #include <strings.h>
35*334Sdp #include <sys/types.h>
36*334Sdp #include <sys/stat.h>
37*334Sdp #include <unistd.h>
38*334Sdp #include "extern.h"
39*334Sdp #include "misc.h"
40*334Sdp #include <sac.h>
41*334Sdp #include "structs.h"
420Sstevel@tonic-gate 
43*334Sdp #define	ADD		0x1	/* -a or other required options seen */
44*334Sdp #define	REMOVE		0x2	/* -r seen */
45*334Sdp #define	ENABLE		0x4	/* -e seen */
46*334Sdp #define	DISABLE		0x8	/* -d seen */
47*334Sdp #define	PLIST		0x10	/* -l seen */
48*334Sdp #define	LIST		0x20	/* -L seen */
49*334Sdp #define	CONFIG		0x40	/* -g seen */
500Sstevel@tonic-gate 
510Sstevel@tonic-gate # define U_FLAG		0x1	/* -fu seen */
520Sstevel@tonic-gate # define X_FLAG		0x2	/* -fx seen */
530Sstevel@tonic-gate 
540Sstevel@tonic-gate /*
550Sstevel@tonic-gate  * functions
560Sstevel@tonic-gate  */
570Sstevel@tonic-gate 
580Sstevel@tonic-gate char	*pflags();
590Sstevel@tonic-gate char	*pspec();
600Sstevel@tonic-gate struct	taglist	*find_type();
610Sstevel@tonic-gate void	usage();
620Sstevel@tonic-gate void	parseline();
630Sstevel@tonic-gate void	add_svc();
640Sstevel@tonic-gate void	rem_svc();
650Sstevel@tonic-gate void	ed_svc();
660Sstevel@tonic-gate void	list_svcs();
670Sstevel@tonic-gate void	doconf();
680Sstevel@tonic-gate 
690Sstevel@tonic-gate /*
700Sstevel@tonic-gate  * format of a _pmtab entry - used to hold parsed info
710Sstevel@tonic-gate  */
720Sstevel@tonic-gate 
730Sstevel@tonic-gate struct	pmtab {
740Sstevel@tonic-gate 	char	*p_tag;		/* service tag */
750Sstevel@tonic-gate 	long	p_flags;	/* flags */
760Sstevel@tonic-gate 	char	*p_id;		/* logname to start service as */
770Sstevel@tonic-gate 	char	*p_res1;	/* reserved field */
780Sstevel@tonic-gate 	char	*p_res2;	/* reserved field */
790Sstevel@tonic-gate 	char	*p_res3;	/* reserved field */
800Sstevel@tonic-gate 	char	*p_pmspec;	/* port monitor specific info */
810Sstevel@tonic-gate };
820Sstevel@tonic-gate 
830Sstevel@tonic-gate /*
840Sstevel@tonic-gate  * format of a tag list, which is a list of port monitor tags of
850Sstevel@tonic-gate  * a designated type
860Sstevel@tonic-gate  */
870Sstevel@tonic-gate 
880Sstevel@tonic-gate struct	taglist {
890Sstevel@tonic-gate 	struct	taglist	*t_next;	/* next in list */
900Sstevel@tonic-gate 	char	t_tag[PMTAGSIZE + 1];	/* PM tag */
910Sstevel@tonic-gate 	char	t_type[PMTYPESIZE + 1];	/* PM type */
920Sstevel@tonic-gate };
930Sstevel@tonic-gate 
940Sstevel@tonic-gate /*
950Sstevel@tonic-gate  * common error messages
960Sstevel@tonic-gate  */
970Sstevel@tonic-gate 
980Sstevel@tonic-gate # define NOTPRIV	"User not privileged for operation"
990Sstevel@tonic-gate # define BADINP		"Embedded newlines not allowed"
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate int	Saferrno;	/* internal `errno' for exit */
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate /*
1050Sstevel@tonic-gate  * main - scan args for pmadm and call appropriate handling code
1060Sstevel@tonic-gate  */
1070Sstevel@tonic-gate 
108*334Sdp int
main(int argc,char * argv[])109*334Sdp main(int argc, char *argv[])
1100Sstevel@tonic-gate {
1110Sstevel@tonic-gate 	int c;			/* option letter */
1120Sstevel@tonic-gate 	int ret;		/* return code from check_version */
1130Sstevel@tonic-gate 	uid_t uid;		/* invoker's real uid */
1140Sstevel@tonic-gate 	int flag = 0;		/* flag to record requested operations */
1150Sstevel@tonic-gate 	int errflg = 0;		/* error indicator */
1160Sstevel@tonic-gate 	int badcnt = 0;		/* count of bad args to -f */
1170Sstevel@tonic-gate 	int version = -1;	/* argument to -v */
1180Sstevel@tonic-gate 	int sawaflag = 0;	/* true if actually saw -a */
1190Sstevel@tonic-gate 	int conflag = 0;	/* true if output should be in condensed form */
1200Sstevel@tonic-gate 	long flags = 0;		/* arguments to -f */
1210Sstevel@tonic-gate 	char *pmtag = NULL;	/* argument to -p */
1220Sstevel@tonic-gate 	char *type = NULL;	/* argument to -t */
1230Sstevel@tonic-gate 	char *script = NULL;	/* argument to -z */
1240Sstevel@tonic-gate 	char *comment = " ";	/* argument to -y */
1250Sstevel@tonic-gate 	char *id = NULL;	/* argument to -i */
1260Sstevel@tonic-gate 	char *svctag = NULL;	/* argument to -s */
1270Sstevel@tonic-gate 	char *pmspec = NULL;	/* argument to -m */
1280Sstevel@tonic-gate 	char badargs[SIZE];	/* place to hold bad args to -f */
1290Sstevel@tonic-gate 	char buf[SIZE];		/* scratch buffer */
1300Sstevel@tonic-gate 	register char *p;	/* scratch pointer */
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	if (argc == 1)
1330Sstevel@tonic-gate 		usage(argv[0]);
1340Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "adef:gi:Llm:p:rs:t:v:y:z:")) != -1) {
1350Sstevel@tonic-gate 		switch (c) {
1360Sstevel@tonic-gate 		case 'a':
1370Sstevel@tonic-gate 			flag |= ADD;
1380Sstevel@tonic-gate 			sawaflag = 1;
1390Sstevel@tonic-gate 			break;
1400Sstevel@tonic-gate 		case 'd':
1410Sstevel@tonic-gate 			flag |= DISABLE;
1420Sstevel@tonic-gate 			break;
1430Sstevel@tonic-gate 		case 'e':
1440Sstevel@tonic-gate 			flag |= ENABLE;
1450Sstevel@tonic-gate 			break;
1460Sstevel@tonic-gate 		case 'f':
1470Sstevel@tonic-gate 			flag |= ADD;
1480Sstevel@tonic-gate 			while (*optarg) {
1490Sstevel@tonic-gate 				switch (*optarg++) {
1500Sstevel@tonic-gate 				case 'u':
1510Sstevel@tonic-gate 					flags |= U_FLAG;
1520Sstevel@tonic-gate 					break;
1530Sstevel@tonic-gate 				case 'x':
1540Sstevel@tonic-gate 					flags |= X_FLAG;
1550Sstevel@tonic-gate 					break;
1560Sstevel@tonic-gate 				default:
1570Sstevel@tonic-gate 					badargs[badcnt++] = *(optarg - 1);
1580Sstevel@tonic-gate 					break;
1590Sstevel@tonic-gate 				}
1600Sstevel@tonic-gate 			}
1610Sstevel@tonic-gate 			/* null terminate just in case anything is there */
1620Sstevel@tonic-gate 			badargs[badcnt] = '\0';
1630Sstevel@tonic-gate 			break;
1640Sstevel@tonic-gate 		case 'g':
1650Sstevel@tonic-gate 			flag |= CONFIG;
1660Sstevel@tonic-gate 			break;
1670Sstevel@tonic-gate 		case 'i':
1680Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
1690Sstevel@tonic-gate 				Saferrno = E_BADARGS;
1700Sstevel@tonic-gate 				error(BADINP);
1710Sstevel@tonic-gate 			}
1720Sstevel@tonic-gate 			flag |= ADD;
1730Sstevel@tonic-gate 			id = optarg;
1740Sstevel@tonic-gate 			break;
1750Sstevel@tonic-gate 		case 'L':
1760Sstevel@tonic-gate 			flag |= LIST;
1770Sstevel@tonic-gate 			break;
1780Sstevel@tonic-gate 		case 'l':
1790Sstevel@tonic-gate 			flag |= PLIST;
1800Sstevel@tonic-gate 			break;
1810Sstevel@tonic-gate 		case 'm':
1820Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
1830Sstevel@tonic-gate 				Saferrno = E_BADARGS;
1840Sstevel@tonic-gate 				error(BADINP);
1850Sstevel@tonic-gate 			}
1860Sstevel@tonic-gate 			if (*optarg == '\0') {
1870Sstevel@tonic-gate 				/* this will generate a usage message below */
1880Sstevel@tonic-gate 				errflg++;
1890Sstevel@tonic-gate 				break;
1900Sstevel@tonic-gate 			}
1910Sstevel@tonic-gate 			flag |= ADD;
1920Sstevel@tonic-gate 			pmspec = optarg;
1930Sstevel@tonic-gate 			break;
1940Sstevel@tonic-gate 		case 'p':
1950Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
1960Sstevel@tonic-gate 				Saferrno = E_BADARGS;
1970Sstevel@tonic-gate 				error(BADINP);
1980Sstevel@tonic-gate 			}
1990Sstevel@tonic-gate 			pmtag = optarg;
2000Sstevel@tonic-gate 			if (strlen(pmtag) > PMTAGSIZE) {
2010Sstevel@tonic-gate 				pmtag[PMTAGSIZE] = '\0';
2020Sstevel@tonic-gate 				(void) fprintf(stderr, "tag too long, truncated to <%s>\n", pmtag);
2030Sstevel@tonic-gate 			}
2040Sstevel@tonic-gate 			for (p = pmtag; *p; p++) {
2050Sstevel@tonic-gate 				if (!isalnum(*p)) {
2060Sstevel@tonic-gate 					Saferrno = E_BADARGS;
2070Sstevel@tonic-gate 					error("port monitor tag must be alphanumeric");
2080Sstevel@tonic-gate 				}
2090Sstevel@tonic-gate 			}
2100Sstevel@tonic-gate 			break;
2110Sstevel@tonic-gate 		case 'r':
2120Sstevel@tonic-gate 			flag |= REMOVE;
2130Sstevel@tonic-gate 			break;
2140Sstevel@tonic-gate 		case 's':
2150Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
2160Sstevel@tonic-gate 				Saferrno = E_BADARGS;
2170Sstevel@tonic-gate 				error(BADINP);
2180Sstevel@tonic-gate 			}
2190Sstevel@tonic-gate 			svctag = optarg;
2200Sstevel@tonic-gate 			if (strlen(svctag) > SVCTAGSIZE) {
2210Sstevel@tonic-gate 				svctag[SVCTAGSIZE] = '\0';
2220Sstevel@tonic-gate 				(void) fprintf(stderr, "svctag too long, truncated to <%s>\n", svctag);
2230Sstevel@tonic-gate 			}
2240Sstevel@tonic-gate 			for (p = svctag; *p; p++) {
2250Sstevel@tonic-gate 				if (!isalnum(*p)) {
2260Sstevel@tonic-gate 					Saferrno = E_BADARGS;
2270Sstevel@tonic-gate 					error("service tag must be alphanumeric");
2280Sstevel@tonic-gate 				}
2290Sstevel@tonic-gate 			}
2300Sstevel@tonic-gate 			break;
2310Sstevel@tonic-gate 		case 't':
2320Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
2330Sstevel@tonic-gate 				Saferrno = E_BADARGS;
2340Sstevel@tonic-gate 				error(BADINP);
2350Sstevel@tonic-gate 			}
2360Sstevel@tonic-gate 			type = optarg;
2370Sstevel@tonic-gate 			if (strlen(type) > PMTYPESIZE) {
2380Sstevel@tonic-gate 				type[PMTYPESIZE] = '\0';
2390Sstevel@tonic-gate 				(void) fprintf(stderr, "type too long, truncated to <%s>\n", type);
2400Sstevel@tonic-gate 			}
2410Sstevel@tonic-gate 			for (p = type; *p; p++) {
2420Sstevel@tonic-gate 				if (!isalnum(*p)) {
2430Sstevel@tonic-gate 					Saferrno = E_BADARGS;
2440Sstevel@tonic-gate 					error("port monitor type must be alphanumeric");
2450Sstevel@tonic-gate 				}
2460Sstevel@tonic-gate 			}
2470Sstevel@tonic-gate 			break;
2480Sstevel@tonic-gate 		case 'v':
2490Sstevel@tonic-gate 			flag |= ADD;
2500Sstevel@tonic-gate 			version = atoi(optarg);
2510Sstevel@tonic-gate 			if (version < 0) {
2520Sstevel@tonic-gate 				Saferrno = E_BADARGS;
2530Sstevel@tonic-gate 				error("version number can not be negative");
2540Sstevel@tonic-gate 			}
2550Sstevel@tonic-gate 			break;
2560Sstevel@tonic-gate 		case 'y':
2570Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
2580Sstevel@tonic-gate 				Saferrno = E_BADARGS;
2590Sstevel@tonic-gate 				error(BADINP);
2600Sstevel@tonic-gate 			}
2610Sstevel@tonic-gate 			flag |= ADD;
2620Sstevel@tonic-gate 			comment = optarg;
2630Sstevel@tonic-gate 			break;
2640Sstevel@tonic-gate 		case 'z':
2650Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
2660Sstevel@tonic-gate 				Saferrno = E_BADARGS;
2670Sstevel@tonic-gate 				error(BADINP);
2680Sstevel@tonic-gate 			}
2690Sstevel@tonic-gate 			script = optarg;
2700Sstevel@tonic-gate 			break;
2710Sstevel@tonic-gate 		case '?':
2720Sstevel@tonic-gate 			errflg++;
2730Sstevel@tonic-gate 		}
2740Sstevel@tonic-gate 	}
2750Sstevel@tonic-gate 	if (errflg || (optind < argc))
2760Sstevel@tonic-gate 		usage(argv[0]);
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 	if (badcnt) {
2790Sstevel@tonic-gate 		/* bad flags were given to -f */
2800Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s are not valid arguments for \"-f\"", badargs);
2810Sstevel@tonic-gate 		Saferrno = E_BADARGS;
2820Sstevel@tonic-gate 		error(buf);
2830Sstevel@tonic-gate 	}
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 	uid = getuid();
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate /*
2880Sstevel@tonic-gate  * don't do anything if _sactab isn't the version we understand
2890Sstevel@tonic-gate  */
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	if ((ret = check_version(VERSION, SACTAB)) == 1) {
2920Sstevel@tonic-gate 		Saferrno = E_SAFERR;
2930Sstevel@tonic-gate 		error("_sactab version number is incorrect");
2940Sstevel@tonic-gate 	}
2950Sstevel@tonic-gate 	else if (ret == 2) {
2960Sstevel@tonic-gate 		(void) sprintf(buf, "could not open %s", SACTAB);
2970Sstevel@tonic-gate 		Saferrno = E_SYSERR;
2980Sstevel@tonic-gate 		error(buf);
2990Sstevel@tonic-gate 	}
3000Sstevel@tonic-gate 	else if (ret == 3) {
3010Sstevel@tonic-gate 		(void) sprintf(buf, "%s file is corrupt", SACTAB);
3020Sstevel@tonic-gate 		Saferrno = E_SAFERR;
3030Sstevel@tonic-gate 		error(buf);
3040Sstevel@tonic-gate 	}
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 	switch (flag) {
3070Sstevel@tonic-gate 	case ADD:
3080Sstevel@tonic-gate 		if (uid) {
3090Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3100Sstevel@tonic-gate 			error(NOTPRIV);
3110Sstevel@tonic-gate 		}
3120Sstevel@tonic-gate 		if (!sawaflag || (pmtag && type) || (!pmtag && !type) || !svctag || !id || !pmspec || (version < 0))
3130Sstevel@tonic-gate 			usage(argv[0]);
3140Sstevel@tonic-gate 		add_svc(pmtag, type, svctag, id, pmspec, flags, version, comment, script);
3150Sstevel@tonic-gate 		break;
3160Sstevel@tonic-gate 	case REMOVE:
3170Sstevel@tonic-gate 		if (uid) {
3180Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3190Sstevel@tonic-gate 			error(NOTPRIV);
3200Sstevel@tonic-gate 		}
3210Sstevel@tonic-gate 		if (!pmtag || !svctag || type || script)
3220Sstevel@tonic-gate 			usage(argv[0]);
3230Sstevel@tonic-gate 		rem_svc(pmtag, svctag);
3240Sstevel@tonic-gate 		break;
3250Sstevel@tonic-gate 	case ENABLE:
3260Sstevel@tonic-gate 		if (uid) {
3270Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3280Sstevel@tonic-gate 			error(NOTPRIV);
3290Sstevel@tonic-gate 		}
3300Sstevel@tonic-gate 		if (!pmtag || !svctag || type || script)
3310Sstevel@tonic-gate 			usage(argv[0]);
3320Sstevel@tonic-gate 		ed_svc(pmtag, svctag, ENABLE);
3330Sstevel@tonic-gate 		break;
3340Sstevel@tonic-gate 	case DISABLE:
3350Sstevel@tonic-gate 		if (uid) {
3360Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3370Sstevel@tonic-gate 			error(NOTPRIV);
3380Sstevel@tonic-gate 		}
3390Sstevel@tonic-gate 		if (!pmtag || !svctag || type || script)
3400Sstevel@tonic-gate 			usage(argv[0]);
3410Sstevel@tonic-gate 		ed_svc(pmtag, svctag, DISABLE);
3420Sstevel@tonic-gate 		break;
3430Sstevel@tonic-gate 	case LIST:
3440Sstevel@tonic-gate 		conflag = 1;
3450Sstevel@tonic-gate 		/* fall through */
3460Sstevel@tonic-gate 	case PLIST:
3470Sstevel@tonic-gate 		if ((pmtag && type) || script)
3480Sstevel@tonic-gate 			usage(argv[0]);
3490Sstevel@tonic-gate 		list_svcs(pmtag, type, svctag, conflag);
3500Sstevel@tonic-gate 		break;
3510Sstevel@tonic-gate 	case CONFIG:
3520Sstevel@tonic-gate 		if (script && uid) {
3530Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3540Sstevel@tonic-gate 			error(NOTPRIV);
3550Sstevel@tonic-gate 		}
3560Sstevel@tonic-gate 		if ((pmtag && type) || (!pmtag && !type) || !svctag || (type && !script))
3570Sstevel@tonic-gate 			usage(argv[0]);
3580Sstevel@tonic-gate 		doconf(script, pmtag, type, svctag);
3590Sstevel@tonic-gate 		break;
3600Sstevel@tonic-gate 	default:
3610Sstevel@tonic-gate 		/* we only get here if more than one flag bit was set */
3620Sstevel@tonic-gate 		usage(argv[0]);
3630Sstevel@tonic-gate 		/* NOTREACHED */
3640Sstevel@tonic-gate 	}
3650Sstevel@tonic-gate 	quit();
3660Sstevel@tonic-gate 	/* NOTREACHED */
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate /*
3710Sstevel@tonic-gate  * usage - print out a usage message
3720Sstevel@tonic-gate  *
3730Sstevel@tonic-gate  *	args:	cmdname - the name command was invoked with
3740Sstevel@tonic-gate  */
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate void
usage(cmdname)3770Sstevel@tonic-gate usage(cmdname)
3780Sstevel@tonic-gate char *cmdname;
3790Sstevel@tonic-gate {
3800Sstevel@tonic-gate 	(void) fprintf(stderr, "Usage:\t%s -a [ -p pmtag | -t type ] -s svctag -i id -m \"pmspecific\"\n", cmdname);
3810Sstevel@tonic-gate 	(void) fprintf(stderr, "\t\t-v version [ -f xu ] [ -y comment ] [ -z script]\n");
3820Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -r -p pmtag -s svctag\n", cmdname);
3830Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -e -p pmtag -s svctag\n", cmdname);
3840Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -d -p pmtag -s svctag\n", cmdname);
3850Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -l [ -p pmtag | -t type ] [ -s svctag ]\n", cmdname);
3860Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -L [ -p pmtag | -t type ] [ -s svctag ]\n", cmdname);
3870Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -g -p pmtag -s svctag [ -z script ]\n", cmdname);
3880Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -g -s svctag -t type -z script\n", cmdname);
3890Sstevel@tonic-gate 	Saferrno = E_BADARGS;
3900Sstevel@tonic-gate 	quit();
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate /*
3950Sstevel@tonic-gate  * add_svc - add a service entry
3960Sstevel@tonic-gate  *
3970Sstevel@tonic-gate  *	args:	tag - port monitor's tag (may be null)
3980Sstevel@tonic-gate  *		type - port monitor's type (may be null)
3990Sstevel@tonic-gate  *		svctag - service's tag
4000Sstevel@tonic-gate  *		id - identity under which service should run
4010Sstevel@tonic-gate  *		pmspec - uninterpreted port monitor-specific info
4020Sstevel@tonic-gate  *		flags - service flags
4030Sstevel@tonic-gate  *		version - version number of port monitor's pmtab
4040Sstevel@tonic-gate  *		comment - comment describing service
4050Sstevel@tonic-gate  *		script - service's configuration script
4060Sstevel@tonic-gate  */
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate void
add_svc(tag,type,svctag,id,pmspec,flags,version,comment,script)4090Sstevel@tonic-gate add_svc(tag, type, svctag, id, pmspec, flags, version, comment, script)
4100Sstevel@tonic-gate char *tag;
4110Sstevel@tonic-gate char *type;
4120Sstevel@tonic-gate char *svctag;
4130Sstevel@tonic-gate char *id;
4140Sstevel@tonic-gate char *pmspec;
4150Sstevel@tonic-gate long flags;
4160Sstevel@tonic-gate int version;
4170Sstevel@tonic-gate char *comment;
4180Sstevel@tonic-gate char *script;
4190Sstevel@tonic-gate {
4200Sstevel@tonic-gate 	FILE *fp;			/* scratch file pointer */
4210Sstevel@tonic-gate 	struct taglist tl;		/* 'list' for degenerate case (1 PM) */
4220Sstevel@tonic-gate 	register struct taglist *tp = NULL;	/* working pointer */
4230Sstevel@tonic-gate 	int ret;			/* return code from check_version */
4240Sstevel@tonic-gate 	char buf[SIZE];			/* scratch buffer */
4250Sstevel@tonic-gate 	char fname[SIZE];		/* scratch buffer for building names */
4260Sstevel@tonic-gate 	int added;			/* count number added */
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate 	fp = fopen(SACTAB, "r");
4290Sstevel@tonic-gate 	if (fp == NULL) {
4300Sstevel@tonic-gate 		Saferrno = E_SYSERR;
4310Sstevel@tonic-gate 		error("Could not open _sactab");
4320Sstevel@tonic-gate 	}
4330Sstevel@tonic-gate 	if (tag && !find_pm(fp, tag)) {
4340Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist", tag);
4350Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
4360Sstevel@tonic-gate 		error(buf);
4370Sstevel@tonic-gate 	}
4380Sstevel@tonic-gate 	if (type && !(tp = find_type(fp, type))) {
4390Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist", type);
4400Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
4410Sstevel@tonic-gate 		error(buf);
4420Sstevel@tonic-gate 	}
4430Sstevel@tonic-gate 	(void) fclose(fp);
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 	if (tag) {
4460Sstevel@tonic-gate 
4470Sstevel@tonic-gate /*
4480Sstevel@tonic-gate  * treat the case of 1 PM as a degenerate case of a list of PMs from a
4490Sstevel@tonic-gate  * type specification.  Build the 'list' here.
4500Sstevel@tonic-gate  */
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 		tp = &tl;
4530Sstevel@tonic-gate 		tp->t_next = NULL;
4540Sstevel@tonic-gate 		(void) strcpy(tp->t_tag, tag);
4550Sstevel@tonic-gate 	}
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 	added = 0;
4580Sstevel@tonic-gate 	while (tp) {
4590Sstevel@tonic-gate 		(void) sprintf(fname, "%s/%s/_pmtab", HOME, tp->t_tag);
4600Sstevel@tonic-gate 		if ((ret = check_version(version, fname)) == 1) {
4610Sstevel@tonic-gate 			(void) sprintf(buf, "%s version number is incorrect", fname);
4620Sstevel@tonic-gate 			Saferrno = E_SAFERR;
4630Sstevel@tonic-gate 			error(buf);
4640Sstevel@tonic-gate 		}
4650Sstevel@tonic-gate 		else if (ret == 2) {
4660Sstevel@tonic-gate 			(void) sprintf(buf, "could not open %s", fname);
4670Sstevel@tonic-gate 			Saferrno = E_SYSERR;
4680Sstevel@tonic-gate 			error(buf);
4690Sstevel@tonic-gate 		}
4700Sstevel@tonic-gate 		else if (ret == 3) {
4710Sstevel@tonic-gate 			(void) sprintf(buf, "%s file is corrupt", fname);
4720Sstevel@tonic-gate 			Saferrno = E_SAFERR;
4730Sstevel@tonic-gate 			error(buf);
4740Sstevel@tonic-gate 		}
4750Sstevel@tonic-gate 		fp = fopen(fname, "r");
4760Sstevel@tonic-gate 		if (fp == NULL) {
4770Sstevel@tonic-gate 			(void) sprintf(buf, "Could not open %s", fname);
4780Sstevel@tonic-gate 			Saferrno = E_SYSERR;
4790Sstevel@tonic-gate 			error(buf);
4800Sstevel@tonic-gate 		}
4810Sstevel@tonic-gate 		if (find_svc(fp, tp->t_tag, svctag)) {
4820Sstevel@tonic-gate 			if (tag) {
4830Sstevel@tonic-gate 				/* special case of tag only */
4840Sstevel@tonic-gate 				(void) sprintf(buf, "Invalid request, %s already exists under %s", svctag, tag);
4850Sstevel@tonic-gate 				Saferrno = E_DUP;
4860Sstevel@tonic-gate 				error(buf);
4870Sstevel@tonic-gate 			}
4880Sstevel@tonic-gate 			else {
4890Sstevel@tonic-gate 				(void) fprintf(stderr, "warning - %s already exists under %s - ignoring\n", svctag, tp->t_tag);
4900Sstevel@tonic-gate 				tp = tp->t_next;
4910Sstevel@tonic-gate 				(void) fclose(fp);
4920Sstevel@tonic-gate 				continue;
4930Sstevel@tonic-gate 			}
4940Sstevel@tonic-gate 		}
4950Sstevel@tonic-gate 		(void) fclose(fp);
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate /*
4980Sstevel@tonic-gate  * put in the config script, if specified
4990Sstevel@tonic-gate */
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 		if (script) {
5020Sstevel@tonic-gate 			(void) sprintf(fname, "%s/%s", tp->t_tag, svctag);
5030Sstevel@tonic-gate 			if (do_config(script, fname)) {
5040Sstevel@tonic-gate 				/* do_config put out any messages */
5050Sstevel@tonic-gate 				tp = tp->t_next;
5060Sstevel@tonic-gate 				continue;
5070Sstevel@tonic-gate 			}
5080Sstevel@tonic-gate 		}
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate /*
5110Sstevel@tonic-gate  * add the line
5120Sstevel@tonic-gate  */
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 		(void) sprintf(fname, "%s/%s/_pmtab", HOME, tp->t_tag);
5150Sstevel@tonic-gate 		fp = fopen(fname, "a");
5160Sstevel@tonic-gate 		if (fp == NULL) {
5170Sstevel@tonic-gate 			(void) sprintf(buf, "Could not open %s", fname);
5180Sstevel@tonic-gate 			Saferrno = E_SYSERR;
5190Sstevel@tonic-gate 			error(buf);
5200Sstevel@tonic-gate 		}
5210Sstevel@tonic-gate 		(void) fprintf(fp, "%s:%s:%s:reserved:reserved:reserved:%s#%s\n",
5220Sstevel@tonic-gate 			svctag, (flags ? pflags(flags, FALSE) : ""), id, pmspec,
5230Sstevel@tonic-gate 			(comment ? comment : ""));
5240Sstevel@tonic-gate 		(void) fclose(fp);
5250Sstevel@tonic-gate 		added++;
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate /*
5280Sstevel@tonic-gate  * tell the SAC to to tell PM to read _pmtab
5290Sstevel@tonic-gate  */
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 		(void) tell_sac(tp->t_tag);
5320Sstevel@tonic-gate 		tp = tp->t_next;
5330Sstevel@tonic-gate 	}
5340Sstevel@tonic-gate 	if (added == 0) {
5350Sstevel@tonic-gate 		Saferrno = E_SAFERR;
5360Sstevel@tonic-gate 		error("No services added");
5370Sstevel@tonic-gate 	}
5380Sstevel@tonic-gate 	return;
5390Sstevel@tonic-gate }
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 
5420Sstevel@tonic-gate /*
5430Sstevel@tonic-gate  * rem_svc - remove a service
5440Sstevel@tonic-gate  *
5450Sstevel@tonic-gate  *	args:	pmtag - tag of port monitor responsible for the service
5460Sstevel@tonic-gate  *		svctag - tag of the service to be removed
5470Sstevel@tonic-gate  */
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate void
rem_svc(pmtag,svctag)5500Sstevel@tonic-gate rem_svc(pmtag, svctag)
5510Sstevel@tonic-gate char *pmtag;
5520Sstevel@tonic-gate char *svctag;
5530Sstevel@tonic-gate {
5540Sstevel@tonic-gate 	FILE *fp;		/* scratch file pointer */
5550Sstevel@tonic-gate 	FILE *tfp;		/* file pointer for temp file */
5560Sstevel@tonic-gate 	int line;		/* line number entry is on */
5570Sstevel@tonic-gate 	char *tname;		/* temp file name */
5580Sstevel@tonic-gate 	char buf[SIZE];		/* scratch buffer */
5590Sstevel@tonic-gate 	char fname[SIZE];	/* path to correct _pmtab */
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate 	fp = fopen(SACTAB, "r");
5620Sstevel@tonic-gate 	if (fp == NULL) {
5630Sstevel@tonic-gate 		Saferrno = E_SYSERR;
5640Sstevel@tonic-gate 		error("Could not open _sactab");
5650Sstevel@tonic-gate 	}
5660Sstevel@tonic-gate 	if (!find_pm(fp, pmtag)) {
5670Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist", pmtag);
5680Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
5690Sstevel@tonic-gate 		error(buf);
5700Sstevel@tonic-gate 	}
5710Sstevel@tonic-gate 	(void) fclose(fp);
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate 	(void) sprintf(fname, "%s/_pmtab", pmtag);
5740Sstevel@tonic-gate 	(void) sprintf(buf, "%s/%s", HOME, fname);
5750Sstevel@tonic-gate 	fp = fopen(buf, "r");
5760Sstevel@tonic-gate 	if (fp == NULL) {
5770Sstevel@tonic-gate 		(void) sprintf(buf, "Could not open %s/%s", HOME, fname);
5780Sstevel@tonic-gate 		Saferrno = E_SYSERR;
5790Sstevel@tonic-gate 		error(buf);
5800Sstevel@tonic-gate 	}
5810Sstevel@tonic-gate 	if ((line = find_svc(fp, pmtag, svctag)) == 0) {
5820Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist under %s", svctag, pmtag);
5830Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
5840Sstevel@tonic-gate 		error(buf);
5850Sstevel@tonic-gate 	}
5860Sstevel@tonic-gate 	tname = make_tempname(fname);
5870Sstevel@tonic-gate 	tfp = open_temp(tname);
5880Sstevel@tonic-gate 	if (line != 1) {
5890Sstevel@tonic-gate 		if (copy_file(fp, tfp, 1, line - 1)) {
5900Sstevel@tonic-gate 			(void) unlink(tname);
5910Sstevel@tonic-gate 			Saferrno = E_SYSERR;
5920Sstevel@tonic-gate 			error("error accessing temp file");
5930Sstevel@tonic-gate 		}
5940Sstevel@tonic-gate 	}
5950Sstevel@tonic-gate 	if (copy_file(fp, tfp, line + 1, -1)) {
5960Sstevel@tonic-gate 		(void) unlink(tname);
5970Sstevel@tonic-gate 		Saferrno = E_SYSERR;
5980Sstevel@tonic-gate 		error("error accessing temp file");
5990Sstevel@tonic-gate 	}
6000Sstevel@tonic-gate 	(void) fclose(fp);
6010Sstevel@tonic-gate 	if (fclose(tfp) == EOF) {
6020Sstevel@tonic-gate 		(void) unlink(tname);
6030Sstevel@tonic-gate 		Saferrno = E_SYSERR;
6040Sstevel@tonic-gate 		error("error closing tempfile");
6050Sstevel@tonic-gate 	}
6060Sstevel@tonic-gate 	/* note - replace only returns if successful */
6070Sstevel@tonic-gate 	replace(fname, tname);
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate /*
6100Sstevel@tonic-gate  * tell the SAC to to tell PM to read _pmtab
6110Sstevel@tonic-gate  */
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate 	if (tell_sac(pmtag)) {
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate /*
6160Sstevel@tonic-gate  * if we got rid of the service, try to remove the config script too.
6170Sstevel@tonic-gate  * Don't check return status since it may not have existed anyhow.
6180Sstevel@tonic-gate  */
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 		(void) sprintf(buf, "%s/%s/%s", HOME, pmtag, svctag);
6210Sstevel@tonic-gate 		(void) unlink(buf);
6220Sstevel@tonic-gate 		return;
6230Sstevel@tonic-gate 	}
6240Sstevel@tonic-gate }
6250Sstevel@tonic-gate 
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 
6280Sstevel@tonic-gate /*
6290Sstevel@tonic-gate  * ed_svc - enable or disable a particular service
6300Sstevel@tonic-gate  *
6310Sstevel@tonic-gate  *	args:	pmtag - tag of port monitor responsible for the service
6320Sstevel@tonic-gate  *		svctag - tag of service to be enabled or disabled
6330Sstevel@tonic-gate  *		flag - operation to perform (ENABLE or DISABLE)
6340Sstevel@tonic-gate  */
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate void
ed_svc(pmtag,svctag,flag)6370Sstevel@tonic-gate ed_svc(pmtag, svctag, flag)
6380Sstevel@tonic-gate char *pmtag;
6390Sstevel@tonic-gate char *svctag;
6400Sstevel@tonic-gate int flag;
6410Sstevel@tonic-gate {
6420Sstevel@tonic-gate 	FILE *fp;		/* scratch file pointer */
6430Sstevel@tonic-gate 	FILE *tfp;		/* file pointer for temp file */
6440Sstevel@tonic-gate 	int line;		/* line number entry is on */
6450Sstevel@tonic-gate 	register char *from;	/* working pointer */
6460Sstevel@tonic-gate 	register char *to;	/* working pointer */
6470Sstevel@tonic-gate 	char *tname;		/* temp file name */
6480Sstevel@tonic-gate 	char *p;		/* scratch pointer */
6490Sstevel@tonic-gate 	char buf[SIZE];		/* scratch buffer */
6500Sstevel@tonic-gate 	char tbuf[SIZE];	/* scratch buffer */
6510Sstevel@tonic-gate 	char fname[SIZE];	/* path to correct _pmtab */
6520Sstevel@tonic-gate 
6530Sstevel@tonic-gate 	fp = fopen(SACTAB, "r");
6540Sstevel@tonic-gate 	if (fp == NULL) {
6550Sstevel@tonic-gate 		Saferrno = E_SYSERR;
6560Sstevel@tonic-gate 		error("Could not open _sactab");
6570Sstevel@tonic-gate 	}
6580Sstevel@tonic-gate 	if (!find_pm(fp, pmtag)) {
6590Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist", pmtag);
6600Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
6610Sstevel@tonic-gate 		error(buf);
6620Sstevel@tonic-gate 	}
6630Sstevel@tonic-gate 	(void) fclose(fp);
6640Sstevel@tonic-gate 
6650Sstevel@tonic-gate 	(void) sprintf(fname, "%s/_pmtab", pmtag);
6660Sstevel@tonic-gate 	(void) sprintf(buf, "%s/%s", HOME, fname);
6670Sstevel@tonic-gate 	fp = fopen(buf, "r");
6680Sstevel@tonic-gate 	if (fp == NULL) {
6690Sstevel@tonic-gate 		(void) sprintf(buf, "Could not open %s/%s", HOME, fname);
6700Sstevel@tonic-gate 		Saferrno = E_SYSERR;
6710Sstevel@tonic-gate 		error(buf);
6720Sstevel@tonic-gate 	}
6730Sstevel@tonic-gate 	if ((line = find_svc(fp, pmtag, svctag)) == 0) {
6740Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist under %s", svctag, pmtag);
6750Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
6760Sstevel@tonic-gate 		error(buf);
6770Sstevel@tonic-gate 	}
6780Sstevel@tonic-gate 	tname = make_tempname(fname);
6790Sstevel@tonic-gate 	tfp = open_temp(tname);
6800Sstevel@tonic-gate 	if (line != 1) {
6810Sstevel@tonic-gate 		if (copy_file(fp, tfp, 1, line - 1)) {
6820Sstevel@tonic-gate 			(void) unlink(tname);
6830Sstevel@tonic-gate 			Saferrno = E_SYSERR;
6840Sstevel@tonic-gate 			error("error accessing temp file");
6850Sstevel@tonic-gate 		}
6860Sstevel@tonic-gate 	}
6870Sstevel@tonic-gate 
6880Sstevel@tonic-gate /*
6890Sstevel@tonic-gate  * Note: find_svc above has already read and parsed this entry, thus
6900Sstevel@tonic-gate  * we know it to be well-formed, so just change the flags as appropriate
6910Sstevel@tonic-gate  */
6920Sstevel@tonic-gate 
6930Sstevel@tonic-gate 	if (fgets(buf, SIZE, fp) == NULL) {
6940Sstevel@tonic-gate 		(void) unlink(tname);
6950Sstevel@tonic-gate 		Saferrno = E_SYSERR;
6960Sstevel@tonic-gate 		error("error accessing temp file");
6970Sstevel@tonic-gate 	}
6980Sstevel@tonic-gate 	from = buf;
6990Sstevel@tonic-gate 	to = tbuf;
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate /*
7020Sstevel@tonic-gate  * copy initial portion of entry
7030Sstevel@tonic-gate  */
7040Sstevel@tonic-gate 
7050Sstevel@tonic-gate 	p = strchr(from, DELIMC);
7060Sstevel@tonic-gate 	for ( ; from <= p; )
7070Sstevel@tonic-gate 		*to++ = *from++;
7080Sstevel@tonic-gate 
7090Sstevel@tonic-gate /*
7100Sstevel@tonic-gate  * isolate and fix the flags
7110Sstevel@tonic-gate  */
7120Sstevel@tonic-gate 
7130Sstevel@tonic-gate 	p = strchr(from, DELIMC);
7140Sstevel@tonic-gate 	for ( ; from < p; ) {
7150Sstevel@tonic-gate 		if (*from == 'x') {
7160Sstevel@tonic-gate 			from++;
7170Sstevel@tonic-gate 			continue;
7180Sstevel@tonic-gate 		}
7190Sstevel@tonic-gate 		*to++ = *from++;
7200Sstevel@tonic-gate 	}
7210Sstevel@tonic-gate 
7220Sstevel@tonic-gate /*
7230Sstevel@tonic-gate  * above we removed x flag, if this was a disable operation, stick it in
7240Sstevel@tonic-gate  * and also copy the field delimiter
7250Sstevel@tonic-gate  */
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate 	if (flag == DISABLE)
7280Sstevel@tonic-gate 		*to++ = 'x';
7290Sstevel@tonic-gate 	*to++ = *from++;
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate /*
7320Sstevel@tonic-gate  * copy the rest of the line
7330Sstevel@tonic-gate  */
7340Sstevel@tonic-gate 
7350Sstevel@tonic-gate 	for ( ; from < &buf[SIZE - 1] ;)
7360Sstevel@tonic-gate 		*to++ = *from++;
7370Sstevel@tonic-gate /***	*to = '\0';  BUG: Don't uncomment it ****/
7380Sstevel@tonic-gate 
7390Sstevel@tonic-gate 	(void) fprintf(tfp, "%s", tbuf);
7400Sstevel@tonic-gate 
7410Sstevel@tonic-gate 	if (copy_file(fp, tfp, line + 1, -1)) {
7420Sstevel@tonic-gate 		(void) unlink(tname);
7430Sstevel@tonic-gate 		Saferrno = E_SYSERR;
7440Sstevel@tonic-gate 		error("error accessing temp file");
7450Sstevel@tonic-gate 	}
7460Sstevel@tonic-gate 	(void) fclose(fp);
7470Sstevel@tonic-gate 	if (fclose(tfp) == EOF) {
7480Sstevel@tonic-gate 		(void) unlink(tname);
7490Sstevel@tonic-gate 		Saferrno = E_SYSERR;
7500Sstevel@tonic-gate 		error("error closing tempfile");
7510Sstevel@tonic-gate 	}
7520Sstevel@tonic-gate 	/* note - replace only returns if successful */
7530Sstevel@tonic-gate 	replace(fname, tname);
7540Sstevel@tonic-gate 
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate /*
7570Sstevel@tonic-gate  * tell the SAC to to tell PM to read _pmtab
7580Sstevel@tonic-gate  */
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate 	(void) tell_sac(pmtag);
7610Sstevel@tonic-gate }
7620Sstevel@tonic-gate 
7630Sstevel@tonic-gate 
7640Sstevel@tonic-gate /*
7650Sstevel@tonic-gate  * doconf - take a config script and have it put where it belongs or
7660Sstevel@tonic-gate  *	    output an existing one
7670Sstevel@tonic-gate  *
7680Sstevel@tonic-gate  *	args:	script - name of file containing script (if NULL, means
7690Sstevel@tonic-gate  *			 output existing one instead)
7700Sstevel@tonic-gate  *		tag - tag of port monitor that is responsible for the
7710Sstevel@tonic-gate  *		      designated service (may be null)
7720Sstevel@tonic-gate  *		type - type of port monitor that is responsible for the
7730Sstevel@tonic-gate  *		       designated service (may be null)
7740Sstevel@tonic-gate  *		svctag - tag of service whose config script we're operating on
7750Sstevel@tonic-gate  */
7760Sstevel@tonic-gate 
7770Sstevel@tonic-gate void
doconf(script,tag,type,svctag)7780Sstevel@tonic-gate doconf(script, tag, type, svctag)
7790Sstevel@tonic-gate char *script;
7800Sstevel@tonic-gate char *tag;
7810Sstevel@tonic-gate char *type;
7820Sstevel@tonic-gate char *svctag;
7830Sstevel@tonic-gate {
7840Sstevel@tonic-gate 	FILE *fp;			/* scratch file pointer */
7850Sstevel@tonic-gate 	int added;			/* count of config scripts added */
7860Sstevel@tonic-gate 	struct taglist tl;		/* 'list' for degenerate case (1 PM) */
7870Sstevel@tonic-gate 	register struct taglist *tp = NULL;	/* working pointer */
7880Sstevel@tonic-gate 	char buf[SIZE];			/* scratch buffer */
7890Sstevel@tonic-gate 	char fname[SIZE];		/* scratch buffer for names */
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate 	fp = fopen(SACTAB, "r");
7920Sstevel@tonic-gate 	if (fp == NULL) {
7930Sstevel@tonic-gate 		Saferrno = E_SYSERR;
7940Sstevel@tonic-gate 		error("Could not open _sactab");
7950Sstevel@tonic-gate 	}
7960Sstevel@tonic-gate 	if (tag && !find_pm(fp, tag)) {
7970Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist", tag);
7980Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
7990Sstevel@tonic-gate 		error(buf);
8000Sstevel@tonic-gate 	}
8010Sstevel@tonic-gate 	if (type && !(tp = find_type(fp, type))) {
8020Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist", type);
8030Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
8040Sstevel@tonic-gate 		error(buf);
8050Sstevel@tonic-gate 	}
8060Sstevel@tonic-gate 	(void) fclose(fp);
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate 	if (tag) {
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate /*
8110Sstevel@tonic-gate  * treat the case of 1 PM as a degenerate case of a list of PMs from a
8120Sstevel@tonic-gate  * type specification.  Build the 'list' here.
8130Sstevel@tonic-gate  */
8140Sstevel@tonic-gate 
8150Sstevel@tonic-gate 		tp = &tl;
8160Sstevel@tonic-gate 		tp->t_next = NULL;
8170Sstevel@tonic-gate 		(void) strcpy(tp->t_tag, tag);
8180Sstevel@tonic-gate 	}
8190Sstevel@tonic-gate 
8200Sstevel@tonic-gate 	added = 0;
8210Sstevel@tonic-gate 	while (tp) {
8220Sstevel@tonic-gate 		(void) sprintf(fname, "%s/%s/_pmtab", HOME, tp->t_tag);
8230Sstevel@tonic-gate 		fp = fopen(fname, "r");
8240Sstevel@tonic-gate 		if (fp == NULL) {
8250Sstevel@tonic-gate 			(void) sprintf(buf, "Could not open %s", fname);
8260Sstevel@tonic-gate 			Saferrno = E_SYSERR;
8270Sstevel@tonic-gate 			error(buf);
8280Sstevel@tonic-gate 		}
8290Sstevel@tonic-gate 		if (!find_svc(fp, tp->t_tag, svctag)) {
8300Sstevel@tonic-gate 			if (tag) {
8310Sstevel@tonic-gate 				/* special case of tag only */
8320Sstevel@tonic-gate 				(void) sprintf(buf, "Invalid request, %s does not exist under %s", svctag, tag);
8330Sstevel@tonic-gate 				Saferrno = E_NOEXIST;
8340Sstevel@tonic-gate 				error(buf);
8350Sstevel@tonic-gate 			}
8360Sstevel@tonic-gate 			else {
8370Sstevel@tonic-gate 				(void) fprintf(stderr, "warning - %s does not exist under %s - ignoring\n", svctag, tp->t_tag);
8380Sstevel@tonic-gate 				Saferrno = E_NOEXIST;
8390Sstevel@tonic-gate 				tp = tp->t_next;
8400Sstevel@tonic-gate 				(void) fclose(fp);
8410Sstevel@tonic-gate 				continue;
8420Sstevel@tonic-gate 			}
8430Sstevel@tonic-gate 		}
8440Sstevel@tonic-gate 		(void) fclose(fp);
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 		(void) sprintf(fname, "%s/%s", tp->t_tag, svctag);
8470Sstevel@tonic-gate 
8480Sstevel@tonic-gate /*
8490Sstevel@tonic-gate  * do_config does all the real work (keep track if any errors occurred)
8500Sstevel@tonic-gate  */
8510Sstevel@tonic-gate 
8520Sstevel@tonic-gate 		if (do_config(script, fname) == 0)
8530Sstevel@tonic-gate 			added++;
8540Sstevel@tonic-gate 		tp = tp->t_next;
8550Sstevel@tonic-gate 	}
8560Sstevel@tonic-gate 	if (added == 0) {
8570Sstevel@tonic-gate 		Saferrno = E_SAFERR;
8580Sstevel@tonic-gate 		error("No configuration scripts installed");
8590Sstevel@tonic-gate 	}
8600Sstevel@tonic-gate 	return;
8610Sstevel@tonic-gate }
8620Sstevel@tonic-gate 
8630Sstevel@tonic-gate 
8640Sstevel@tonic-gate /*
8650Sstevel@tonic-gate  * tell_sac - use sacadm to tell the sac to tell a port monitor to read
8660Sstevel@tonic-gate  *	its _pmtab.  Return TRUE on success, FALSE on failure.
8670Sstevel@tonic-gate  *
8680Sstevel@tonic-gate  *	args:	tag - tag of port monitor to be notified
8690Sstevel@tonic-gate  */
8700Sstevel@tonic-gate 
8710Sstevel@tonic-gate 
872*334Sdp int
tell_sac(char * tag)873*334Sdp tell_sac(char *tag)
8740Sstevel@tonic-gate {
8750Sstevel@tonic-gate 	pid_t pid;	/* returned pid from fork */
8760Sstevel@tonic-gate 	int status;	/* return status from sacadm child */
8770Sstevel@tonic-gate 
8780Sstevel@tonic-gate 	if ((pid = fork()) < 0) {
8790Sstevel@tonic-gate 		(void) fprintf(stderr, "warning - fork failed - could not notify <%s> about modified table\n", tag);
8800Sstevel@tonic-gate 		(void) fprintf(stderr, "try executing the command \"sacadm -x -p %s\"\n", tag);
8810Sstevel@tonic-gate 		Saferrno = E_SYSERR;
8820Sstevel@tonic-gate 		return(FALSE);
8830Sstevel@tonic-gate 	}
8840Sstevel@tonic-gate 	else if (pid) {
8850Sstevel@tonic-gate 		/* parent */
8860Sstevel@tonic-gate 		(void) wait(&status);
8870Sstevel@tonic-gate 		if (status) {
8880Sstevel@tonic-gate 			if (((status >> 8) & 0xff) == E_PMNOTRUN) {
8890Sstevel@tonic-gate 				(void) fprintf(stderr, "warning - port monitor, %s is not running\n", tag);
8900Sstevel@tonic-gate 				return (FALSE);
8910Sstevel@tonic-gate 			}
8920Sstevel@tonic-gate 			if (((status >> 8) & 0xff) == E_SACNOTRUN) {
8930Sstevel@tonic-gate 				Saferrno = E_SACNOTRUN;
8940Sstevel@tonic-gate 			} else {
8950Sstevel@tonic-gate 				Saferrno = E_SYSERR;
8960Sstevel@tonic-gate 			}
8970Sstevel@tonic-gate 			(void) fprintf(stderr,
8980Sstevel@tonic-gate 			    "warning - could not notify <%s> about modified"
8990Sstevel@tonic-gate 			    " table\n", tag);
9000Sstevel@tonic-gate 			(void) fprintf(stderr, "try executing the command"
9010Sstevel@tonic-gate 			    " \"sacadm -x -p %s\"\n", tag);
9020Sstevel@tonic-gate 			return(FALSE);
9030Sstevel@tonic-gate 		}
9040Sstevel@tonic-gate 		else {
9050Sstevel@tonic-gate 			return(TRUE);
9060Sstevel@tonic-gate 		}
9070Sstevel@tonic-gate 	}
9080Sstevel@tonic-gate 	else {
9090Sstevel@tonic-gate 		/* set IFS for security */
9100Sstevel@tonic-gate 		(void) putenv("IFS=\" \"");
9110Sstevel@tonic-gate 		/* muffle sacadm warning messages */
9120Sstevel@tonic-gate 		(void) fclose(stderr);
9130Sstevel@tonic-gate 		(void) fopen("/dev/null", "w");
9140Sstevel@tonic-gate 		(void) execl("/usr/sbin/sacadm", "sacadm", "-x", "-p", tag, 0);
9150Sstevel@tonic-gate 
9160Sstevel@tonic-gate /*
9170Sstevel@tonic-gate  * if we got here, it didn't work, exit status will clue in parent to
9180Sstevel@tonic-gate  * put out the warning
9190Sstevel@tonic-gate  */
9200Sstevel@tonic-gate 
9210Sstevel@tonic-gate 		exit(1);
9220Sstevel@tonic-gate 	}
9230Sstevel@tonic-gate 	/* NOTREACHED */
9240Sstevel@tonic-gate }
9250Sstevel@tonic-gate 
9260Sstevel@tonic-gate 
9270Sstevel@tonic-gate /*
9280Sstevel@tonic-gate  * list_svcs - list information about services
9290Sstevel@tonic-gate  *
9300Sstevel@tonic-gate  *	args:	pmtag - tag of port monitor responsible for the service
9310Sstevel@tonic-gate  *			(may be null)
9320Sstevel@tonic-gate  *		type - type of port monitor responsible for the service
9330Sstevel@tonic-gate  *		       (may be null)
9340Sstevel@tonic-gate  *		svctag - tag of service to be listed (may be null)
9350Sstevel@tonic-gate  *		oflag - true if output should be easily parseable
9360Sstevel@tonic-gate  */
9370Sstevel@tonic-gate 
9380Sstevel@tonic-gate void
list_svcs(pmtag,type,svctag,oflag)9390Sstevel@tonic-gate list_svcs(pmtag, type, svctag, oflag)
9400Sstevel@tonic-gate char *pmtag;
9410Sstevel@tonic-gate char *type;
9420Sstevel@tonic-gate char *svctag;
9430Sstevel@tonic-gate {
9440Sstevel@tonic-gate 	FILE *fp;				/* scratch file pointer */
9450Sstevel@tonic-gate 	register struct taglist *tp;		/* pointer to PM list */
9460Sstevel@tonic-gate 	int nprint = 0;				/* count # of svcs printed */
9470Sstevel@tonic-gate 	struct pmtab pmtab;			/* place to hold parsed info */
9480Sstevel@tonic-gate 	register struct pmtab *pp = &pmtab;	/* and a pointer to it */
9490Sstevel@tonic-gate 	register char *p;			/* working pointer */
9500Sstevel@tonic-gate 	char buf[SIZE];				/* scratch buffer */
9510Sstevel@tonic-gate 	char fname[SIZE];			/* scratch buffer for building names */
9520Sstevel@tonic-gate 
9530Sstevel@tonic-gate 	fp = fopen(SACTAB, "r");
9540Sstevel@tonic-gate 	if (fp == NULL) {
9550Sstevel@tonic-gate 		Saferrno = E_SYSERR;
9560Sstevel@tonic-gate 		error("Could not open _sactab");
9570Sstevel@tonic-gate 	}
9580Sstevel@tonic-gate 	if (pmtag && !find_pm(fp, pmtag)) {
9590Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist", pmtag);
9600Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
9610Sstevel@tonic-gate 		error(buf);
9620Sstevel@tonic-gate 	}
9630Sstevel@tonic-gate 	rewind(fp);
9640Sstevel@tonic-gate 	if (type) {
9650Sstevel@tonic-gate 		tp = find_type(fp, type);
9660Sstevel@tonic-gate 		if (tp == NULL) {
9670Sstevel@tonic-gate 			(void) sprintf(buf, "Invalid request, %s does not exist", type);
9680Sstevel@tonic-gate 			Saferrno = E_NOEXIST;
9690Sstevel@tonic-gate 			error(buf);
9700Sstevel@tonic-gate 		}
9710Sstevel@tonic-gate 	}
9720Sstevel@tonic-gate 	else
9730Sstevel@tonic-gate 		tp = find_type(fp, NULL);
9740Sstevel@tonic-gate 	(void) fclose(fp);
9750Sstevel@tonic-gate 
9760Sstevel@tonic-gate 	while (tp) {
9770Sstevel@tonic-gate 		if (pmtag && strcmp(tp->t_tag, pmtag)) {
9780Sstevel@tonic-gate 			/* not interested in this port monitor */
9790Sstevel@tonic-gate 			tp = tp->t_next;
9800Sstevel@tonic-gate 			continue;
9810Sstevel@tonic-gate 		}
9820Sstevel@tonic-gate 		(void) sprintf(fname, "%s/%s/_pmtab", HOME, tp->t_tag);
9830Sstevel@tonic-gate 		fp = fopen(fname, "r");
9840Sstevel@tonic-gate 		if (fp == NULL) {
9850Sstevel@tonic-gate 			(void) sprintf(buf, "Could not open %s", fname);
9860Sstevel@tonic-gate 			Saferrno = E_SYSERR;
9870Sstevel@tonic-gate 			error(buf);
9880Sstevel@tonic-gate 		}
9890Sstevel@tonic-gate 		while (fgets(buf, SIZE, fp)) {
9900Sstevel@tonic-gate 			p = trim(buf);
9910Sstevel@tonic-gate 			if (*p == '\0')
9920Sstevel@tonic-gate 				continue;
9930Sstevel@tonic-gate 			parseline(p, pp, tp->t_tag);
9940Sstevel@tonic-gate 			if (!svctag || !strcmp(pp->p_tag, svctag)) {
9950Sstevel@tonic-gate 				if (oflag) {
9960Sstevel@tonic-gate 					(void) printf("%s:%s:%s:%s:%s:%s:%s:%s:%s#%s\n",
9970Sstevel@tonic-gate 						tp->t_tag, tp->t_type, pp->p_tag,
9980Sstevel@tonic-gate 						pflags(pp->p_flags, FALSE),
9990Sstevel@tonic-gate 						pp->p_id, pp->p_res1, pp->p_res2,
10000Sstevel@tonic-gate 						pp->p_res3,pp->p_pmspec, Comment);
10010Sstevel@tonic-gate 				}
10020Sstevel@tonic-gate 				else {
10030Sstevel@tonic-gate 					if (nprint == 0) {
10040Sstevel@tonic-gate 						(void) printf("PMTAG          PMTYPE         SVCTAG         FLGS ID       <PMSPECIFIC>\n");
10050Sstevel@tonic-gate 					}
10060Sstevel@tonic-gate 					(void) printf("%-14s %-14s %-14s %-4s %-8s %s #%s\n", tp->t_tag, tp->t_type, pp->p_tag,
10070Sstevel@tonic-gate 						pflags(pp->p_flags, TRUE), pp->p_id, pspec(pp->p_pmspec), Comment);
10080Sstevel@tonic-gate 				}
10090Sstevel@tonic-gate 				nprint++;
10100Sstevel@tonic-gate 			}
10110Sstevel@tonic-gate 		}
10120Sstevel@tonic-gate 		if (!feof(fp)) {
10130Sstevel@tonic-gate 			(void) sprintf(buf, "error reading %s", fname);
10140Sstevel@tonic-gate 			Saferrno = E_SYSERR;
10150Sstevel@tonic-gate 			error(buf);
10160Sstevel@tonic-gate 		}
10170Sstevel@tonic-gate 		else {
10180Sstevel@tonic-gate 			(void) fclose(fp);
10190Sstevel@tonic-gate 			tp = tp->t_next;
10200Sstevel@tonic-gate 		}
10210Sstevel@tonic-gate 	}
10220Sstevel@tonic-gate 	/* if we didn't find any valid ones, indicate an error */
10230Sstevel@tonic-gate 	if (nprint == 0) {
10240Sstevel@tonic-gate 		if (svctag)
10250Sstevel@tonic-gate 			(void) fprintf(stderr, "Service <%s> does not exist\n", svctag);
10260Sstevel@tonic-gate 		else
10270Sstevel@tonic-gate 			(void) fprintf(stderr, "No services defined\n");
10280Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
10290Sstevel@tonic-gate 	}
10300Sstevel@tonic-gate 	return;
10310Sstevel@tonic-gate }
10320Sstevel@tonic-gate 
10330Sstevel@tonic-gate 
10340Sstevel@tonic-gate /*
10350Sstevel@tonic-gate  * find_svc - find an entry in _pmtab for a particular service tag
10360Sstevel@tonic-gate  *
10370Sstevel@tonic-gate  *	args:	fp - file pointer for _pmtab
10380Sstevel@tonic-gate  *		tag - port monitor tag (for error reporting)
10390Sstevel@tonic-gate  *		svctag - tag of service we're looking for
10400Sstevel@tonic-gate  */
10410Sstevel@tonic-gate 
1042*334Sdp int
find_svc(FILE * fp,char * tag,char * svctag)1043*334Sdp find_svc(FILE *fp, char *tag, char *svctag)
10440Sstevel@tonic-gate {
10450Sstevel@tonic-gate 	register char *p;	/* working pointer */
10460Sstevel@tonic-gate 	int line = 0;		/* line number we found entry on */
10470Sstevel@tonic-gate 	struct pmtab pmtab;	/* place to hold parsed info */
10480Sstevel@tonic-gate 	static char buf[SIZE];	/* scratch buffer */
10490Sstevel@tonic-gate 
10500Sstevel@tonic-gate 	while (fgets(buf, SIZE, fp)) {
10510Sstevel@tonic-gate 		line++;
10520Sstevel@tonic-gate 		p = trim(buf);
10530Sstevel@tonic-gate 		if (*p == '\0')
10540Sstevel@tonic-gate 			continue;
10550Sstevel@tonic-gate 		parseline(p, &pmtab, tag);
10560Sstevel@tonic-gate 		if (!(strcmp(pmtab.p_tag, svctag)))
10570Sstevel@tonic-gate 			return(line);
10580Sstevel@tonic-gate 	}
10590Sstevel@tonic-gate 	if (!feof(fp)) {
10600Sstevel@tonic-gate 		(void) sprintf(buf, "error reading %s/%s/_pmtab", HOME, tag);
10610Sstevel@tonic-gate 		Saferrno = E_SYSERR;
10620Sstevel@tonic-gate 		error(buf);
1063*334Sdp 		/* NOTREACHED */
1064*334Sdp 		return (0);
1065*334Sdp 	} else
1066*334Sdp 		return (0);
10670Sstevel@tonic-gate }
10680Sstevel@tonic-gate 
10690Sstevel@tonic-gate 
10700Sstevel@tonic-gate /*
10710Sstevel@tonic-gate  * parseline - parse a line from _pmtab.  This routine will return if the
10720Sstevel@tonic-gate  *		parse wa successful, otherwise it will output an error and
10730Sstevel@tonic-gate  *		exit.
10740Sstevel@tonic-gate  *
10750Sstevel@tonic-gate  *	args:	p - pointer to the data read from the file (note - this is
10760Sstevel@tonic-gate  *		    a static data region, so we can point into it)
10770Sstevel@tonic-gate  *		pp - pointer to a structure in which the separated fields
10780Sstevel@tonic-gate  *		     are placed
10790Sstevel@tonic-gate  *		tag - port monitor tag (for error reporting)
10800Sstevel@tonic-gate  *
10810Sstevel@tonic-gate  *	A line in the file has the following format:
10820Sstevel@tonic-gate  *
10830Sstevel@tonic-gate  *	tag:flags:identity:reserved:reserved:reserved:PM_spec_info # comment
10840Sstevel@tonic-gate  */
10850Sstevel@tonic-gate 
10860Sstevel@tonic-gate 
10870Sstevel@tonic-gate void
parseline(p,pp,tag)10880Sstevel@tonic-gate parseline(p, pp, tag)
10890Sstevel@tonic-gate register char *p;
10900Sstevel@tonic-gate register struct pmtab *pp;
10910Sstevel@tonic-gate char *tag;
10920Sstevel@tonic-gate {
10930Sstevel@tonic-gate 	char buf[SIZE];	/* scratch buffer */
10940Sstevel@tonic-gate 
10950Sstevel@tonic-gate /*
10960Sstevel@tonic-gate  * get the service tag
10970Sstevel@tonic-gate  */
10980Sstevel@tonic-gate 
10990Sstevel@tonic-gate 	p = nexttok(p, DELIM, FALSE);
11000Sstevel@tonic-gate 	if (p == NULL) {
11010Sstevel@tonic-gate 		(void) sprintf(buf, "%s/%s/_pmtab is corrupt", HOME, tag);
11020Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11030Sstevel@tonic-gate 		error(buf);
11040Sstevel@tonic-gate 	}
11050Sstevel@tonic-gate 	if (strlen(p) > PMTAGSIZE) {
11060Sstevel@tonic-gate 		p[PMTAGSIZE] = '\0';
11070Sstevel@tonic-gate 		(void) fprintf(stderr, "tag too long, truncated to <%s>", p);
11080Sstevel@tonic-gate 	}
11090Sstevel@tonic-gate 	pp->p_tag = p;
11100Sstevel@tonic-gate 
11110Sstevel@tonic-gate /*
11120Sstevel@tonic-gate  * get the flags
11130Sstevel@tonic-gate  */
11140Sstevel@tonic-gate 
11150Sstevel@tonic-gate 	p = nexttok(NULL, DELIM, FALSE);
11160Sstevel@tonic-gate 	if (p == NULL) {
11170Sstevel@tonic-gate 		(void) sprintf(buf, "%s/%s/_pmtab is corrupt", HOME, tag);
11180Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11190Sstevel@tonic-gate 		error(buf);
11200Sstevel@tonic-gate 	}
11210Sstevel@tonic-gate 	pp->p_flags = 0;
11220Sstevel@tonic-gate 	while (*p) {
11230Sstevel@tonic-gate 		switch (*p++) {
11240Sstevel@tonic-gate 		case 'u':
11250Sstevel@tonic-gate 			pp->p_flags |= U_FLAG;
11260Sstevel@tonic-gate 			break;
11270Sstevel@tonic-gate 		case 'x':
11280Sstevel@tonic-gate 			pp->p_flags |= X_FLAG;
11290Sstevel@tonic-gate 			break;
11300Sstevel@tonic-gate 		default:
11310Sstevel@tonic-gate 			(void) sprintf(buf, "Unrecognized flag <%c>", *(p - 1));
11320Sstevel@tonic-gate 			Saferrno = E_SAFERR;
11330Sstevel@tonic-gate 			error(buf);
11340Sstevel@tonic-gate 			break;
11350Sstevel@tonic-gate 		}
11360Sstevel@tonic-gate 	}
11370Sstevel@tonic-gate 
11380Sstevel@tonic-gate /*
11390Sstevel@tonic-gate  * get the identity
11400Sstevel@tonic-gate  */
11410Sstevel@tonic-gate 
11420Sstevel@tonic-gate 	p = nexttok(NULL, DELIM, FALSE);
11430Sstevel@tonic-gate 	if (p == NULL) {
11440Sstevel@tonic-gate 		(void) sprintf(buf, "%s/%s/_pmtab is corrupt", HOME, tag);
11450Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11460Sstevel@tonic-gate 		error(buf);
11470Sstevel@tonic-gate 	}
11480Sstevel@tonic-gate 	pp->p_id = p;
11490Sstevel@tonic-gate 
11500Sstevel@tonic-gate /*
11510Sstevel@tonic-gate  * get the first reserved field
11520Sstevel@tonic-gate  */
11530Sstevel@tonic-gate 
11540Sstevel@tonic-gate 	p = nexttok(NULL, DELIM, FALSE);
11550Sstevel@tonic-gate 	if (p == NULL) {
11560Sstevel@tonic-gate 		(void) sprintf(buf, "%s/%s/_pmtab is corrupt", HOME, tag);
11570Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11580Sstevel@tonic-gate 		error(buf);
11590Sstevel@tonic-gate 	}
11600Sstevel@tonic-gate 	pp->p_res1 = p;
11610Sstevel@tonic-gate 
11620Sstevel@tonic-gate /*
11630Sstevel@tonic-gate  * get the second reserved field
11640Sstevel@tonic-gate  */
11650Sstevel@tonic-gate 
11660Sstevel@tonic-gate 	p = nexttok(NULL, DELIM, FALSE);
11670Sstevel@tonic-gate 	if (p == NULL) {
11680Sstevel@tonic-gate 		(void) sprintf(buf, "%s/%s/_pmtab is corrupt", HOME, tag);
11690Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11700Sstevel@tonic-gate 		error(buf);
11710Sstevel@tonic-gate 	}
11720Sstevel@tonic-gate 	pp->p_res2 = p;
11730Sstevel@tonic-gate 
11740Sstevel@tonic-gate /*
11750Sstevel@tonic-gate  * get the third reserved field
11760Sstevel@tonic-gate  */
11770Sstevel@tonic-gate 
11780Sstevel@tonic-gate 	p = nexttok(NULL, DELIM, FALSE);
11790Sstevel@tonic-gate 	if (p == NULL) {
11800Sstevel@tonic-gate 		(void) sprintf(buf, "%s/%s/_pmtab is corrupt", HOME, tag);
11810Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11820Sstevel@tonic-gate 		error(buf);
11830Sstevel@tonic-gate 	}
11840Sstevel@tonic-gate 	pp->p_res3 = p;
11850Sstevel@tonic-gate 
11860Sstevel@tonic-gate /*
11870Sstevel@tonic-gate  * the rest is the port monitor specific info
11880Sstevel@tonic-gate  */
11890Sstevel@tonic-gate 
11900Sstevel@tonic-gate 	p = nexttok(NULL, DELIM, TRUE);
11910Sstevel@tonic-gate 	if (p == NULL) {
11920Sstevel@tonic-gate 		(void) sprintf(buf, "%s/%s/_pmtab is corrupt", HOME, tag);
11930Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11940Sstevel@tonic-gate 		error(buf);
11950Sstevel@tonic-gate 	}
11960Sstevel@tonic-gate 	pp->p_pmspec = p;
11970Sstevel@tonic-gate 	return;
11980Sstevel@tonic-gate }
11990Sstevel@tonic-gate 
12000Sstevel@tonic-gate 
12010Sstevel@tonic-gate /*
12020Sstevel@tonic-gate  * pspec - format port monitor specific information
12030Sstevel@tonic-gate  *
12040Sstevel@tonic-gate  *	args:	spec - port monitor specific info, separated by
12050Sstevel@tonic-gate  *		       field separater character (may be escaped by \)
12060Sstevel@tonic-gate  */
12070Sstevel@tonic-gate 
12080Sstevel@tonic-gate char *
pspec(spec)12090Sstevel@tonic-gate pspec(spec)
12100Sstevel@tonic-gate char *spec;
12110Sstevel@tonic-gate {
12120Sstevel@tonic-gate 	static char buf[SIZE];		/* returned string */
12130Sstevel@tonic-gate 	register char *from;		/* working pointer */
12140Sstevel@tonic-gate 	register char *to;		/* working pointer */
12150Sstevel@tonic-gate 	int newflag;			/* flag indicating new field */
12160Sstevel@tonic-gate 
12170Sstevel@tonic-gate 	to = buf;
12180Sstevel@tonic-gate 	from = spec;
12190Sstevel@tonic-gate 	newflag = 1;
12200Sstevel@tonic-gate 	while (*from) {
12210Sstevel@tonic-gate 		switch (*from) {
12220Sstevel@tonic-gate 		case ':':
12230Sstevel@tonic-gate 			if (newflag) {
12240Sstevel@tonic-gate 				*to++ = '-';
12250Sstevel@tonic-gate 			}
12260Sstevel@tonic-gate 			*to++ = ' ';
12270Sstevel@tonic-gate 			from++;
12280Sstevel@tonic-gate 			newflag = 1;
12290Sstevel@tonic-gate 			break;
12300Sstevel@tonic-gate 		case '\\':
12310Sstevel@tonic-gate 			if (*(from + 1) == ':') {
12320Sstevel@tonic-gate 				*to++ = ':';
12330Sstevel@tonic-gate 				/* skip over \: */
12340Sstevel@tonic-gate 				from += 2;
12350Sstevel@tonic-gate 			}
12360Sstevel@tonic-gate 			else
12370Sstevel@tonic-gate 				*to++ = *from++;
12380Sstevel@tonic-gate 			newflag = 0;
12390Sstevel@tonic-gate 			break;
12400Sstevel@tonic-gate 		default:
12410Sstevel@tonic-gate 			newflag = 0;
12420Sstevel@tonic-gate 			*to++ = *from++;
12430Sstevel@tonic-gate 		}
12440Sstevel@tonic-gate 	}
12450Sstevel@tonic-gate 	*to = '\0';
12460Sstevel@tonic-gate 	return(buf);
12470Sstevel@tonic-gate }
12480Sstevel@tonic-gate 
12490Sstevel@tonic-gate 
12500Sstevel@tonic-gate /*
12510Sstevel@tonic-gate  * pflags - put service flags into intelligible form for output
12520Sstevel@tonic-gate  *
12530Sstevel@tonic-gate  *	args:	flags - binary representation of flags
12540Sstevel@tonic-gate  *		dflag - true if a "-" should be returned if no flags
12550Sstevel@tonic-gate  */
12560Sstevel@tonic-gate 
12570Sstevel@tonic-gate char *
pflags(flags,dflag)12580Sstevel@tonic-gate pflags(flags, dflag)
12590Sstevel@tonic-gate long flags;
12600Sstevel@tonic-gate int dflag;
12610Sstevel@tonic-gate {
12620Sstevel@tonic-gate 	register int i;			/* scratch counter */
12630Sstevel@tonic-gate 	static char buf[SIZE];		/* formatted flags */
12640Sstevel@tonic-gate 
12650Sstevel@tonic-gate 	if (flags == 0) {
12660Sstevel@tonic-gate 		if (dflag)
12670Sstevel@tonic-gate 			return("-");
12680Sstevel@tonic-gate 		else
12690Sstevel@tonic-gate 			return("");
12700Sstevel@tonic-gate 	}
12710Sstevel@tonic-gate 	i = 0;
12720Sstevel@tonic-gate 	if (flags & U_FLAG) {
12730Sstevel@tonic-gate 		buf[i++] = 'u';
12740Sstevel@tonic-gate 		flags &= ~U_FLAG;
12750Sstevel@tonic-gate 	}
12760Sstevel@tonic-gate 	if (flags & X_FLAG) {
12770Sstevel@tonic-gate 		buf[i++] = 'x';
12780Sstevel@tonic-gate 		flags &= ~X_FLAG;
12790Sstevel@tonic-gate 	}
12800Sstevel@tonic-gate 	if (flags) {
12810Sstevel@tonic-gate 		Saferrno = E_SAFERR;
12820Sstevel@tonic-gate 		error("Internal error in pflags");
12830Sstevel@tonic-gate 	}
12840Sstevel@tonic-gate 	buf[i] = '\0';
12850Sstevel@tonic-gate 	return(buf);
12860Sstevel@tonic-gate }
12870Sstevel@tonic-gate 
12880Sstevel@tonic-gate 
12890Sstevel@tonic-gate /*
12900Sstevel@tonic-gate  * find_type - find entries in _sactab for a particular port monitor type
12910Sstevel@tonic-gate  *
12920Sstevel@tonic-gate  *	args:	fp - file pointer for _sactab
12930Sstevel@tonic-gate  *		type - type of port monitor we're looking for (if type is
12940Sstevel@tonic-gate  *		       null, it means find all PMs)
12950Sstevel@tonic-gate  */
12960Sstevel@tonic-gate 
12970Sstevel@tonic-gate struct taglist *
find_type(fp,type)12980Sstevel@tonic-gate find_type(fp, type)
12990Sstevel@tonic-gate FILE *fp;
13000Sstevel@tonic-gate char *type;
13010Sstevel@tonic-gate {
13020Sstevel@tonic-gate 	register char *p;			/* working pointer */
13030Sstevel@tonic-gate 	struct sactab stab;			/* place to hold parsed info */
13040Sstevel@tonic-gate 	register struct sactab *sp = &stab;	/* and a pointer to it */
13050Sstevel@tonic-gate 	char buf[SIZE];				/* scratch buffer */
13060Sstevel@tonic-gate 	struct taglist *thead;			/* linked list of tags */
13070Sstevel@tonic-gate 	register struct taglist *temp;		/* scratch pointer */
13080Sstevel@tonic-gate 
13090Sstevel@tonic-gate 	thead = NULL;
13100Sstevel@tonic-gate 	while (fgets(buf, SIZE, fp)) {
13110Sstevel@tonic-gate 		p = trim(buf);
13120Sstevel@tonic-gate 		if (*p == '\0')
13130Sstevel@tonic-gate 			continue;
13140Sstevel@tonic-gate 		parse(p, sp);
13150Sstevel@tonic-gate 		if ((type == NULL) || !(strcmp(sp->sc_type, type))) {
13160Sstevel@tonic-gate 			temp = (struct taglist *) malloc(sizeof(struct taglist));
13170Sstevel@tonic-gate 			if (temp == NULL) {
13180Sstevel@tonic-gate 				Saferrno = E_SYSERR;
13190Sstevel@tonic-gate 				error("malloc failed");
13200Sstevel@tonic-gate 			}
13210Sstevel@tonic-gate 			temp->t_next = thead;
13220Sstevel@tonic-gate 			(void) strcpy(temp->t_tag, sp->sc_tag);
13230Sstevel@tonic-gate 			(void) strcpy(temp->t_type, sp->sc_type);
13240Sstevel@tonic-gate 			thead = temp;
13250Sstevel@tonic-gate 		}
13260Sstevel@tonic-gate 	}
13270Sstevel@tonic-gate 	if (!feof(fp)) {
13280Sstevel@tonic-gate 		Saferrno = E_SYSERR;
13290Sstevel@tonic-gate 		error("error reading _sactab");
1330*334Sdp 		/* NOTREACHED */
1331*334Sdp 		return (0);
1332*334Sdp 	} else
1333*334Sdp 		return (thead ? thead : NULL);
13340Sstevel@tonic-gate }
1335