xref: /illumos-gate/usr/src/cmd/saf/pmadm.c (revision c53bc758)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
2334e48580Sdp  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28*c53bc758SToomas Soome /*	  All Rights Reserved	*/
297c478bd9Sstevel@tonic-gate 
3034e48580Sdp #include <stdio.h>
3134e48580Sdp #include <stdlib.h>
3234e48580Sdp #include <strings.h>
3334e48580Sdp #include <sys/types.h>
3434e48580Sdp #include <sys/stat.h>
3534e48580Sdp #include <unistd.h>
3634e48580Sdp #include "extern.h"
3734e48580Sdp #include "misc.h"
3834e48580Sdp #include <sac.h>
3934e48580Sdp #include "structs.h"
4034e48580Sdp 
4134e48580Sdp #define	ADD		0x1	/* -a or other required options seen */
4234e48580Sdp #define	REMOVE		0x2	/* -r seen */
4334e48580Sdp #define	ENABLE		0x4	/* -e seen */
4434e48580Sdp #define	DISABLE		0x8	/* -d seen */
4534e48580Sdp #define	PLIST		0x10	/* -l seen */
4634e48580Sdp #define	LIST		0x20	/* -L seen */
4734e48580Sdp #define	CONFIG		0x40	/* -g seen */
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate # define U_FLAG		0x1	/* -fu seen */
507c478bd9Sstevel@tonic-gate # define X_FLAG		0x2	/* -fx seen */
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate  * functions
547c478bd9Sstevel@tonic-gate  */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate char	*pflags();
577c478bd9Sstevel@tonic-gate char	*pspec();
587c478bd9Sstevel@tonic-gate struct	taglist	*find_type();
597c478bd9Sstevel@tonic-gate void	usage();
607c478bd9Sstevel@tonic-gate void	parseline();
617c478bd9Sstevel@tonic-gate void	add_svc();
627c478bd9Sstevel@tonic-gate void	rem_svc();
637c478bd9Sstevel@tonic-gate void	ed_svc();
647c478bd9Sstevel@tonic-gate void	list_svcs();
657c478bd9Sstevel@tonic-gate void	doconf();
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate /*
687c478bd9Sstevel@tonic-gate  * format of a _pmtab entry - used to hold parsed info
697c478bd9Sstevel@tonic-gate  */
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate struct	pmtab {
727c478bd9Sstevel@tonic-gate 	char	*p_tag;		/* service tag */
737c478bd9Sstevel@tonic-gate 	long	p_flags;	/* flags */
747c478bd9Sstevel@tonic-gate 	char	*p_id;		/* logname to start service as */
757c478bd9Sstevel@tonic-gate 	char	*p_res1;	/* reserved field */
767c478bd9Sstevel@tonic-gate 	char	*p_res2;	/* reserved field */
777c478bd9Sstevel@tonic-gate 	char	*p_res3;	/* reserved field */
787c478bd9Sstevel@tonic-gate 	char	*p_pmspec;	/* port monitor specific info */
797c478bd9Sstevel@tonic-gate };
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate /*
827c478bd9Sstevel@tonic-gate  * format of a tag list, which is a list of port monitor tags of
837c478bd9Sstevel@tonic-gate  * a designated type
847c478bd9Sstevel@tonic-gate  */
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate struct	taglist {
877c478bd9Sstevel@tonic-gate 	struct	taglist	*t_next;	/* next in list */
887c478bd9Sstevel@tonic-gate 	char	t_tag[PMTAGSIZE + 1];	/* PM tag */
897c478bd9Sstevel@tonic-gate 	char	t_type[PMTYPESIZE + 1];	/* PM type */
907c478bd9Sstevel@tonic-gate };
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate /*
937c478bd9Sstevel@tonic-gate  * common error messages
947c478bd9Sstevel@tonic-gate  */
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate # define NOTPRIV	"User not privileged for operation"
977c478bd9Sstevel@tonic-gate # define BADINP		"Embedded newlines not allowed"
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate int	Saferrno;	/* internal `errno' for exit */
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate /*
1037c478bd9Sstevel@tonic-gate  * main - scan args for pmadm and call appropriate handling code
1047c478bd9Sstevel@tonic-gate  */
1057c478bd9Sstevel@tonic-gate 
10634e48580Sdp int
main(int argc,char * argv[])10734e48580Sdp main(int argc, char *argv[])
1087c478bd9Sstevel@tonic-gate {
1097c478bd9Sstevel@tonic-gate 	int c;			/* option letter */
1107c478bd9Sstevel@tonic-gate 	int ret;		/* return code from check_version */
1117c478bd9Sstevel@tonic-gate 	uid_t uid;		/* invoker's real uid */
1127c478bd9Sstevel@tonic-gate 	int flag = 0;		/* flag to record requested operations */
1137c478bd9Sstevel@tonic-gate 	int errflg = 0;		/* error indicator */
1147c478bd9Sstevel@tonic-gate 	int badcnt = 0;		/* count of bad args to -f */
1157c478bd9Sstevel@tonic-gate 	int version = -1;	/* argument to -v */
1167c478bd9Sstevel@tonic-gate 	int sawaflag = 0;	/* true if actually saw -a */
1177c478bd9Sstevel@tonic-gate 	int conflag = 0;	/* true if output should be in condensed form */
1187c478bd9Sstevel@tonic-gate 	long flags = 0;		/* arguments to -f */
1197c478bd9Sstevel@tonic-gate 	char *pmtag = NULL;	/* argument to -p */
1207c478bd9Sstevel@tonic-gate 	char *type = NULL;	/* argument to -t */
1217c478bd9Sstevel@tonic-gate 	char *script = NULL;	/* argument to -z */
1227c478bd9Sstevel@tonic-gate 	char *comment = " ";	/* argument to -y */
1237c478bd9Sstevel@tonic-gate 	char *id = NULL;	/* argument to -i */
1247c478bd9Sstevel@tonic-gate 	char *svctag = NULL;	/* argument to -s */
1257c478bd9Sstevel@tonic-gate 	char *pmspec = NULL;	/* argument to -m */
1267c478bd9Sstevel@tonic-gate 	char badargs[SIZE];	/* place to hold bad args to -f */
1277c478bd9Sstevel@tonic-gate 	char buf[SIZE];		/* scratch buffer */
1287c478bd9Sstevel@tonic-gate 	register char *p;	/* scratch pointer */
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	if (argc == 1)
1317c478bd9Sstevel@tonic-gate 		usage(argv[0]);
1327c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "adef:gi:Llm:p:rs:t:v:y:z:")) != -1) {
1337c478bd9Sstevel@tonic-gate 		switch (c) {
1347c478bd9Sstevel@tonic-gate 		case 'a':
1357c478bd9Sstevel@tonic-gate 			flag |= ADD;
1367c478bd9Sstevel@tonic-gate 			sawaflag = 1;
1377c478bd9Sstevel@tonic-gate 			break;
1387c478bd9Sstevel@tonic-gate 		case 'd':
1397c478bd9Sstevel@tonic-gate 			flag |= DISABLE;
1407c478bd9Sstevel@tonic-gate 			break;
1417c478bd9Sstevel@tonic-gate 		case 'e':
1427c478bd9Sstevel@tonic-gate 			flag |= ENABLE;
1437c478bd9Sstevel@tonic-gate 			break;
1447c478bd9Sstevel@tonic-gate 		case 'f':
1457c478bd9Sstevel@tonic-gate 			flag |= ADD;
1467c478bd9Sstevel@tonic-gate 			while (*optarg) {
1477c478bd9Sstevel@tonic-gate 				switch (*optarg++) {
1487c478bd9Sstevel@tonic-gate 				case 'u':
1497c478bd9Sstevel@tonic-gate 					flags |= U_FLAG;
1507c478bd9Sstevel@tonic-gate 					break;
1517c478bd9Sstevel@tonic-gate 				case 'x':
1527c478bd9Sstevel@tonic-gate 					flags |= X_FLAG;
1537c478bd9Sstevel@tonic-gate 					break;
1547c478bd9Sstevel@tonic-gate 				default:
1557c478bd9Sstevel@tonic-gate 					badargs[badcnt++] = *(optarg - 1);
1567c478bd9Sstevel@tonic-gate 					break;
1577c478bd9Sstevel@tonic-gate 				}
1587c478bd9Sstevel@tonic-gate 			}
1597c478bd9Sstevel@tonic-gate 			/* null terminate just in case anything is there */
1607c478bd9Sstevel@tonic-gate 			badargs[badcnt] = '\0';
1617c478bd9Sstevel@tonic-gate 			break;
1627c478bd9Sstevel@tonic-gate 		case 'g':
1637c478bd9Sstevel@tonic-gate 			flag |= CONFIG;
1647c478bd9Sstevel@tonic-gate 			break;
1657c478bd9Sstevel@tonic-gate 		case 'i':
1667c478bd9Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
1677c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
1687c478bd9Sstevel@tonic-gate 				error(BADINP);
1697c478bd9Sstevel@tonic-gate 			}
1707c478bd9Sstevel@tonic-gate 			flag |= ADD;
1717c478bd9Sstevel@tonic-gate 			id = optarg;
1727c478bd9Sstevel@tonic-gate 			break;
1737c478bd9Sstevel@tonic-gate 		case 'L':
1747c478bd9Sstevel@tonic-gate 			flag |= LIST;
1757c478bd9Sstevel@tonic-gate 			break;
1767c478bd9Sstevel@tonic-gate 		case 'l':
1777c478bd9Sstevel@tonic-gate 			flag |= PLIST;
1787c478bd9Sstevel@tonic-gate 			break;
1797c478bd9Sstevel@tonic-gate 		case 'm':
1807c478bd9Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
1817c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
1827c478bd9Sstevel@tonic-gate 				error(BADINP);
1837c478bd9Sstevel@tonic-gate 			}
1847c478bd9Sstevel@tonic-gate 			if (*optarg == '\0') {
1857c478bd9Sstevel@tonic-gate 				/* this will generate a usage message below */
1867c478bd9Sstevel@tonic-gate 				errflg++;
1877c478bd9Sstevel@tonic-gate 				break;
1887c478bd9Sstevel@tonic-gate 			}
1897c478bd9Sstevel@tonic-gate 			flag |= ADD;
1907c478bd9Sstevel@tonic-gate 			pmspec = optarg;
1917c478bd9Sstevel@tonic-gate 			break;
1927c478bd9Sstevel@tonic-gate 		case 'p':
1937c478bd9Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
1947c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
1957c478bd9Sstevel@tonic-gate 				error(BADINP);
1967c478bd9Sstevel@tonic-gate 			}
1977c478bd9Sstevel@tonic-gate 			pmtag = optarg;
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 			if (strchr(optarg, '\n')) {
2147c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
2157c478bd9Sstevel@tonic-gate 				error(BADINP);
2167c478bd9Sstevel@tonic-gate 			}
2177c478bd9Sstevel@tonic-gate 			svctag = optarg;
2187c478bd9Sstevel@tonic-gate 			if (strlen(svctag) > SVCTAGSIZE) {
2197c478bd9Sstevel@tonic-gate 				svctag[SVCTAGSIZE] = '\0';
2207c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "svctag too long, truncated to <%s>\n", svctag);
2217c478bd9Sstevel@tonic-gate 			}
2227c478bd9Sstevel@tonic-gate 			for (p = svctag; *p; p++) {
2237c478bd9Sstevel@tonic-gate 				if (!isalnum(*p)) {
2247c478bd9Sstevel@tonic-gate 					Saferrno = E_BADARGS;
2257c478bd9Sstevel@tonic-gate 					error("service tag must be alphanumeric");
2267c478bd9Sstevel@tonic-gate 				}
2277c478bd9Sstevel@tonic-gate 			}
2287c478bd9Sstevel@tonic-gate 			break;
2297c478bd9Sstevel@tonic-gate 		case 't':
2307c478bd9Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
2317c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
2327c478bd9Sstevel@tonic-gate 				error(BADINP);
2337c478bd9Sstevel@tonic-gate 			}
2347c478bd9Sstevel@tonic-gate 			type = optarg;
2357c478bd9Sstevel@tonic-gate 			if (strlen(type) > PMTYPESIZE) {
2367c478bd9Sstevel@tonic-gate 				type[PMTYPESIZE] = '\0';
2377c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "type too long, truncated to <%s>\n", type);
2387c478bd9Sstevel@tonic-gate 			}
2397c478bd9Sstevel@tonic-gate 			for (p = type; *p; p++) {
2407c478bd9Sstevel@tonic-gate 				if (!isalnum(*p)) {
2417c478bd9Sstevel@tonic-gate 					Saferrno = E_BADARGS;
2427c478bd9Sstevel@tonic-gate 					error("port monitor type must be alphanumeric");
2437c478bd9Sstevel@tonic-gate 				}
2447c478bd9Sstevel@tonic-gate 			}
2457c478bd9Sstevel@tonic-gate 			break;
2467c478bd9Sstevel@tonic-gate 		case 'v':
2477c478bd9Sstevel@tonic-gate 			flag |= ADD;
2487c478bd9Sstevel@tonic-gate 			version = atoi(optarg);
2497c478bd9Sstevel@tonic-gate 			if (version < 0) {
2507c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
2517c478bd9Sstevel@tonic-gate 				error("version number can not be negative");
2527c478bd9Sstevel@tonic-gate 			}
2537c478bd9Sstevel@tonic-gate 			break;
2547c478bd9Sstevel@tonic-gate 		case 'y':
2557c478bd9Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
2567c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
2577c478bd9Sstevel@tonic-gate 				error(BADINP);
2587c478bd9Sstevel@tonic-gate 			}
2597c478bd9Sstevel@tonic-gate 			flag |= ADD;
2607c478bd9Sstevel@tonic-gate 			comment = optarg;
2617c478bd9Sstevel@tonic-gate 			break;
2627c478bd9Sstevel@tonic-gate 		case 'z':
2637c478bd9Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
2647c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
2657c478bd9Sstevel@tonic-gate 				error(BADINP);
2667c478bd9Sstevel@tonic-gate 			}
2677c478bd9Sstevel@tonic-gate 			script = optarg;
2687c478bd9Sstevel@tonic-gate 			break;
2697c478bd9Sstevel@tonic-gate 		case '?':
2707c478bd9Sstevel@tonic-gate 			errflg++;
2717c478bd9Sstevel@tonic-gate 		}
2727c478bd9Sstevel@tonic-gate 	}
2737c478bd9Sstevel@tonic-gate 	if (errflg || (optind < argc))
2747c478bd9Sstevel@tonic-gate 		usage(argv[0]);
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	if (badcnt) {
2777c478bd9Sstevel@tonic-gate 		/* bad flags were given to -f */
2787c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s are not valid arguments for \"-f\"", badargs);
2797c478bd9Sstevel@tonic-gate 		Saferrno = E_BADARGS;
2807c478bd9Sstevel@tonic-gate 		error(buf);
2817c478bd9Sstevel@tonic-gate 	}
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	uid = getuid();
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate /*
2867c478bd9Sstevel@tonic-gate  * don't do anything if _sactab isn't the version we understand
2877c478bd9Sstevel@tonic-gate  */
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	if ((ret = check_version(VERSION, SACTAB)) == 1) {
2907c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
2917c478bd9Sstevel@tonic-gate 		error("_sactab version number is incorrect");
2927c478bd9Sstevel@tonic-gate 	}
2937c478bd9Sstevel@tonic-gate 	else if (ret == 2) {
2947c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "could not open %s", SACTAB);
2957c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
2967c478bd9Sstevel@tonic-gate 		error(buf);
2977c478bd9Sstevel@tonic-gate 	}
2987c478bd9Sstevel@tonic-gate 	else if (ret == 3) {
2997c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "%s file is corrupt", SACTAB);
3007c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
3017c478bd9Sstevel@tonic-gate 		error(buf);
3027c478bd9Sstevel@tonic-gate 	}
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	switch (flag) {
3057c478bd9Sstevel@tonic-gate 	case ADD:
3067c478bd9Sstevel@tonic-gate 		if (uid) {
3077c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3087c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
3097c478bd9Sstevel@tonic-gate 		}
3107c478bd9Sstevel@tonic-gate 		if (!sawaflag || (pmtag && type) || (!pmtag && !type) || !svctag || !id || !pmspec || (version < 0))
3117c478bd9Sstevel@tonic-gate 			usage(argv[0]);
3127c478bd9Sstevel@tonic-gate 		add_svc(pmtag, type, svctag, id, pmspec, flags, version, comment, script);
3137c478bd9Sstevel@tonic-gate 		break;
3147c478bd9Sstevel@tonic-gate 	case REMOVE:
3157c478bd9Sstevel@tonic-gate 		if (uid) {
3167c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3177c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
3187c478bd9Sstevel@tonic-gate 		}
3197c478bd9Sstevel@tonic-gate 		if (!pmtag || !svctag || type || script)
3207c478bd9Sstevel@tonic-gate 			usage(argv[0]);
3217c478bd9Sstevel@tonic-gate 		rem_svc(pmtag, svctag);
3227c478bd9Sstevel@tonic-gate 		break;
3237c478bd9Sstevel@tonic-gate 	case ENABLE:
3247c478bd9Sstevel@tonic-gate 		if (uid) {
3257c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3267c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
3277c478bd9Sstevel@tonic-gate 		}
3287c478bd9Sstevel@tonic-gate 		if (!pmtag || !svctag || type || script)
3297c478bd9Sstevel@tonic-gate 			usage(argv[0]);
3307c478bd9Sstevel@tonic-gate 		ed_svc(pmtag, svctag, ENABLE);
3317c478bd9Sstevel@tonic-gate 		break;
3327c478bd9Sstevel@tonic-gate 	case DISABLE:
3337c478bd9Sstevel@tonic-gate 		if (uid) {
3347c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3357c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
3367c478bd9Sstevel@tonic-gate 		}
3377c478bd9Sstevel@tonic-gate 		if (!pmtag || !svctag || type || script)
3387c478bd9Sstevel@tonic-gate 			usage(argv[0]);
3397c478bd9Sstevel@tonic-gate 		ed_svc(pmtag, svctag, DISABLE);
3407c478bd9Sstevel@tonic-gate 		break;
3417c478bd9Sstevel@tonic-gate 	case LIST:
3427c478bd9Sstevel@tonic-gate 		conflag = 1;
3437c478bd9Sstevel@tonic-gate 		/* fall through */
3447c478bd9Sstevel@tonic-gate 	case PLIST:
3457c478bd9Sstevel@tonic-gate 		if ((pmtag && type) || script)
3467c478bd9Sstevel@tonic-gate 			usage(argv[0]);
3477c478bd9Sstevel@tonic-gate 		list_svcs(pmtag, type, svctag, conflag);
3487c478bd9Sstevel@tonic-gate 		break;
3497c478bd9Sstevel@tonic-gate 	case CONFIG:
3507c478bd9Sstevel@tonic-gate 		if (script && uid) {
3517c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
3527c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
3537c478bd9Sstevel@tonic-gate 		}
3547c478bd9Sstevel@tonic-gate 		if ((pmtag && type) || (!pmtag && !type) || !svctag || (type && !script))
3557c478bd9Sstevel@tonic-gate 			usage(argv[0]);
3567c478bd9Sstevel@tonic-gate 		doconf(script, pmtag, type, svctag);
3577c478bd9Sstevel@tonic-gate 		break;
3587c478bd9Sstevel@tonic-gate 	default:
3597c478bd9Sstevel@tonic-gate 		/* we only get here if more than one flag bit was set */
3607c478bd9Sstevel@tonic-gate 		usage(argv[0]);
3617c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
3627c478bd9Sstevel@tonic-gate 	}
3637c478bd9Sstevel@tonic-gate 	quit();
3647c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
3657c478bd9Sstevel@tonic-gate }
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate /*
3697c478bd9Sstevel@tonic-gate  * usage - print out a usage message
3707c478bd9Sstevel@tonic-gate  *
3717c478bd9Sstevel@tonic-gate  *	args:	cmdname - the name command was invoked with
3727c478bd9Sstevel@tonic-gate  */
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate void
usage(cmdname)3757c478bd9Sstevel@tonic-gate usage(cmdname)
3767c478bd9Sstevel@tonic-gate char *cmdname;
3777c478bd9Sstevel@tonic-gate {
3787c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "Usage:\t%s -a [ -p pmtag | -t type ] -s svctag -i id -m \"pmspecific\"\n", cmdname);
3797c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t\t-v version [ -f xu ] [ -y comment ] [ -z script]\n");
3807c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -r -p pmtag -s svctag\n", cmdname);
3817c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -e -p pmtag -s svctag\n", cmdname);
3827c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -d -p pmtag -s svctag\n", cmdname);
3837c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -l [ -p pmtag | -t type ] [ -s svctag ]\n", cmdname);
3847c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -L [ -p pmtag | -t type ] [ -s svctag ]\n", cmdname);
3857c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -g -p pmtag -s svctag [ -z script ]\n", cmdname);
3867c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -g -s svctag -t type -z script\n", cmdname);
3877c478bd9Sstevel@tonic-gate 	Saferrno = E_BADARGS;
3887c478bd9Sstevel@tonic-gate 	quit();
3897c478bd9Sstevel@tonic-gate }
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate /*
3937c478bd9Sstevel@tonic-gate  * add_svc - add a service entry
3947c478bd9Sstevel@tonic-gate  *
3957c478bd9Sstevel@tonic-gate  *	args:	tag - port monitor's tag (may be null)
3967c478bd9Sstevel@tonic-gate  *		type - port monitor's type (may be null)
3977c478bd9Sstevel@tonic-gate  *		svctag - service's tag
3987c478bd9Sstevel@tonic-gate  *		id - identity under which service should run
3997c478bd9Sstevel@tonic-gate  *		pmspec - uninterpreted port monitor-specific info
4007c478bd9Sstevel@tonic-gate  *		flags - service flags
4017c478bd9Sstevel@tonic-gate  *		version - version number of port monitor's pmtab
4027c478bd9Sstevel@tonic-gate  *		comment - comment describing service
4037c478bd9Sstevel@tonic-gate  *		script - service's configuration script
4047c478bd9Sstevel@tonic-gate  */
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate void
add_svc(tag,type,svctag,id,pmspec,flags,version,comment,script)4077c478bd9Sstevel@tonic-gate add_svc(tag, type, svctag, id, pmspec, flags, version, comment, script)
4087c478bd9Sstevel@tonic-gate char *tag;
4097c478bd9Sstevel@tonic-gate char *type;
4107c478bd9Sstevel@tonic-gate char *svctag;
4117c478bd9Sstevel@tonic-gate char *id;
4127c478bd9Sstevel@tonic-gate char *pmspec;
4137c478bd9Sstevel@tonic-gate long flags;
4147c478bd9Sstevel@tonic-gate int version;
4157c478bd9Sstevel@tonic-gate char *comment;
4167c478bd9Sstevel@tonic-gate char *script;
4177c478bd9Sstevel@tonic-gate {
4187c478bd9Sstevel@tonic-gate 	FILE *fp;			/* scratch file pointer */
4197c478bd9Sstevel@tonic-gate 	struct taglist tl;		/* 'list' for degenerate case (1 PM) */
4207c478bd9Sstevel@tonic-gate 	register struct taglist *tp = NULL;	/* working pointer */
4217c478bd9Sstevel@tonic-gate 	int ret;			/* return code from check_version */
4227c478bd9Sstevel@tonic-gate 	char buf[SIZE];			/* scratch buffer */
4237c478bd9Sstevel@tonic-gate 	char fname[SIZE];		/* scratch buffer for building names */
4247c478bd9Sstevel@tonic-gate 	int added;			/* count number added */
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 	fp = fopen(SACTAB, "r");
4277c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
4287c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
4297c478bd9Sstevel@tonic-gate 		error("Could not open _sactab");
4307c478bd9Sstevel@tonic-gate 	}
4317c478bd9Sstevel@tonic-gate 	if (tag && !find_pm(fp, tag)) {
4327c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist", tag);
4337c478bd9Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
4347c478bd9Sstevel@tonic-gate 		error(buf);
4357c478bd9Sstevel@tonic-gate 	}
4367c478bd9Sstevel@tonic-gate 	if (type && !(tp = find_type(fp, type))) {
4377c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist", type);
4387c478bd9Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
4397c478bd9Sstevel@tonic-gate 		error(buf);
4407c478bd9Sstevel@tonic-gate 	}
4417c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	if (tag) {
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate /*
4467c478bd9Sstevel@tonic-gate  * treat the case of 1 PM as a degenerate case of a list of PMs from a
4477c478bd9Sstevel@tonic-gate  * type specification.  Build the 'list' here.
4487c478bd9Sstevel@tonic-gate  */
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate 		tp = &tl;
4517c478bd9Sstevel@tonic-gate 		tp->t_next = NULL;
4527c478bd9Sstevel@tonic-gate 		(void) strcpy(tp->t_tag, tag);
4537c478bd9Sstevel@tonic-gate 	}
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 	added = 0;
4567c478bd9Sstevel@tonic-gate 	while (tp) {
4577c478bd9Sstevel@tonic-gate 		(void) sprintf(fname, "%s/%s/_pmtab", HOME, tp->t_tag);
4587c478bd9Sstevel@tonic-gate 		if ((ret = check_version(version, fname)) == 1) {
4597c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "%s version number is incorrect", fname);
4607c478bd9Sstevel@tonic-gate 			Saferrno = E_SAFERR;
4617c478bd9Sstevel@tonic-gate 			error(buf);
4627c478bd9Sstevel@tonic-gate 		}
4637c478bd9Sstevel@tonic-gate 		else if (ret == 2) {
4647c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "could not open %s", fname);
4657c478bd9Sstevel@tonic-gate 			Saferrno = E_SYSERR;
4667c478bd9Sstevel@tonic-gate 			error(buf);
4677c478bd9Sstevel@tonic-gate 		}
4687c478bd9Sstevel@tonic-gate 		else if (ret == 3) {
4697c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "%s file is corrupt", fname);
4707c478bd9Sstevel@tonic-gate 			Saferrno = E_SAFERR;
4717c478bd9Sstevel@tonic-gate 			error(buf);
4727c478bd9Sstevel@tonic-gate 		}
4737c478bd9Sstevel@tonic-gate 		fp = fopen(fname, "r");
4747c478bd9Sstevel@tonic-gate 		if (fp == NULL) {
4757c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "Could not open %s", fname);
4767c478bd9Sstevel@tonic-gate 			Saferrno = E_SYSERR;
4777c478bd9Sstevel@tonic-gate 			error(buf);
4787c478bd9Sstevel@tonic-gate 		}
4797c478bd9Sstevel@tonic-gate 		if (find_svc(fp, tp->t_tag, svctag)) {
4807c478bd9Sstevel@tonic-gate 			if (tag) {
4817c478bd9Sstevel@tonic-gate 				/* special case of tag only */
4827c478bd9Sstevel@tonic-gate 				(void) sprintf(buf, "Invalid request, %s already exists under %s", svctag, tag);
4837c478bd9Sstevel@tonic-gate 				Saferrno = E_DUP;
4847c478bd9Sstevel@tonic-gate 				error(buf);
4857c478bd9Sstevel@tonic-gate 			}
4867c478bd9Sstevel@tonic-gate 			else {
4877c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "warning - %s already exists under %s - ignoring\n", svctag, tp->t_tag);
4887c478bd9Sstevel@tonic-gate 				tp = tp->t_next;
4897c478bd9Sstevel@tonic-gate 				(void) fclose(fp);
4907c478bd9Sstevel@tonic-gate 				continue;
4917c478bd9Sstevel@tonic-gate 			}
4927c478bd9Sstevel@tonic-gate 		}
4937c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate /*
4967c478bd9Sstevel@tonic-gate  * put in the config script, if specified
4977c478bd9Sstevel@tonic-gate */
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 		if (script) {
5007c478bd9Sstevel@tonic-gate 			(void) sprintf(fname, "%s/%s", tp->t_tag, svctag);
5017c478bd9Sstevel@tonic-gate 			if (do_config(script, fname)) {
5027c478bd9Sstevel@tonic-gate 				/* do_config put out any messages */
5037c478bd9Sstevel@tonic-gate 				tp = tp->t_next;
5047c478bd9Sstevel@tonic-gate 				continue;
5057c478bd9Sstevel@tonic-gate 			}
5067c478bd9Sstevel@tonic-gate 		}
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate /*
5097c478bd9Sstevel@tonic-gate  * add the line
5107c478bd9Sstevel@tonic-gate  */
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 		(void) sprintf(fname, "%s/%s/_pmtab", HOME, tp->t_tag);
5137c478bd9Sstevel@tonic-gate 		fp = fopen(fname, "a");
5147c478bd9Sstevel@tonic-gate 		if (fp == NULL) {
5157c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "Could not open %s", fname);
5167c478bd9Sstevel@tonic-gate 			Saferrno = E_SYSERR;
5177c478bd9Sstevel@tonic-gate 			error(buf);
5187c478bd9Sstevel@tonic-gate 		}
5197c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "%s:%s:%s:reserved:reserved:reserved:%s#%s\n",
5207c478bd9Sstevel@tonic-gate 			svctag, (flags ? pflags(flags, FALSE) : ""), id, pmspec,
5217c478bd9Sstevel@tonic-gate 			(comment ? comment : ""));
5227c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
5237c478bd9Sstevel@tonic-gate 		added++;
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate /*
5267c478bd9Sstevel@tonic-gate  * tell the SAC to to tell PM to read _pmtab
5277c478bd9Sstevel@tonic-gate  */
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 		(void) tell_sac(tp->t_tag);
5307c478bd9Sstevel@tonic-gate 		tp = tp->t_next;
5317c478bd9Sstevel@tonic-gate 	}
5327c478bd9Sstevel@tonic-gate 	if (added == 0) {
5337c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
5347c478bd9Sstevel@tonic-gate 		error("No services added");
5357c478bd9Sstevel@tonic-gate 	}
5367c478bd9Sstevel@tonic-gate 	return;
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate /*
5417c478bd9Sstevel@tonic-gate  * rem_svc - remove a service
5427c478bd9Sstevel@tonic-gate  *
5437c478bd9Sstevel@tonic-gate  *	args:	pmtag - tag of port monitor responsible for the service
5447c478bd9Sstevel@tonic-gate  *		svctag - tag of the service to be removed
5457c478bd9Sstevel@tonic-gate  */
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate void
rem_svc(pmtag,svctag)5487c478bd9Sstevel@tonic-gate rem_svc(pmtag, svctag)
5497c478bd9Sstevel@tonic-gate char *pmtag;
5507c478bd9Sstevel@tonic-gate char *svctag;
5517c478bd9Sstevel@tonic-gate {
5527c478bd9Sstevel@tonic-gate 	FILE *fp;		/* scratch file pointer */
5537c478bd9Sstevel@tonic-gate 	FILE *tfp;		/* file pointer for temp file */
5547c478bd9Sstevel@tonic-gate 	int line;		/* line number entry is on */
5557c478bd9Sstevel@tonic-gate 	char *tname;		/* temp file name */
5567c478bd9Sstevel@tonic-gate 	char buf[SIZE];		/* scratch buffer */
5577c478bd9Sstevel@tonic-gate 	char fname[SIZE];	/* path to correct _pmtab */
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 	fp = fopen(SACTAB, "r");
5607c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
5617c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
5627c478bd9Sstevel@tonic-gate 		error("Could not open _sactab");
5637c478bd9Sstevel@tonic-gate 	}
5647c478bd9Sstevel@tonic-gate 	if (!find_pm(fp, pmtag)) {
5657c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist", pmtag);
5667c478bd9Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
5677c478bd9Sstevel@tonic-gate 		error(buf);
5687c478bd9Sstevel@tonic-gate 	}
5697c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 	(void) sprintf(fname, "%s/_pmtab", pmtag);
5727c478bd9Sstevel@tonic-gate 	(void) sprintf(buf, "%s/%s", HOME, fname);
5737c478bd9Sstevel@tonic-gate 	fp = fopen(buf, "r");
5747c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
5757c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "Could not open %s/%s", HOME, fname);
5767c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
5777c478bd9Sstevel@tonic-gate 		error(buf);
5787c478bd9Sstevel@tonic-gate 	}
5797c478bd9Sstevel@tonic-gate 	if ((line = find_svc(fp, pmtag, svctag)) == 0) {
5807c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist under %s", svctag, pmtag);
5817c478bd9Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
5827c478bd9Sstevel@tonic-gate 		error(buf);
5837c478bd9Sstevel@tonic-gate 	}
5847c478bd9Sstevel@tonic-gate 	tname = make_tempname(fname);
5857c478bd9Sstevel@tonic-gate 	tfp = open_temp(tname);
5867c478bd9Sstevel@tonic-gate 	if (line != 1) {
5877c478bd9Sstevel@tonic-gate 		if (copy_file(fp, tfp, 1, line - 1)) {
5887c478bd9Sstevel@tonic-gate 			(void) unlink(tname);
5897c478bd9Sstevel@tonic-gate 			Saferrno = E_SYSERR;
5907c478bd9Sstevel@tonic-gate 			error("error accessing temp file");
5917c478bd9Sstevel@tonic-gate 		}
5927c478bd9Sstevel@tonic-gate 	}
5937c478bd9Sstevel@tonic-gate 	if (copy_file(fp, tfp, line + 1, -1)) {
5947c478bd9Sstevel@tonic-gate 		(void) unlink(tname);
5957c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
5967c478bd9Sstevel@tonic-gate 		error("error accessing temp file");
5977c478bd9Sstevel@tonic-gate 	}
5987c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
5997c478bd9Sstevel@tonic-gate 	if (fclose(tfp) == EOF) {
6007c478bd9Sstevel@tonic-gate 		(void) unlink(tname);
6017c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
6027c478bd9Sstevel@tonic-gate 		error("error closing tempfile");
6037c478bd9Sstevel@tonic-gate 	}
6047c478bd9Sstevel@tonic-gate 	/* note - replace only returns if successful */
6057c478bd9Sstevel@tonic-gate 	replace(fname, tname);
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate /*
6087c478bd9Sstevel@tonic-gate  * tell the SAC to to tell PM to read _pmtab
6097c478bd9Sstevel@tonic-gate  */
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 	if (tell_sac(pmtag)) {
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate /*
6147c478bd9Sstevel@tonic-gate  * if we got rid of the service, try to remove the config script too.
6157c478bd9Sstevel@tonic-gate  * Don't check return status since it may not have existed anyhow.
6167c478bd9Sstevel@tonic-gate  */
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "%s/%s/%s", HOME, pmtag, svctag);
6197c478bd9Sstevel@tonic-gate 		(void) unlink(buf);
6207c478bd9Sstevel@tonic-gate 		return;
6217c478bd9Sstevel@tonic-gate 	}
6227c478bd9Sstevel@tonic-gate }
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate /*
6277c478bd9Sstevel@tonic-gate  * ed_svc - enable or disable a particular service
6287c478bd9Sstevel@tonic-gate  *
6297c478bd9Sstevel@tonic-gate  *	args:	pmtag - tag of port monitor responsible for the service
6307c478bd9Sstevel@tonic-gate  *		svctag - tag of service to be enabled or disabled
6317c478bd9Sstevel@tonic-gate  *		flag - operation to perform (ENABLE or DISABLE)
6327c478bd9Sstevel@tonic-gate  */
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate void
ed_svc(pmtag,svctag,flag)6357c478bd9Sstevel@tonic-gate ed_svc(pmtag, svctag, flag)
6367c478bd9Sstevel@tonic-gate char *pmtag;
6377c478bd9Sstevel@tonic-gate char *svctag;
6387c478bd9Sstevel@tonic-gate int flag;
6397c478bd9Sstevel@tonic-gate {
6407c478bd9Sstevel@tonic-gate 	FILE *fp;		/* scratch file pointer */
6417c478bd9Sstevel@tonic-gate 	FILE *tfp;		/* file pointer for temp file */
6427c478bd9Sstevel@tonic-gate 	int line;		/* line number entry is on */
6437c478bd9Sstevel@tonic-gate 	register char *from;	/* working pointer */
6447c478bd9Sstevel@tonic-gate 	register char *to;	/* working pointer */
6457c478bd9Sstevel@tonic-gate 	char *tname;		/* temp file name */
6467c478bd9Sstevel@tonic-gate 	char *p;		/* scratch pointer */
6477c478bd9Sstevel@tonic-gate 	char buf[SIZE];		/* scratch buffer */
6487c478bd9Sstevel@tonic-gate 	char tbuf[SIZE];	/* scratch buffer */
6497c478bd9Sstevel@tonic-gate 	char fname[SIZE];	/* path to correct _pmtab */
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 	fp = fopen(SACTAB, "r");
6527c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
6537c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
6547c478bd9Sstevel@tonic-gate 		error("Could not open _sactab");
6557c478bd9Sstevel@tonic-gate 	}
6567c478bd9Sstevel@tonic-gate 	if (!find_pm(fp, pmtag)) {
6577c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist", pmtag);
6587c478bd9Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
6597c478bd9Sstevel@tonic-gate 		error(buf);
6607c478bd9Sstevel@tonic-gate 	}
6617c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	(void) sprintf(fname, "%s/_pmtab", pmtag);
6647c478bd9Sstevel@tonic-gate 	(void) sprintf(buf, "%s/%s", HOME, fname);
6657c478bd9Sstevel@tonic-gate 	fp = fopen(buf, "r");
6667c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
6677c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "Could not open %s/%s", HOME, fname);
6687c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
6697c478bd9Sstevel@tonic-gate 		error(buf);
6707c478bd9Sstevel@tonic-gate 	}
6717c478bd9Sstevel@tonic-gate 	if ((line = find_svc(fp, pmtag, svctag)) == 0) {
6727c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist under %s", svctag, pmtag);
6737c478bd9Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
6747c478bd9Sstevel@tonic-gate 		error(buf);
6757c478bd9Sstevel@tonic-gate 	}
6767c478bd9Sstevel@tonic-gate 	tname = make_tempname(fname);
6777c478bd9Sstevel@tonic-gate 	tfp = open_temp(tname);
6787c478bd9Sstevel@tonic-gate 	if (line != 1) {
6797c478bd9Sstevel@tonic-gate 		if (copy_file(fp, tfp, 1, line - 1)) {
6807c478bd9Sstevel@tonic-gate 			(void) unlink(tname);
6817c478bd9Sstevel@tonic-gate 			Saferrno = E_SYSERR;
6827c478bd9Sstevel@tonic-gate 			error("error accessing temp file");
6837c478bd9Sstevel@tonic-gate 		}
6847c478bd9Sstevel@tonic-gate 	}
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate /*
6877c478bd9Sstevel@tonic-gate  * Note: find_svc above has already read and parsed this entry, thus
6887c478bd9Sstevel@tonic-gate  * we know it to be well-formed, so just change the flags as appropriate
6897c478bd9Sstevel@tonic-gate  */
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate 	if (fgets(buf, SIZE, fp) == NULL) {
6927c478bd9Sstevel@tonic-gate 		(void) unlink(tname);
6937c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
6947c478bd9Sstevel@tonic-gate 		error("error accessing temp file");
6957c478bd9Sstevel@tonic-gate 	}
6967c478bd9Sstevel@tonic-gate 	from = buf;
6977c478bd9Sstevel@tonic-gate 	to = tbuf;
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate /*
7007c478bd9Sstevel@tonic-gate  * copy initial portion of entry
7017c478bd9Sstevel@tonic-gate  */
7027c478bd9Sstevel@tonic-gate 
7037c478bd9Sstevel@tonic-gate 	p = strchr(from, DELIMC);
7047c478bd9Sstevel@tonic-gate 	for ( ; from <= p; )
7057c478bd9Sstevel@tonic-gate 		*to++ = *from++;
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate /*
7087c478bd9Sstevel@tonic-gate  * isolate and fix the flags
7097c478bd9Sstevel@tonic-gate  */
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 	p = strchr(from, DELIMC);
7127c478bd9Sstevel@tonic-gate 	for ( ; from < p; ) {
7137c478bd9Sstevel@tonic-gate 		if (*from == 'x') {
7147c478bd9Sstevel@tonic-gate 			from++;
7157c478bd9Sstevel@tonic-gate 			continue;
7167c478bd9Sstevel@tonic-gate 		}
7177c478bd9Sstevel@tonic-gate 		*to++ = *from++;
7187c478bd9Sstevel@tonic-gate 	}
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate /*
7217c478bd9Sstevel@tonic-gate  * above we removed x flag, if this was a disable operation, stick it in
7227c478bd9Sstevel@tonic-gate  * and also copy the field delimiter
7237c478bd9Sstevel@tonic-gate  */
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 	if (flag == DISABLE)
7267c478bd9Sstevel@tonic-gate 		*to++ = 'x';
7277c478bd9Sstevel@tonic-gate 	*to++ = *from++;
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate /*
7307c478bd9Sstevel@tonic-gate  * copy the rest of the line
7317c478bd9Sstevel@tonic-gate  */
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate 	for ( ; from < &buf[SIZE - 1] ;)
7347c478bd9Sstevel@tonic-gate 		*to++ = *from++;
7357c478bd9Sstevel@tonic-gate /***	*to = '\0';  BUG: Don't uncomment it ****/
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate 	(void) fprintf(tfp, "%s", tbuf);
7387c478bd9Sstevel@tonic-gate 
7397c478bd9Sstevel@tonic-gate 	if (copy_file(fp, tfp, line + 1, -1)) {
7407c478bd9Sstevel@tonic-gate 		(void) unlink(tname);
7417c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
7427c478bd9Sstevel@tonic-gate 		error("error accessing temp file");
7437c478bd9Sstevel@tonic-gate 	}
7447c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
7457c478bd9Sstevel@tonic-gate 	if (fclose(tfp) == EOF) {
7467c478bd9Sstevel@tonic-gate 		(void) unlink(tname);
7477c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
7487c478bd9Sstevel@tonic-gate 		error("error closing tempfile");
7497c478bd9Sstevel@tonic-gate 	}
7507c478bd9Sstevel@tonic-gate 	/* note - replace only returns if successful */
7517c478bd9Sstevel@tonic-gate 	replace(fname, tname);
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate /*
7557c478bd9Sstevel@tonic-gate  * tell the SAC to to tell PM to read _pmtab
7567c478bd9Sstevel@tonic-gate  */
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate 	(void) tell_sac(pmtag);
7597c478bd9Sstevel@tonic-gate }
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate /*
7637c478bd9Sstevel@tonic-gate  * doconf - take a config script and have it put where it belongs or
7647c478bd9Sstevel@tonic-gate  *	    output an existing one
7657c478bd9Sstevel@tonic-gate  *
7667c478bd9Sstevel@tonic-gate  *	args:	script - name of file containing script (if NULL, means
7677c478bd9Sstevel@tonic-gate  *			 output existing one instead)
7687c478bd9Sstevel@tonic-gate  *		tag - tag of port monitor that is responsible for the
7697c478bd9Sstevel@tonic-gate  *		      designated service (may be null)
7707c478bd9Sstevel@tonic-gate  *		type - type of port monitor that is responsible for the
7717c478bd9Sstevel@tonic-gate  *		       designated service (may be null)
7727c478bd9Sstevel@tonic-gate  *		svctag - tag of service whose config script we're operating on
7737c478bd9Sstevel@tonic-gate  */
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate void
doconf(script,tag,type,svctag)7767c478bd9Sstevel@tonic-gate doconf(script, tag, type, svctag)
7777c478bd9Sstevel@tonic-gate char *script;
7787c478bd9Sstevel@tonic-gate char *tag;
7797c478bd9Sstevel@tonic-gate char *type;
7807c478bd9Sstevel@tonic-gate char *svctag;
7817c478bd9Sstevel@tonic-gate {
7827c478bd9Sstevel@tonic-gate 	FILE *fp;			/* scratch file pointer */
7837c478bd9Sstevel@tonic-gate 	int added;			/* count of config scripts added */
7847c478bd9Sstevel@tonic-gate 	struct taglist tl;		/* 'list' for degenerate case (1 PM) */
7857c478bd9Sstevel@tonic-gate 	register struct taglist *tp = NULL;	/* working pointer */
7867c478bd9Sstevel@tonic-gate 	char buf[SIZE];			/* scratch buffer */
7877c478bd9Sstevel@tonic-gate 	char fname[SIZE];		/* scratch buffer for names */
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate 	fp = fopen(SACTAB, "r");
7907c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
7917c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
7927c478bd9Sstevel@tonic-gate 		error("Could not open _sactab");
7937c478bd9Sstevel@tonic-gate 	}
7947c478bd9Sstevel@tonic-gate 	if (tag && !find_pm(fp, tag)) {
7957c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist", tag);
7967c478bd9Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
7977c478bd9Sstevel@tonic-gate 		error(buf);
7987c478bd9Sstevel@tonic-gate 	}
7997c478bd9Sstevel@tonic-gate 	if (type && !(tp = find_type(fp, type))) {
8007c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist", type);
8017c478bd9Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
8027c478bd9Sstevel@tonic-gate 		error(buf);
8037c478bd9Sstevel@tonic-gate 	}
8047c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate 	if (tag) {
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate /*
8097c478bd9Sstevel@tonic-gate  * treat the case of 1 PM as a degenerate case of a list of PMs from a
8107c478bd9Sstevel@tonic-gate  * type specification.  Build the 'list' here.
8117c478bd9Sstevel@tonic-gate  */
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 		tp = &tl;
8147c478bd9Sstevel@tonic-gate 		tp->t_next = NULL;
8157c478bd9Sstevel@tonic-gate 		(void) strcpy(tp->t_tag, tag);
8167c478bd9Sstevel@tonic-gate 	}
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 	added = 0;
8197c478bd9Sstevel@tonic-gate 	while (tp) {
8207c478bd9Sstevel@tonic-gate 		(void) sprintf(fname, "%s/%s/_pmtab", HOME, tp->t_tag);
8217c478bd9Sstevel@tonic-gate 		fp = fopen(fname, "r");
8227c478bd9Sstevel@tonic-gate 		if (fp == NULL) {
8237c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "Could not open %s", fname);
8247c478bd9Sstevel@tonic-gate 			Saferrno = E_SYSERR;
8257c478bd9Sstevel@tonic-gate 			error(buf);
8267c478bd9Sstevel@tonic-gate 		}
8277c478bd9Sstevel@tonic-gate 		if (!find_svc(fp, tp->t_tag, svctag)) {
8287c478bd9Sstevel@tonic-gate 			if (tag) {
8297c478bd9Sstevel@tonic-gate 				/* special case of tag only */
8307c478bd9Sstevel@tonic-gate 				(void) sprintf(buf, "Invalid request, %s does not exist under %s", svctag, tag);
8317c478bd9Sstevel@tonic-gate 				Saferrno = E_NOEXIST;
8327c478bd9Sstevel@tonic-gate 				error(buf);
8337c478bd9Sstevel@tonic-gate 			}
8347c478bd9Sstevel@tonic-gate 			else {
8357c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "warning - %s does not exist under %s - ignoring\n", svctag, tp->t_tag);
8367c478bd9Sstevel@tonic-gate 				Saferrno = E_NOEXIST;
8377c478bd9Sstevel@tonic-gate 				tp = tp->t_next;
8387c478bd9Sstevel@tonic-gate 				(void) fclose(fp);
8397c478bd9Sstevel@tonic-gate 				continue;
8407c478bd9Sstevel@tonic-gate 			}
8417c478bd9Sstevel@tonic-gate 		}
8427c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate 		(void) sprintf(fname, "%s/%s", tp->t_tag, svctag);
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate /*
8477c478bd9Sstevel@tonic-gate  * do_config does all the real work (keep track if any errors occurred)
8487c478bd9Sstevel@tonic-gate  */
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 		if (do_config(script, fname) == 0)
8517c478bd9Sstevel@tonic-gate 			added++;
8527c478bd9Sstevel@tonic-gate 		tp = tp->t_next;
8537c478bd9Sstevel@tonic-gate 	}
8547c478bd9Sstevel@tonic-gate 	if (added == 0) {
8557c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
8567c478bd9Sstevel@tonic-gate 		error("No configuration scripts installed");
8577c478bd9Sstevel@tonic-gate 	}
8587c478bd9Sstevel@tonic-gate 	return;
8597c478bd9Sstevel@tonic-gate }
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate /*
8637c478bd9Sstevel@tonic-gate  * tell_sac - use sacadm to tell the sac to tell a port monitor to read
8647c478bd9Sstevel@tonic-gate  *	its _pmtab.  Return TRUE on success, FALSE on failure.
8657c478bd9Sstevel@tonic-gate  *
8667c478bd9Sstevel@tonic-gate  *	args:	tag - tag of port monitor to be notified
8677c478bd9Sstevel@tonic-gate  */
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate 
87034e48580Sdp int
tell_sac(char * tag)87134e48580Sdp tell_sac(char *tag)
8727c478bd9Sstevel@tonic-gate {
8737c478bd9Sstevel@tonic-gate 	pid_t pid;	/* returned pid from fork */
8747c478bd9Sstevel@tonic-gate 	int status;	/* return status from sacadm child */
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate 	if ((pid = fork()) < 0) {
8777c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "warning - fork failed - could not notify <%s> about modified table\n", tag);
8787c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "try executing the command \"sacadm -x -p %s\"\n", tag);
8797c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
8807c478bd9Sstevel@tonic-gate 		return(FALSE);
8817c478bd9Sstevel@tonic-gate 	}
8827c478bd9Sstevel@tonic-gate 	else if (pid) {
8837c478bd9Sstevel@tonic-gate 		/* parent */
8847c478bd9Sstevel@tonic-gate 		(void) wait(&status);
8857c478bd9Sstevel@tonic-gate 		if (status) {
8867c478bd9Sstevel@tonic-gate 			if (((status >> 8) & 0xff) == E_PMNOTRUN) {
8877c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "warning - port monitor, %s is not running\n", tag);
8887c478bd9Sstevel@tonic-gate 				return (FALSE);
8897c478bd9Sstevel@tonic-gate 			}
8907c478bd9Sstevel@tonic-gate 			if (((status >> 8) & 0xff) == E_SACNOTRUN) {
8917c478bd9Sstevel@tonic-gate 				Saferrno = E_SACNOTRUN;
8927c478bd9Sstevel@tonic-gate 			} else {
8937c478bd9Sstevel@tonic-gate 				Saferrno = E_SYSERR;
8947c478bd9Sstevel@tonic-gate 			}
8957c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
8967c478bd9Sstevel@tonic-gate 			    "warning - could not notify <%s> about modified"
8977c478bd9Sstevel@tonic-gate 			    " table\n", tag);
8987c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "try executing the command"
8997c478bd9Sstevel@tonic-gate 			    " \"sacadm -x -p %s\"\n", tag);
9007c478bd9Sstevel@tonic-gate 			return(FALSE);
9017c478bd9Sstevel@tonic-gate 		}
9027c478bd9Sstevel@tonic-gate 		else {
9037c478bd9Sstevel@tonic-gate 			return(TRUE);
9047c478bd9Sstevel@tonic-gate 		}
9057c478bd9Sstevel@tonic-gate 	}
9067c478bd9Sstevel@tonic-gate 	else {
9077c478bd9Sstevel@tonic-gate 		/* set IFS for security */
9087c478bd9Sstevel@tonic-gate 		(void) putenv("IFS=\" \"");
9097c478bd9Sstevel@tonic-gate 		/* muffle sacadm warning messages */
9107c478bd9Sstevel@tonic-gate 		(void) fclose(stderr);
9117c478bd9Sstevel@tonic-gate 		(void) fopen("/dev/null", "w");
9127c478bd9Sstevel@tonic-gate 		(void) execl("/usr/sbin/sacadm", "sacadm", "-x", "-p", tag, 0);
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate /*
9157c478bd9Sstevel@tonic-gate  * if we got here, it didn't work, exit status will clue in parent to
9167c478bd9Sstevel@tonic-gate  * put out the warning
9177c478bd9Sstevel@tonic-gate  */
9187c478bd9Sstevel@tonic-gate 
9197c478bd9Sstevel@tonic-gate 		exit(1);
9207c478bd9Sstevel@tonic-gate 	}
9217c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
9227c478bd9Sstevel@tonic-gate }
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate /*
9267c478bd9Sstevel@tonic-gate  * list_svcs - list information about services
9277c478bd9Sstevel@tonic-gate  *
9287c478bd9Sstevel@tonic-gate  *	args:	pmtag - tag of port monitor responsible for the service
9297c478bd9Sstevel@tonic-gate  *			(may be null)
9307c478bd9Sstevel@tonic-gate  *		type - type of port monitor responsible for the service
9317c478bd9Sstevel@tonic-gate  *		       (may be null)
9327c478bd9Sstevel@tonic-gate  *		svctag - tag of service to be listed (may be null)
9337c478bd9Sstevel@tonic-gate  *		oflag - true if output should be easily parseable
9347c478bd9Sstevel@tonic-gate  */
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate void
list_svcs(char * pmtag,char * type,char * svctag,int oflag)937*c53bc758SToomas Soome list_svcs(char *pmtag, char *type, char *svctag, int oflag)
9387c478bd9Sstevel@tonic-gate {
9397c478bd9Sstevel@tonic-gate 	FILE *fp;				/* scratch file pointer */
9407c478bd9Sstevel@tonic-gate 	register struct taglist *tp;		/* pointer to PM list */
9417c478bd9Sstevel@tonic-gate 	int nprint = 0;				/* count # of svcs printed */
9427c478bd9Sstevel@tonic-gate 	struct pmtab pmtab;			/* place to hold parsed info */
9437c478bd9Sstevel@tonic-gate 	register struct pmtab *pp = &pmtab;	/* and a pointer to it */
9447c478bd9Sstevel@tonic-gate 	register char *p;			/* working pointer */
9457c478bd9Sstevel@tonic-gate 	char buf[SIZE];				/* scratch buffer */
9467c478bd9Sstevel@tonic-gate 	char fname[SIZE];			/* scratch buffer for building names */
9477c478bd9Sstevel@tonic-gate 
9487c478bd9Sstevel@tonic-gate 	fp = fopen(SACTAB, "r");
9497c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
9507c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
9517c478bd9Sstevel@tonic-gate 		error("Could not open _sactab");
9527c478bd9Sstevel@tonic-gate 	}
9537c478bd9Sstevel@tonic-gate 	if (pmtag && !find_pm(fp, pmtag)) {
9547c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist", pmtag);
9557c478bd9Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
9567c478bd9Sstevel@tonic-gate 		error(buf);
9577c478bd9Sstevel@tonic-gate 	}
9587c478bd9Sstevel@tonic-gate 	rewind(fp);
9597c478bd9Sstevel@tonic-gate 	if (type) {
9607c478bd9Sstevel@tonic-gate 		tp = find_type(fp, type);
9617c478bd9Sstevel@tonic-gate 		if (tp == NULL) {
9627c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "Invalid request, %s does not exist", type);
9637c478bd9Sstevel@tonic-gate 			Saferrno = E_NOEXIST;
9647c478bd9Sstevel@tonic-gate 			error(buf);
9657c478bd9Sstevel@tonic-gate 		}
9667c478bd9Sstevel@tonic-gate 	}
9677c478bd9Sstevel@tonic-gate 	else
9687c478bd9Sstevel@tonic-gate 		tp = find_type(fp, NULL);
9697c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
9707c478bd9Sstevel@tonic-gate 
9717c478bd9Sstevel@tonic-gate 	while (tp) {
9727c478bd9Sstevel@tonic-gate 		if (pmtag && strcmp(tp->t_tag, pmtag)) {
9737c478bd9Sstevel@tonic-gate 			/* not interested in this port monitor */
9747c478bd9Sstevel@tonic-gate 			tp = tp->t_next;
9757c478bd9Sstevel@tonic-gate 			continue;
9767c478bd9Sstevel@tonic-gate 		}
9777c478bd9Sstevel@tonic-gate 		(void) sprintf(fname, "%s/%s/_pmtab", HOME, tp->t_tag);
9787c478bd9Sstevel@tonic-gate 		fp = fopen(fname, "r");
9797c478bd9Sstevel@tonic-gate 		if (fp == NULL) {
9807c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "Could not open %s", fname);
9817c478bd9Sstevel@tonic-gate 			Saferrno = E_SYSERR;
9827c478bd9Sstevel@tonic-gate 			error(buf);
9837c478bd9Sstevel@tonic-gate 		}
9847c478bd9Sstevel@tonic-gate 		while (fgets(buf, SIZE, fp)) {
9857c478bd9Sstevel@tonic-gate 			p = trim(buf);
9867c478bd9Sstevel@tonic-gate 			if (*p == '\0')
9877c478bd9Sstevel@tonic-gate 				continue;
9887c478bd9Sstevel@tonic-gate 			parseline(p, pp, tp->t_tag);
9897c478bd9Sstevel@tonic-gate 			if (!svctag || !strcmp(pp->p_tag, svctag)) {
9907c478bd9Sstevel@tonic-gate 				if (oflag) {
9917c478bd9Sstevel@tonic-gate 					(void) printf("%s:%s:%s:%s:%s:%s:%s:%s:%s#%s\n",
9927c478bd9Sstevel@tonic-gate 						tp->t_tag, tp->t_type, pp->p_tag,
9937c478bd9Sstevel@tonic-gate 						pflags(pp->p_flags, FALSE),
9947c478bd9Sstevel@tonic-gate 						pp->p_id, pp->p_res1, pp->p_res2,
9957c478bd9Sstevel@tonic-gate 						pp->p_res3,pp->p_pmspec, Comment);
9967c478bd9Sstevel@tonic-gate 				}
9977c478bd9Sstevel@tonic-gate 				else {
9987c478bd9Sstevel@tonic-gate 					if (nprint == 0) {
9997c478bd9Sstevel@tonic-gate 						(void) printf("PMTAG          PMTYPE         SVCTAG         FLGS ID       <PMSPECIFIC>\n");
10007c478bd9Sstevel@tonic-gate 					}
10017c478bd9Sstevel@tonic-gate 					(void) printf("%-14s %-14s %-14s %-4s %-8s %s #%s\n", tp->t_tag, tp->t_type, pp->p_tag,
10027c478bd9Sstevel@tonic-gate 						pflags(pp->p_flags, TRUE), pp->p_id, pspec(pp->p_pmspec), Comment);
10037c478bd9Sstevel@tonic-gate 				}
10047c478bd9Sstevel@tonic-gate 				nprint++;
10057c478bd9Sstevel@tonic-gate 			}
10067c478bd9Sstevel@tonic-gate 		}
10077c478bd9Sstevel@tonic-gate 		if (!feof(fp)) {
10087c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "error reading %s", fname);
10097c478bd9Sstevel@tonic-gate 			Saferrno = E_SYSERR;
10107c478bd9Sstevel@tonic-gate 			error(buf);
10117c478bd9Sstevel@tonic-gate 		}
10127c478bd9Sstevel@tonic-gate 		else {
10137c478bd9Sstevel@tonic-gate 			(void) fclose(fp);
10147c478bd9Sstevel@tonic-gate 			tp = tp->t_next;
10157c478bd9Sstevel@tonic-gate 		}
10167c478bd9Sstevel@tonic-gate 	}
10177c478bd9Sstevel@tonic-gate 	/* if we didn't find any valid ones, indicate an error */
10187c478bd9Sstevel@tonic-gate 	if (nprint == 0) {
10197c478bd9Sstevel@tonic-gate 		if (svctag)
10207c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "Service <%s> does not exist\n", svctag);
10217c478bd9Sstevel@tonic-gate 		else
10227c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "No services defined\n");
10237c478bd9Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
10247c478bd9Sstevel@tonic-gate 	}
10257c478bd9Sstevel@tonic-gate 	return;
10267c478bd9Sstevel@tonic-gate }
10277c478bd9Sstevel@tonic-gate 
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate /*
10307c478bd9Sstevel@tonic-gate  * find_svc - find an entry in _pmtab for a particular service tag
10317c478bd9Sstevel@tonic-gate  *
10327c478bd9Sstevel@tonic-gate  *	args:	fp - file pointer for _pmtab
10337c478bd9Sstevel@tonic-gate  *		tag - port monitor tag (for error reporting)
10347c478bd9Sstevel@tonic-gate  *		svctag - tag of service we're looking for
10357c478bd9Sstevel@tonic-gate  */
10367c478bd9Sstevel@tonic-gate 
103734e48580Sdp int
find_svc(FILE * fp,char * tag,char * svctag)103834e48580Sdp find_svc(FILE *fp, char *tag, char *svctag)
10397c478bd9Sstevel@tonic-gate {
10407c478bd9Sstevel@tonic-gate 	register char *p;	/* working pointer */
10417c478bd9Sstevel@tonic-gate 	int line = 0;		/* line number we found entry on */
10427c478bd9Sstevel@tonic-gate 	struct pmtab pmtab;	/* place to hold parsed info */
10437c478bd9Sstevel@tonic-gate 	static char buf[SIZE];	/* scratch buffer */
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate 	while (fgets(buf, SIZE, fp)) {
10467c478bd9Sstevel@tonic-gate 		line++;
10477c478bd9Sstevel@tonic-gate 		p = trim(buf);
10487c478bd9Sstevel@tonic-gate 		if (*p == '\0')
10497c478bd9Sstevel@tonic-gate 			continue;
10507c478bd9Sstevel@tonic-gate 		parseline(p, &pmtab, tag);
10517c478bd9Sstevel@tonic-gate 		if (!(strcmp(pmtab.p_tag, svctag)))
10527c478bd9Sstevel@tonic-gate 			return(line);
10537c478bd9Sstevel@tonic-gate 	}
10547c478bd9Sstevel@tonic-gate 	if (!feof(fp)) {
10557c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "error reading %s/%s/_pmtab", HOME, tag);
10567c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
10577c478bd9Sstevel@tonic-gate 		error(buf);
105834e48580Sdp 		/* NOTREACHED */
105934e48580Sdp 		return (0);
106034e48580Sdp 	} else
106134e48580Sdp 		return (0);
10627c478bd9Sstevel@tonic-gate }
10637c478bd9Sstevel@tonic-gate 
10647c478bd9Sstevel@tonic-gate 
10657c478bd9Sstevel@tonic-gate /*
10667c478bd9Sstevel@tonic-gate  * parseline - parse a line from _pmtab.  This routine will return if the
10677c478bd9Sstevel@tonic-gate  *		parse wa successful, otherwise it will output an error and
10687c478bd9Sstevel@tonic-gate  *		exit.
10697c478bd9Sstevel@tonic-gate  *
10707c478bd9Sstevel@tonic-gate  *	args:	p - pointer to the data read from the file (note - this is
10717c478bd9Sstevel@tonic-gate  *		    a static data region, so we can point into it)
10727c478bd9Sstevel@tonic-gate  *		pp - pointer to a structure in which the separated fields
10737c478bd9Sstevel@tonic-gate  *		     are placed
10747c478bd9Sstevel@tonic-gate  *		tag - port monitor tag (for error reporting)
10757c478bd9Sstevel@tonic-gate  *
10767c478bd9Sstevel@tonic-gate  *	A line in the file has the following format:
10777c478bd9Sstevel@tonic-gate  *
10787c478bd9Sstevel@tonic-gate  *	tag:flags:identity:reserved:reserved:reserved:PM_spec_info # comment
10797c478bd9Sstevel@tonic-gate  */
10807c478bd9Sstevel@tonic-gate 
10817c478bd9Sstevel@tonic-gate 
10827c478bd9Sstevel@tonic-gate void
parseline(p,pp,tag)10837c478bd9Sstevel@tonic-gate parseline(p, pp, tag)
10847c478bd9Sstevel@tonic-gate register char *p;
10857c478bd9Sstevel@tonic-gate register struct pmtab *pp;
10867c478bd9Sstevel@tonic-gate char *tag;
10877c478bd9Sstevel@tonic-gate {
10887c478bd9Sstevel@tonic-gate 	char buf[SIZE];	/* scratch buffer */
10897c478bd9Sstevel@tonic-gate 
10907c478bd9Sstevel@tonic-gate /*
10917c478bd9Sstevel@tonic-gate  * get the service tag
10927c478bd9Sstevel@tonic-gate  */
10937c478bd9Sstevel@tonic-gate 
10947c478bd9Sstevel@tonic-gate 	p = nexttok(p, DELIM, FALSE);
10957c478bd9Sstevel@tonic-gate 	if (p == NULL) {
10967c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "%s/%s/_pmtab is corrupt", HOME, tag);
10977c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
10987c478bd9Sstevel@tonic-gate 		error(buf);
10997c478bd9Sstevel@tonic-gate 	}
11007c478bd9Sstevel@tonic-gate 	if (strlen(p) > PMTAGSIZE) {
11017c478bd9Sstevel@tonic-gate 		p[PMTAGSIZE] = '\0';
11027c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "tag too long, truncated to <%s>", p);
11037c478bd9Sstevel@tonic-gate 	}
11047c478bd9Sstevel@tonic-gate 	pp->p_tag = p;
11057c478bd9Sstevel@tonic-gate 
11067c478bd9Sstevel@tonic-gate /*
11077c478bd9Sstevel@tonic-gate  * get the flags
11087c478bd9Sstevel@tonic-gate  */
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate 	p = nexttok(NULL, DELIM, FALSE);
11117c478bd9Sstevel@tonic-gate 	if (p == NULL) {
11127c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "%s/%s/_pmtab is corrupt", HOME, tag);
11137c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11147c478bd9Sstevel@tonic-gate 		error(buf);
11157c478bd9Sstevel@tonic-gate 	}
11167c478bd9Sstevel@tonic-gate 	pp->p_flags = 0;
11177c478bd9Sstevel@tonic-gate 	while (*p) {
11187c478bd9Sstevel@tonic-gate 		switch (*p++) {
11197c478bd9Sstevel@tonic-gate 		case 'u':
11207c478bd9Sstevel@tonic-gate 			pp->p_flags |= U_FLAG;
11217c478bd9Sstevel@tonic-gate 			break;
11227c478bd9Sstevel@tonic-gate 		case 'x':
11237c478bd9Sstevel@tonic-gate 			pp->p_flags |= X_FLAG;
11247c478bd9Sstevel@tonic-gate 			break;
11257c478bd9Sstevel@tonic-gate 		default:
11267c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "Unrecognized flag <%c>", *(p - 1));
11277c478bd9Sstevel@tonic-gate 			Saferrno = E_SAFERR;
11287c478bd9Sstevel@tonic-gate 			error(buf);
11297c478bd9Sstevel@tonic-gate 			break;
11307c478bd9Sstevel@tonic-gate 		}
11317c478bd9Sstevel@tonic-gate 	}
11327c478bd9Sstevel@tonic-gate 
11337c478bd9Sstevel@tonic-gate /*
11347c478bd9Sstevel@tonic-gate  * get the identity
11357c478bd9Sstevel@tonic-gate  */
11367c478bd9Sstevel@tonic-gate 
11377c478bd9Sstevel@tonic-gate 	p = nexttok(NULL, DELIM, FALSE);
11387c478bd9Sstevel@tonic-gate 	if (p == NULL) {
11397c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "%s/%s/_pmtab is corrupt", HOME, tag);
11407c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11417c478bd9Sstevel@tonic-gate 		error(buf);
11427c478bd9Sstevel@tonic-gate 	}
11437c478bd9Sstevel@tonic-gate 	pp->p_id = p;
11447c478bd9Sstevel@tonic-gate 
11457c478bd9Sstevel@tonic-gate /*
11467c478bd9Sstevel@tonic-gate  * get the first reserved field
11477c478bd9Sstevel@tonic-gate  */
11487c478bd9Sstevel@tonic-gate 
11497c478bd9Sstevel@tonic-gate 	p = nexttok(NULL, DELIM, FALSE);
11507c478bd9Sstevel@tonic-gate 	if (p == NULL) {
11517c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "%s/%s/_pmtab is corrupt", HOME, tag);
11527c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11537c478bd9Sstevel@tonic-gate 		error(buf);
11547c478bd9Sstevel@tonic-gate 	}
11557c478bd9Sstevel@tonic-gate 	pp->p_res1 = p;
11567c478bd9Sstevel@tonic-gate 
11577c478bd9Sstevel@tonic-gate /*
11587c478bd9Sstevel@tonic-gate  * get the second reserved field
11597c478bd9Sstevel@tonic-gate  */
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate 	p = nexttok(NULL, DELIM, FALSE);
11627c478bd9Sstevel@tonic-gate 	if (p == NULL) {
11637c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "%s/%s/_pmtab is corrupt", HOME, tag);
11647c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11657c478bd9Sstevel@tonic-gate 		error(buf);
11667c478bd9Sstevel@tonic-gate 	}
11677c478bd9Sstevel@tonic-gate 	pp->p_res2 = p;
11687c478bd9Sstevel@tonic-gate 
11697c478bd9Sstevel@tonic-gate /*
11707c478bd9Sstevel@tonic-gate  * get the third reserved field
11717c478bd9Sstevel@tonic-gate  */
11727c478bd9Sstevel@tonic-gate 
11737c478bd9Sstevel@tonic-gate 	p = nexttok(NULL, DELIM, FALSE);
11747c478bd9Sstevel@tonic-gate 	if (p == NULL) {
11757c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "%s/%s/_pmtab is corrupt", HOME, tag);
11767c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11777c478bd9Sstevel@tonic-gate 		error(buf);
11787c478bd9Sstevel@tonic-gate 	}
11797c478bd9Sstevel@tonic-gate 	pp->p_res3 = p;
11807c478bd9Sstevel@tonic-gate 
11817c478bd9Sstevel@tonic-gate /*
11827c478bd9Sstevel@tonic-gate  * the rest is the port monitor specific info
11837c478bd9Sstevel@tonic-gate  */
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate 	p = nexttok(NULL, DELIM, TRUE);
11867c478bd9Sstevel@tonic-gate 	if (p == NULL) {
11877c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "%s/%s/_pmtab is corrupt", HOME, tag);
11887c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
11897c478bd9Sstevel@tonic-gate 		error(buf);
11907c478bd9Sstevel@tonic-gate 	}
11917c478bd9Sstevel@tonic-gate 	pp->p_pmspec = p;
11927c478bd9Sstevel@tonic-gate 	return;
11937c478bd9Sstevel@tonic-gate }
11947c478bd9Sstevel@tonic-gate 
11957c478bd9Sstevel@tonic-gate 
11967c478bd9Sstevel@tonic-gate /*
11977c478bd9Sstevel@tonic-gate  * pspec - format port monitor specific information
11987c478bd9Sstevel@tonic-gate  *
11997c478bd9Sstevel@tonic-gate  *	args:	spec - port monitor specific info, separated by
12007c478bd9Sstevel@tonic-gate  *		       field separater character (may be escaped by \)
12017c478bd9Sstevel@tonic-gate  */
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate char *
pspec(spec)12047c478bd9Sstevel@tonic-gate pspec(spec)
12057c478bd9Sstevel@tonic-gate char *spec;
12067c478bd9Sstevel@tonic-gate {
12077c478bd9Sstevel@tonic-gate 	static char buf[SIZE];		/* returned string */
12087c478bd9Sstevel@tonic-gate 	register char *from;		/* working pointer */
12097c478bd9Sstevel@tonic-gate 	register char *to;		/* working pointer */
12107c478bd9Sstevel@tonic-gate 	int newflag;			/* flag indicating new field */
12117c478bd9Sstevel@tonic-gate 
12127c478bd9Sstevel@tonic-gate 	to = buf;
12137c478bd9Sstevel@tonic-gate 	from = spec;
12147c478bd9Sstevel@tonic-gate 	newflag = 1;
12157c478bd9Sstevel@tonic-gate 	while (*from) {
12167c478bd9Sstevel@tonic-gate 		switch (*from) {
12177c478bd9Sstevel@tonic-gate 		case ':':
12187c478bd9Sstevel@tonic-gate 			if (newflag) {
12197c478bd9Sstevel@tonic-gate 				*to++ = '-';
12207c478bd9Sstevel@tonic-gate 			}
12217c478bd9Sstevel@tonic-gate 			*to++ = ' ';
12227c478bd9Sstevel@tonic-gate 			from++;
12237c478bd9Sstevel@tonic-gate 			newflag = 1;
12247c478bd9Sstevel@tonic-gate 			break;
12257c478bd9Sstevel@tonic-gate 		case '\\':
12267c478bd9Sstevel@tonic-gate 			if (*(from + 1) == ':') {
12277c478bd9Sstevel@tonic-gate 				*to++ = ':';
12287c478bd9Sstevel@tonic-gate 				/* skip over \: */
12297c478bd9Sstevel@tonic-gate 				from += 2;
12307c478bd9Sstevel@tonic-gate 			}
12317c478bd9Sstevel@tonic-gate 			else
12327c478bd9Sstevel@tonic-gate 				*to++ = *from++;
12337c478bd9Sstevel@tonic-gate 			newflag = 0;
12347c478bd9Sstevel@tonic-gate 			break;
12357c478bd9Sstevel@tonic-gate 		default:
12367c478bd9Sstevel@tonic-gate 			newflag = 0;
12377c478bd9Sstevel@tonic-gate 			*to++ = *from++;
12387c478bd9Sstevel@tonic-gate 		}
12397c478bd9Sstevel@tonic-gate 	}
12407c478bd9Sstevel@tonic-gate 	*to = '\0';
12417c478bd9Sstevel@tonic-gate 	return(buf);
12427c478bd9Sstevel@tonic-gate }
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate 
12457c478bd9Sstevel@tonic-gate /*
12467c478bd9Sstevel@tonic-gate  * pflags - put service flags into intelligible form for output
12477c478bd9Sstevel@tonic-gate  *
12487c478bd9Sstevel@tonic-gate  *	args:	flags - binary representation of flags
12497c478bd9Sstevel@tonic-gate  *		dflag - true if a "-" should be returned if no flags
12507c478bd9Sstevel@tonic-gate  */
12517c478bd9Sstevel@tonic-gate 
12527c478bd9Sstevel@tonic-gate char *
pflags(flags,dflag)12537c478bd9Sstevel@tonic-gate pflags(flags, dflag)
12547c478bd9Sstevel@tonic-gate long flags;
12557c478bd9Sstevel@tonic-gate int dflag;
12567c478bd9Sstevel@tonic-gate {
12577c478bd9Sstevel@tonic-gate 	register int i;			/* scratch counter */
12587c478bd9Sstevel@tonic-gate 	static char buf[SIZE];		/* formatted flags */
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate 	if (flags == 0) {
12617c478bd9Sstevel@tonic-gate 		if (dflag)
12627c478bd9Sstevel@tonic-gate 			return("-");
12637c478bd9Sstevel@tonic-gate 		else
12647c478bd9Sstevel@tonic-gate 			return("");
12657c478bd9Sstevel@tonic-gate 	}
12667c478bd9Sstevel@tonic-gate 	i = 0;
12677c478bd9Sstevel@tonic-gate 	if (flags & U_FLAG) {
12687c478bd9Sstevel@tonic-gate 		buf[i++] = 'u';
12697c478bd9Sstevel@tonic-gate 		flags &= ~U_FLAG;
12707c478bd9Sstevel@tonic-gate 	}
12717c478bd9Sstevel@tonic-gate 	if (flags & X_FLAG) {
12727c478bd9Sstevel@tonic-gate 		buf[i++] = 'x';
12737c478bd9Sstevel@tonic-gate 		flags &= ~X_FLAG;
12747c478bd9Sstevel@tonic-gate 	}
12757c478bd9Sstevel@tonic-gate 	if (flags) {
12767c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
12777c478bd9Sstevel@tonic-gate 		error("Internal error in pflags");
12787c478bd9Sstevel@tonic-gate 	}
12797c478bd9Sstevel@tonic-gate 	buf[i] = '\0';
12807c478bd9Sstevel@tonic-gate 	return(buf);
12817c478bd9Sstevel@tonic-gate }
12827c478bd9Sstevel@tonic-gate 
12837c478bd9Sstevel@tonic-gate 
12847c478bd9Sstevel@tonic-gate /*
12857c478bd9Sstevel@tonic-gate  * find_type - find entries in _sactab for a particular port monitor type
12867c478bd9Sstevel@tonic-gate  *
12877c478bd9Sstevel@tonic-gate  *	args:	fp - file pointer for _sactab
12887c478bd9Sstevel@tonic-gate  *		type - type of port monitor we're looking for (if type is
12897c478bd9Sstevel@tonic-gate  *		       null, it means find all PMs)
12907c478bd9Sstevel@tonic-gate  */
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate struct taglist *
find_type(fp,type)12937c478bd9Sstevel@tonic-gate find_type(fp, type)
12947c478bd9Sstevel@tonic-gate FILE *fp;
12957c478bd9Sstevel@tonic-gate char *type;
12967c478bd9Sstevel@tonic-gate {
12977c478bd9Sstevel@tonic-gate 	register char *p;			/* working pointer */
12987c478bd9Sstevel@tonic-gate 	struct sactab stab;			/* place to hold parsed info */
12997c478bd9Sstevel@tonic-gate 	register struct sactab *sp = &stab;	/* and a pointer to it */
13007c478bd9Sstevel@tonic-gate 	char buf[SIZE];				/* scratch buffer */
13017c478bd9Sstevel@tonic-gate 	struct taglist *thead;			/* linked list of tags */
13027c478bd9Sstevel@tonic-gate 	register struct taglist *temp;		/* scratch pointer */
13037c478bd9Sstevel@tonic-gate 
13047c478bd9Sstevel@tonic-gate 	thead = NULL;
13057c478bd9Sstevel@tonic-gate 	while (fgets(buf, SIZE, fp)) {
13067c478bd9Sstevel@tonic-gate 		p = trim(buf);
13077c478bd9Sstevel@tonic-gate 		if (*p == '\0')
13087c478bd9Sstevel@tonic-gate 			continue;
13097c478bd9Sstevel@tonic-gate 		parse(p, sp);
13107c478bd9Sstevel@tonic-gate 		if ((type == NULL) || !(strcmp(sp->sc_type, type))) {
13117c478bd9Sstevel@tonic-gate 			temp = (struct taglist *) malloc(sizeof(struct taglist));
13127c478bd9Sstevel@tonic-gate 			if (temp == NULL) {
13137c478bd9Sstevel@tonic-gate 				Saferrno = E_SYSERR;
13147c478bd9Sstevel@tonic-gate 				error("malloc failed");
13157c478bd9Sstevel@tonic-gate 			}
13167c478bd9Sstevel@tonic-gate 			temp->t_next = thead;
13177c478bd9Sstevel@tonic-gate 			(void) strcpy(temp->t_tag, sp->sc_tag);
13187c478bd9Sstevel@tonic-gate 			(void) strcpy(temp->t_type, sp->sc_type);
13197c478bd9Sstevel@tonic-gate 			thead = temp;
13207c478bd9Sstevel@tonic-gate 		}
13217c478bd9Sstevel@tonic-gate 	}
13227c478bd9Sstevel@tonic-gate 	if (!feof(fp)) {
13237c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
13247c478bd9Sstevel@tonic-gate 		error("error reading _sactab");
132534e48580Sdp 		/* NOTREACHED */
132634e48580Sdp 		return (0);
132734e48580Sdp 	} else
132834e48580Sdp 		return (thead ? thead : NULL);
13297c478bd9Sstevel@tonic-gate }
1330