xref: /titanic_50/usr/src/cmd/saf/sacadm.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1999 by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  * All rights reserved.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"       /* SVr4.0 1.15*/
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate # include <stdio.h>
35*7c478bd9Sstevel@tonic-gate # include <fcntl.h>
36*7c478bd9Sstevel@tonic-gate # include <errno.h>
37*7c478bd9Sstevel@tonic-gate # include <sys/types.h>
38*7c478bd9Sstevel@tonic-gate # include <sys/stat.h>
39*7c478bd9Sstevel@tonic-gate # include <signal.h>
40*7c478bd9Sstevel@tonic-gate # include <unistd.h>
41*7c478bd9Sstevel@tonic-gate # include <sac.h>
42*7c478bd9Sstevel@tonic-gate # include "misc.h"
43*7c478bd9Sstevel@tonic-gate # include "structs.h"
44*7c478bd9Sstevel@tonic-gate # include "adm.h"
45*7c478bd9Sstevel@tonic-gate # include "extern.h"
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate /*
49*7c478bd9Sstevel@tonic-gate  * functions
50*7c478bd9Sstevel@tonic-gate  */
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate char	*pflags();
53*7c478bd9Sstevel@tonic-gate char	*getfield();
54*7c478bd9Sstevel@tonic-gate void	add_pm();
55*7c478bd9Sstevel@tonic-gate void	cleandirs();
56*7c478bd9Sstevel@tonic-gate void	rem_pm();
57*7c478bd9Sstevel@tonic-gate void	start_pm();
58*7c478bd9Sstevel@tonic-gate void	kill_pm();
59*7c478bd9Sstevel@tonic-gate void	enable_pm();
60*7c478bd9Sstevel@tonic-gate void	disable_pm();
61*7c478bd9Sstevel@tonic-gate void	list_pms();
62*7c478bd9Sstevel@tonic-gate void	read_db();
63*7c478bd9Sstevel@tonic-gate void	sendcmd();
64*7c478bd9Sstevel@tonic-gate void	checkresp();
65*7c478bd9Sstevel@tonic-gate void	single_print();
66*7c478bd9Sstevel@tonic-gate void	catch();
67*7c478bd9Sstevel@tonic-gate void	usage();
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate # define START		0x1	/* -s seen */
70*7c478bd9Sstevel@tonic-gate # define KILL		0x2	/* -k seen */
71*7c478bd9Sstevel@tonic-gate # define ENABLE		0x4	/* -e seen */
72*7c478bd9Sstevel@tonic-gate # define DISABLE	0x8	/* -d seen */
73*7c478bd9Sstevel@tonic-gate # define PLIST		0x10	/* -l seen */
74*7c478bd9Sstevel@tonic-gate # define LIST		0x20	/* -L seen */
75*7c478bd9Sstevel@tonic-gate # define DBREAD		0x40	/* -x seen */
76*7c478bd9Sstevel@tonic-gate # define CONFIG		0x80	/* -G seen */
77*7c478bd9Sstevel@tonic-gate # define PCONFIG	0x100	/* -g seen */
78*7c478bd9Sstevel@tonic-gate # define ADD		0x200	/* -a or other required options seen */
79*7c478bd9Sstevel@tonic-gate # define REMOVE		0x400	/* -r seen */
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate /*
82*7c478bd9Sstevel@tonic-gate  * common error messages
83*7c478bd9Sstevel@tonic-gate  */
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate # define NOTPRIV	"User not privileged for operation"
86*7c478bd9Sstevel@tonic-gate # define SACERR		"Can not contact SAC"
87*7c478bd9Sstevel@tonic-gate # define BADINP		"Embedded newlines not allowed"
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate int	Saferrno;	/* internal `errno' for exit */
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate /*
94*7c478bd9Sstevel@tonic-gate  * main - scan args for sacadm and call appropriate handling code
95*7c478bd9Sstevel@tonic-gate  */
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate main(argc, argv)
98*7c478bd9Sstevel@tonic-gate int argc;
99*7c478bd9Sstevel@tonic-gate char *argv[];
100*7c478bd9Sstevel@tonic-gate {
101*7c478bd9Sstevel@tonic-gate 	int c;			/* option letter */
102*7c478bd9Sstevel@tonic-gate 	uid_t uid;		/* invoker's real uid */
103*7c478bd9Sstevel@tonic-gate 	int ret;		/* return code from check_version */
104*7c478bd9Sstevel@tonic-gate 	int flag = 0;		/* flag to record requested operations */
105*7c478bd9Sstevel@tonic-gate 	int errflg = 0;		/* error indicator */
106*7c478bd9Sstevel@tonic-gate 	int version = -1;	/* argument to -v */
107*7c478bd9Sstevel@tonic-gate 	int count = 0;		/* argument to -n */
108*7c478bd9Sstevel@tonic-gate 	int badcnt = 0;		/* count of bad args to -f */
109*7c478bd9Sstevel@tonic-gate 	int sawaflag = 0;	/* true if actually saw -a */
110*7c478bd9Sstevel@tonic-gate 	int conflag = 0;	/* true if output should be in condensed form */
111*7c478bd9Sstevel@tonic-gate 	long flags = 0;		/* arguments to -f */
112*7c478bd9Sstevel@tonic-gate 	FILE *fp;		/* scratch file pointer */
113*7c478bd9Sstevel@tonic-gate 	char *pmtag = NULL;	/* argument to -p */
114*7c478bd9Sstevel@tonic-gate 	char *type = NULL;	/* argument to -t */
115*7c478bd9Sstevel@tonic-gate 	char *script = NULL;	/* argument to -z */
116*7c478bd9Sstevel@tonic-gate 	char *command = NULL;	/* argument to -c */
117*7c478bd9Sstevel@tonic-gate 	char *comment = " ";	/* argument to -y */
118*7c478bd9Sstevel@tonic-gate 	char badargs[BADFARGSIZE];	/* place to hold bad args to -f */
119*7c478bd9Sstevel@tonic-gate 	char buf[SIZE];		/* scratch buffer */
120*7c478bd9Sstevel@tonic-gate 	register char *p;	/* scratch pointer */
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate 	if (argc == 1)
123*7c478bd9Sstevel@tonic-gate 		usage(argv[0]);
124*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "ac:def:GgkLln:p:rst:v:xy:z:")) != -1) {
125*7c478bd9Sstevel@tonic-gate 		switch (c) {
126*7c478bd9Sstevel@tonic-gate 		case 'a':
127*7c478bd9Sstevel@tonic-gate 			flag |= ADD;
128*7c478bd9Sstevel@tonic-gate 			sawaflag = 1;
129*7c478bd9Sstevel@tonic-gate 			break;
130*7c478bd9Sstevel@tonic-gate 		case 'c':
131*7c478bd9Sstevel@tonic-gate 			flag |= ADD;
132*7c478bd9Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
133*7c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
134*7c478bd9Sstevel@tonic-gate 				error(BADINP);
135*7c478bd9Sstevel@tonic-gate 			}
136*7c478bd9Sstevel@tonic-gate 			command = optarg;
137*7c478bd9Sstevel@tonic-gate 			if (*command != '/') {
138*7c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
139*7c478bd9Sstevel@tonic-gate 				error("command must be a full pathname");
140*7c478bd9Sstevel@tonic-gate 			}
141*7c478bd9Sstevel@tonic-gate 			break;
142*7c478bd9Sstevel@tonic-gate 		case 'd':
143*7c478bd9Sstevel@tonic-gate 			flag |= DISABLE;
144*7c478bd9Sstevel@tonic-gate 			break;
145*7c478bd9Sstevel@tonic-gate 		case 'e':
146*7c478bd9Sstevel@tonic-gate 			flag |= ENABLE;
147*7c478bd9Sstevel@tonic-gate 			break;
148*7c478bd9Sstevel@tonic-gate 		case 'f':
149*7c478bd9Sstevel@tonic-gate 			flag |= ADD;
150*7c478bd9Sstevel@tonic-gate 			while (*optarg) {
151*7c478bd9Sstevel@tonic-gate 				switch (*optarg++) {
152*7c478bd9Sstevel@tonic-gate 				case 'd':
153*7c478bd9Sstevel@tonic-gate 					flags |= D_FLAG;
154*7c478bd9Sstevel@tonic-gate 					break;
155*7c478bd9Sstevel@tonic-gate 				case 'x':
156*7c478bd9Sstevel@tonic-gate 					flags |= X_FLAG;
157*7c478bd9Sstevel@tonic-gate 					break;
158*7c478bd9Sstevel@tonic-gate 				default:
159*7c478bd9Sstevel@tonic-gate 					if (badcnt < (BADFARGSIZE -1))
160*7c478bd9Sstevel@tonic-gate 					    badargs[badcnt++] = *(optarg - 1);
161*7c478bd9Sstevel@tonic-gate 					break;
162*7c478bd9Sstevel@tonic-gate 				}
163*7c478bd9Sstevel@tonic-gate 			}
164*7c478bd9Sstevel@tonic-gate 			/* null terminate just in case anything is there */
165*7c478bd9Sstevel@tonic-gate 			badargs[badcnt] = '\0';
166*7c478bd9Sstevel@tonic-gate 			break;
167*7c478bd9Sstevel@tonic-gate 		case 'G':
168*7c478bd9Sstevel@tonic-gate 			flag |= CONFIG;
169*7c478bd9Sstevel@tonic-gate 			break;
170*7c478bd9Sstevel@tonic-gate 		case 'g':
171*7c478bd9Sstevel@tonic-gate 			flag |= PCONFIG;
172*7c478bd9Sstevel@tonic-gate 			break;
173*7c478bd9Sstevel@tonic-gate 		case 'k':
174*7c478bd9Sstevel@tonic-gate 			flag |= KILL;
175*7c478bd9Sstevel@tonic-gate 			break;
176*7c478bd9Sstevel@tonic-gate 		case 'L':
177*7c478bd9Sstevel@tonic-gate 			flag |= LIST;
178*7c478bd9Sstevel@tonic-gate 			break;
179*7c478bd9Sstevel@tonic-gate 		case 'l':
180*7c478bd9Sstevel@tonic-gate 			flag |= PLIST;
181*7c478bd9Sstevel@tonic-gate 			break;
182*7c478bd9Sstevel@tonic-gate 		case 'n':
183*7c478bd9Sstevel@tonic-gate 			flag |= ADD;
184*7c478bd9Sstevel@tonic-gate 			count = atoi(optarg);
185*7c478bd9Sstevel@tonic-gate 			if (count < 0) {
186*7c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
187*7c478bd9Sstevel@tonic-gate 				error("restart count can not be negative");
188*7c478bd9Sstevel@tonic-gate 			}
189*7c478bd9Sstevel@tonic-gate 			break;
190*7c478bd9Sstevel@tonic-gate 		case 'p':
191*7c478bd9Sstevel@tonic-gate 			pmtag = optarg;
192*7c478bd9Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
193*7c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
194*7c478bd9Sstevel@tonic-gate 				error(BADINP);
195*7c478bd9Sstevel@tonic-gate 			}
196*7c478bd9Sstevel@tonic-gate 			if (strlen(pmtag) > PMTAGSIZE) {
197*7c478bd9Sstevel@tonic-gate 				pmtag[PMTAGSIZE] = '\0';
198*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "tag too long, truncated to <%s>\n", pmtag);
199*7c478bd9Sstevel@tonic-gate 			}
200*7c478bd9Sstevel@tonic-gate 			for (p = pmtag; *p; p++) {
201*7c478bd9Sstevel@tonic-gate 				if (!isalnum(*p)) {
202*7c478bd9Sstevel@tonic-gate 					Saferrno = E_BADARGS;
203*7c478bd9Sstevel@tonic-gate 					error("port monitor tag must be alphanumeric");
204*7c478bd9Sstevel@tonic-gate 				}
205*7c478bd9Sstevel@tonic-gate 			}
206*7c478bd9Sstevel@tonic-gate 			break;
207*7c478bd9Sstevel@tonic-gate 		case 'r':
208*7c478bd9Sstevel@tonic-gate 			flag |= REMOVE;
209*7c478bd9Sstevel@tonic-gate 			break;
210*7c478bd9Sstevel@tonic-gate 		case 's':
211*7c478bd9Sstevel@tonic-gate 			flag |= START;
212*7c478bd9Sstevel@tonic-gate 			break;
213*7c478bd9Sstevel@tonic-gate 		case 't':
214*7c478bd9Sstevel@tonic-gate 			type = optarg;
215*7c478bd9Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
216*7c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
217*7c478bd9Sstevel@tonic-gate 				error(BADINP);
218*7c478bd9Sstevel@tonic-gate 			}
219*7c478bd9Sstevel@tonic-gate 			if (strlen(type) > PMTYPESIZE) {
220*7c478bd9Sstevel@tonic-gate 				type[PMTYPESIZE] = '\0';
221*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "type too long, truncated to <%s>\n", type);
222*7c478bd9Sstevel@tonic-gate 			}
223*7c478bd9Sstevel@tonic-gate 			for (p = type; *p; p++) {
224*7c478bd9Sstevel@tonic-gate 				if (!isalnum(*p)) {
225*7c478bd9Sstevel@tonic-gate 					Saferrno = E_BADARGS;
226*7c478bd9Sstevel@tonic-gate 					error("port monitor type must be alphanumeric");
227*7c478bd9Sstevel@tonic-gate 				}
228*7c478bd9Sstevel@tonic-gate 			}
229*7c478bd9Sstevel@tonic-gate 			break;
230*7c478bd9Sstevel@tonic-gate 		case 'v':
231*7c478bd9Sstevel@tonic-gate 			flag |= ADD;
232*7c478bd9Sstevel@tonic-gate 			version = atoi(optarg);
233*7c478bd9Sstevel@tonic-gate 			if (version < 0) {
234*7c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
235*7c478bd9Sstevel@tonic-gate 				error("version number can not be negative");
236*7c478bd9Sstevel@tonic-gate 			}
237*7c478bd9Sstevel@tonic-gate 			break;
238*7c478bd9Sstevel@tonic-gate 		case 'x':
239*7c478bd9Sstevel@tonic-gate 			flag |= DBREAD;
240*7c478bd9Sstevel@tonic-gate 			break;
241*7c478bd9Sstevel@tonic-gate 		case 'y':
242*7c478bd9Sstevel@tonic-gate 			flag |= ADD;
243*7c478bd9Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
244*7c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
245*7c478bd9Sstevel@tonic-gate 				error(BADINP);
246*7c478bd9Sstevel@tonic-gate 			}
247*7c478bd9Sstevel@tonic-gate 			comment = optarg;
248*7c478bd9Sstevel@tonic-gate 			break;
249*7c478bd9Sstevel@tonic-gate 		case 'z':
250*7c478bd9Sstevel@tonic-gate 			if (strchr(optarg, '\n')) {
251*7c478bd9Sstevel@tonic-gate 				Saferrno = E_BADARGS;
252*7c478bd9Sstevel@tonic-gate 				error(BADINP);
253*7c478bd9Sstevel@tonic-gate 			}
254*7c478bd9Sstevel@tonic-gate 			script = optarg;
255*7c478bd9Sstevel@tonic-gate 			break;
256*7c478bd9Sstevel@tonic-gate 		case '?':
257*7c478bd9Sstevel@tonic-gate 			errflg++;
258*7c478bd9Sstevel@tonic-gate 		}
259*7c478bd9Sstevel@tonic-gate 	}
260*7c478bd9Sstevel@tonic-gate 	if (errflg || (optind < argc))
261*7c478bd9Sstevel@tonic-gate 		usage(argv[0]);
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 	if (badcnt) {
264*7c478bd9Sstevel@tonic-gate 		/* bad flags were given to -f */
265*7c478bd9Sstevel@tonic-gate 		Saferrno = E_BADARGS;
266*7c478bd9Sstevel@tonic-gate 		(void) sprintf(buf,
267*7c478bd9Sstevel@tonic-gate 		    "Invalid request, %s are not valid arguments for \"-f\"",
268*7c478bd9Sstevel@tonic-gate 			badargs);
269*7c478bd9Sstevel@tonic-gate 		error(buf);
270*7c478bd9Sstevel@tonic-gate 	}
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	if ((ret = check_version(VERSION, SACTAB)) == 1) {
273*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
274*7c478bd9Sstevel@tonic-gate 		error("_sactab version number is incorrect");
275*7c478bd9Sstevel@tonic-gate 	}
276*7c478bd9Sstevel@tonic-gate 	else if (ret == 2) {
277*7c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "could not open %s", SACTAB);
278*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
279*7c478bd9Sstevel@tonic-gate 		error(buf);
280*7c478bd9Sstevel@tonic-gate 	}
281*7c478bd9Sstevel@tonic-gate 	else if (ret == 3) {
282*7c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "%s file is corrupt", SACTAB);
283*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
284*7c478bd9Sstevel@tonic-gate 		error(buf);
285*7c478bd9Sstevel@tonic-gate 	}
286*7c478bd9Sstevel@tonic-gate 	uid = getuid();
287*7c478bd9Sstevel@tonic-gate 	switch (flag) {
288*7c478bd9Sstevel@tonic-gate 	case ADD:
289*7c478bd9Sstevel@tonic-gate 		if (uid) {
290*7c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
291*7c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
292*7c478bd9Sstevel@tonic-gate 		}
293*7c478bd9Sstevel@tonic-gate 		if (!sawaflag || !pmtag || !type || !command || (version < 0))
294*7c478bd9Sstevel@tonic-gate 			usage(argv[0]);
295*7c478bd9Sstevel@tonic-gate 		add_pm(pmtag, type, command, version, flags, count, script, comment);
296*7c478bd9Sstevel@tonic-gate 		break;
297*7c478bd9Sstevel@tonic-gate 	case REMOVE:
298*7c478bd9Sstevel@tonic-gate 		if (uid) {
299*7c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
300*7c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
301*7c478bd9Sstevel@tonic-gate 		}
302*7c478bd9Sstevel@tonic-gate 		if (!pmtag || type || script)
303*7c478bd9Sstevel@tonic-gate 			usage(argv[0]);
304*7c478bd9Sstevel@tonic-gate 		rem_pm(pmtag);
305*7c478bd9Sstevel@tonic-gate 		break;
306*7c478bd9Sstevel@tonic-gate 	case START:
307*7c478bd9Sstevel@tonic-gate 		if (uid) {
308*7c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
309*7c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
310*7c478bd9Sstevel@tonic-gate 		}
311*7c478bd9Sstevel@tonic-gate 		if (!pmtag || type || script)
312*7c478bd9Sstevel@tonic-gate 			usage(argv[0]);
313*7c478bd9Sstevel@tonic-gate 		start_pm(pmtag);
314*7c478bd9Sstevel@tonic-gate 		break;
315*7c478bd9Sstevel@tonic-gate 	case KILL:
316*7c478bd9Sstevel@tonic-gate 		if (uid) {
317*7c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
318*7c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
319*7c478bd9Sstevel@tonic-gate 		}
320*7c478bd9Sstevel@tonic-gate 		if (!pmtag || type || script)
321*7c478bd9Sstevel@tonic-gate 			usage(argv[0]);
322*7c478bd9Sstevel@tonic-gate 		kill_pm(pmtag);
323*7c478bd9Sstevel@tonic-gate 		break;
324*7c478bd9Sstevel@tonic-gate 	case ENABLE:
325*7c478bd9Sstevel@tonic-gate 		if (uid) {
326*7c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
327*7c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
328*7c478bd9Sstevel@tonic-gate 		}
329*7c478bd9Sstevel@tonic-gate 		if (!pmtag || type || script)
330*7c478bd9Sstevel@tonic-gate 			usage(argv[0]);
331*7c478bd9Sstevel@tonic-gate 		enable_pm(pmtag);
332*7c478bd9Sstevel@tonic-gate 		break;
333*7c478bd9Sstevel@tonic-gate 	case DISABLE:
334*7c478bd9Sstevel@tonic-gate 		if (uid) {
335*7c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
336*7c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
337*7c478bd9Sstevel@tonic-gate 		}
338*7c478bd9Sstevel@tonic-gate 		if (!pmtag || type || script)
339*7c478bd9Sstevel@tonic-gate 			usage(argv[0]);
340*7c478bd9Sstevel@tonic-gate 		disable_pm(pmtag);
341*7c478bd9Sstevel@tonic-gate 		break;
342*7c478bd9Sstevel@tonic-gate 	case LIST:
343*7c478bd9Sstevel@tonic-gate 		conflag = 1;
344*7c478bd9Sstevel@tonic-gate 		/* fall through */
345*7c478bd9Sstevel@tonic-gate 	case PLIST:
346*7c478bd9Sstevel@tonic-gate 		if ((pmtag && type) || script)
347*7c478bd9Sstevel@tonic-gate 			usage(argv[0]);
348*7c478bd9Sstevel@tonic-gate 		list_pms(pmtag, type, conflag);
349*7c478bd9Sstevel@tonic-gate 		break;
350*7c478bd9Sstevel@tonic-gate 	case DBREAD:
351*7c478bd9Sstevel@tonic-gate 		if (uid) {
352*7c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
353*7c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
354*7c478bd9Sstevel@tonic-gate 		}
355*7c478bd9Sstevel@tonic-gate 		if (type || script)
356*7c478bd9Sstevel@tonic-gate 			usage(argv[0]);
357*7c478bd9Sstevel@tonic-gate 		read_db(pmtag);
358*7c478bd9Sstevel@tonic-gate 		break;
359*7c478bd9Sstevel@tonic-gate 	case CONFIG:
360*7c478bd9Sstevel@tonic-gate 		if (script && uid) {
361*7c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
362*7c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
363*7c478bd9Sstevel@tonic-gate 		}
364*7c478bd9Sstevel@tonic-gate 		if (type || pmtag)
365*7c478bd9Sstevel@tonic-gate 			usage(argv[0]);
366*7c478bd9Sstevel@tonic-gate 		(void) do_config(script, "_sysconfig");
367*7c478bd9Sstevel@tonic-gate 		break;
368*7c478bd9Sstevel@tonic-gate 	case PCONFIG:
369*7c478bd9Sstevel@tonic-gate 		if (script && uid) {
370*7c478bd9Sstevel@tonic-gate 			Saferrno = E_NOPRIV;
371*7c478bd9Sstevel@tonic-gate 			error(NOTPRIV);
372*7c478bd9Sstevel@tonic-gate 		}
373*7c478bd9Sstevel@tonic-gate 		if (!pmtag || type)
374*7c478bd9Sstevel@tonic-gate 			usage(argv[0]);
375*7c478bd9Sstevel@tonic-gate 		fp = fopen(SACTAB, "r");
376*7c478bd9Sstevel@tonic-gate 		if (fp == NULL) {
377*7c478bd9Sstevel@tonic-gate 			Saferrno = E_SYSERR;
378*7c478bd9Sstevel@tonic-gate 			error("Could not open _sactab");
379*7c478bd9Sstevel@tonic-gate 		}
380*7c478bd9Sstevel@tonic-gate 		if (!find_pm(fp, pmtag)) {
381*7c478bd9Sstevel@tonic-gate 			Saferrno = E_NOEXIST;
382*7c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "Invalid request, %s does not exist", pmtag);
383*7c478bd9Sstevel@tonic-gate 			error(buf);
384*7c478bd9Sstevel@tonic-gate 		}
385*7c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
386*7c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "%s/_config", pmtag);
387*7c478bd9Sstevel@tonic-gate 		(void) do_config(script, buf);
388*7c478bd9Sstevel@tonic-gate 		break;
389*7c478bd9Sstevel@tonic-gate 	default:
390*7c478bd9Sstevel@tonic-gate 		/* we only get here if more than one flag bit was set */
391*7c478bd9Sstevel@tonic-gate 		usage(argv[0]);
392*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
393*7c478bd9Sstevel@tonic-gate 	}
394*7c478bd9Sstevel@tonic-gate 	quit();
395*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
396*7c478bd9Sstevel@tonic-gate }
397*7c478bd9Sstevel@tonic-gate 
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate /*
400*7c478bd9Sstevel@tonic-gate  * usage - print out a usage message
401*7c478bd9Sstevel@tonic-gate  *
402*7c478bd9Sstevel@tonic-gate  *	args:	cmdname - the name command was invoked with
403*7c478bd9Sstevel@tonic-gate  */
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate void
406*7c478bd9Sstevel@tonic-gate usage(cmdname)
407*7c478bd9Sstevel@tonic-gate char *cmdname;
408*7c478bd9Sstevel@tonic-gate {
409*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "Usage:\t%s -a -p pmtag -t type -c cmd -v ver [ -f dx ] [ -n count ]\n", cmdname);
410*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t\t[ -y comment ] [ -z script]\n");
411*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -r -p pmtag\n", cmdname);
412*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -s -p pmtag\n", cmdname);
413*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -k -p pmtag\n", cmdname);
414*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -e -p pmtag\n", cmdname);
415*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -d -p pmtag\n", cmdname);
416*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -l [ -p pmtag | -t type ]\n", cmdname);
417*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -L [ -p pmtag | -t type ]\n", cmdname);
418*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -g -p pmtag [ -z script ]\n", cmdname);
419*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -G [ -z script ]\n", cmdname);
420*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\t%s -x [ -p pmtag ]\n", cmdname);
421*7c478bd9Sstevel@tonic-gate 	Saferrno = E_BADARGS;
422*7c478bd9Sstevel@tonic-gate 	quit();
423*7c478bd9Sstevel@tonic-gate }
424*7c478bd9Sstevel@tonic-gate 
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate /*
427*7c478bd9Sstevel@tonic-gate  * add_pm - add a port monitor entry
428*7c478bd9Sstevel@tonic-gate  *
429*7c478bd9Sstevel@tonic-gate  *	args:	tag - port monitor's tag
430*7c478bd9Sstevel@tonic-gate  *		type - port monitor's type
431*7c478bd9Sstevel@tonic-gate  *		command - command string to invoke port monitor
432*7c478bd9Sstevel@tonic-gate  *		version - version number of port monitor's pmtab
433*7c478bd9Sstevel@tonic-gate  *		flags - port monitor flags
434*7c478bd9Sstevel@tonic-gate  *		count - restart count
435*7c478bd9Sstevel@tonic-gate  *		script - port monitor's configuration script
436*7c478bd9Sstevel@tonic-gate  *		comment - comment describing port monitor
437*7c478bd9Sstevel@tonic-gate  */
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate void
440*7c478bd9Sstevel@tonic-gate add_pm(tag, type, command, version, flags, count, script, comment)
441*7c478bd9Sstevel@tonic-gate char *tag;
442*7c478bd9Sstevel@tonic-gate char *type;
443*7c478bd9Sstevel@tonic-gate char *command;
444*7c478bd9Sstevel@tonic-gate int version;
445*7c478bd9Sstevel@tonic-gate long flags;
446*7c478bd9Sstevel@tonic-gate int count;
447*7c478bd9Sstevel@tonic-gate char *script;
448*7c478bd9Sstevel@tonic-gate char *comment;
449*7c478bd9Sstevel@tonic-gate {
450*7c478bd9Sstevel@tonic-gate 	FILE *fp;		/* file pointer for _sactab */
451*7c478bd9Sstevel@tonic-gate 	int fd;			/* scratch file descriptor */
452*7c478bd9Sstevel@tonic-gate 	struct stat statbuf;	/* file status info */
453*7c478bd9Sstevel@tonic-gate 	char buf[SIZE];		/* scratch buffer */
454*7c478bd9Sstevel@tonic-gate 	char fname[SIZE];	/* scratch buffer for building names */
455*7c478bd9Sstevel@tonic-gate 	register int i;		/* scratch variable */
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 	fp = fopen(SACTAB, "r");
458*7c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
459*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
460*7c478bd9Sstevel@tonic-gate 		error("Could not open _sactab");
461*7c478bd9Sstevel@tonic-gate 	}
462*7c478bd9Sstevel@tonic-gate 	if (find_pm(fp, tag)) {
463*7c478bd9Sstevel@tonic-gate 		Saferrno = E_DUP;
464*7c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s already exists", tag);
465*7c478bd9Sstevel@tonic-gate 		error(buf);
466*7c478bd9Sstevel@tonic-gate 	}
467*7c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate /*
470*7c478bd9Sstevel@tonic-gate  * create the directories for it if needed and put in initial files
471*7c478bd9Sstevel@tonic-gate  * (/etc/saf and /var/saf)
472*7c478bd9Sstevel@tonic-gate  */
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < 2; i++) {
475*7c478bd9Sstevel@tonic-gate 		/* i == 0 do /etc/saf i == 1 do /var/saf */
476*7c478bd9Sstevel@tonic-gate 		(void) sprintf(fname, "%s/%s", (i == 0 ) ? HOME : ALTHOME, tag);
477*7c478bd9Sstevel@tonic-gate 		if (access(fname, 0) == 0) {
478*7c478bd9Sstevel@tonic-gate 			/* something is there, find out what it is */
479*7c478bd9Sstevel@tonic-gate 			if (stat(fname, &statbuf) < 0) {
480*7c478bd9Sstevel@tonic-gate 				Saferrno = E_SYSERR;
481*7c478bd9Sstevel@tonic-gate 				(void) sprintf(buf, "could not stat <%s>", fname);
482*7c478bd9Sstevel@tonic-gate 				error(buf);
483*7c478bd9Sstevel@tonic-gate 			}
484*7c478bd9Sstevel@tonic-gate 			if ((statbuf.st_mode & S_IFMT) != S_IFDIR) {
485*7c478bd9Sstevel@tonic-gate 				Saferrno = E_SYSERR;
486*7c478bd9Sstevel@tonic-gate 				(void) sprintf(buf, "<%s> exists and is not a directory", fname);
487*7c478bd9Sstevel@tonic-gate 				error(buf);
488*7c478bd9Sstevel@tonic-gate 			}
489*7c478bd9Sstevel@tonic-gate 			/* note: this removes the directory too */
490*7c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "rm -rf %s", fname);
491*7c478bd9Sstevel@tonic-gate 			if (system(buf) < 0) {
492*7c478bd9Sstevel@tonic-gate 				Saferrno = E_SYSERR;
493*7c478bd9Sstevel@tonic-gate 				(void) sprintf(buf, "could not remove files under <%s>", fname);
494*7c478bd9Sstevel@tonic-gate 				error(buf);
495*7c478bd9Sstevel@tonic-gate 			}
496*7c478bd9Sstevel@tonic-gate 		}
497*7c478bd9Sstevel@tonic-gate 
498*7c478bd9Sstevel@tonic-gate /*
499*7c478bd9Sstevel@tonic-gate  * create the directory
500*7c478bd9Sstevel@tonic-gate  */
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate 		if (mkdir(fname, 0755) < 0) {
503*7c478bd9Sstevel@tonic-gate 			Saferrno = E_SYSERR;
504*7c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "could not create directory <%s>", fname);
505*7c478bd9Sstevel@tonic-gate 			cleandirs(tag);
506*7c478bd9Sstevel@tonic-gate 			error(buf);
507*7c478bd9Sstevel@tonic-gate 		}
508*7c478bd9Sstevel@tonic-gate 	}
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate /*
511*7c478bd9Sstevel@tonic-gate  * put in the config script, if specified
512*7c478bd9Sstevel@tonic-gate  */
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate 	if (script) {
515*7c478bd9Sstevel@tonic-gate 		(void) sprintf(fname, "%s/_config", tag);
516*7c478bd9Sstevel@tonic-gate 		if (do_config(script, fname)) {
517*7c478bd9Sstevel@tonic-gate 			cleandirs(tag);
518*7c478bd9Sstevel@tonic-gate 			/* do_config put out any messages */
519*7c478bd9Sstevel@tonic-gate 			quit();
520*7c478bd9Sstevel@tonic-gate 		}
521*7c478bd9Sstevel@tonic-gate 	}
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate /*
524*7c478bd9Sstevel@tonic-gate  * create the communications pipe, but first make sure that the
525*7c478bd9Sstevel@tonic-gate  * permissions we specify are what we get
526*7c478bd9Sstevel@tonic-gate  */
527*7c478bd9Sstevel@tonic-gate 
528*7c478bd9Sstevel@tonic-gate 	(void) umask(0);
529*7c478bd9Sstevel@tonic-gate 	(void) sprintf(fname, "%s/%s/_pmpipe", HOME, tag);
530*7c478bd9Sstevel@tonic-gate 	if (mknod(fname, S_IFIFO | 0600, 0) < 0) {
531*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
532*7c478bd9Sstevel@tonic-gate 		cleandirs(tag);
533*7c478bd9Sstevel@tonic-gate 		error("could not create communications pipe");
534*7c478bd9Sstevel@tonic-gate 	}
535*7c478bd9Sstevel@tonic-gate 
536*7c478bd9Sstevel@tonic-gate /*
537*7c478bd9Sstevel@tonic-gate  * create the _pid file
538*7c478bd9Sstevel@tonic-gate  */
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate 	(void) sprintf(fname, "%s/%s/_pid", HOME, tag);
541*7c478bd9Sstevel@tonic-gate 	if ((fd = creat(fname, 0644)) < 0) {
542*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
543*7c478bd9Sstevel@tonic-gate 		cleandirs(tag);
544*7c478bd9Sstevel@tonic-gate 		error("could not create _pid file");
545*7c478bd9Sstevel@tonic-gate 	}
546*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
547*7c478bd9Sstevel@tonic-gate 
548*7c478bd9Sstevel@tonic-gate /*
549*7c478bd9Sstevel@tonic-gate  * create the _pmtab file
550*7c478bd9Sstevel@tonic-gate  */
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate 	(void) sprintf(fname, "%s/%s/_pmtab", HOME, tag);
553*7c478bd9Sstevel@tonic-gate 	if ((fd = creat(fname, 0644)) < 0) {
554*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
555*7c478bd9Sstevel@tonic-gate 		cleandirs(tag);
556*7c478bd9Sstevel@tonic-gate 		error("could not create _pmtab file");
557*7c478bd9Sstevel@tonic-gate 	}
558*7c478bd9Sstevel@tonic-gate 	(void) sprintf(buf, "%s%d\n", VSTR, version);
559*7c478bd9Sstevel@tonic-gate 	if (write(fd, buf, (unsigned) strlen(buf)) != strlen(buf)) {
560*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
561*7c478bd9Sstevel@tonic-gate 		(void) unlink(fname);
562*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
563*7c478bd9Sstevel@tonic-gate 		cleandirs(tag);
564*7c478bd9Sstevel@tonic-gate 		error("error initializing _pmtab");
565*7c478bd9Sstevel@tonic-gate 	}
566*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
567*7c478bd9Sstevel@tonic-gate 
568*7c478bd9Sstevel@tonic-gate /*
569*7c478bd9Sstevel@tonic-gate  * isolate the command name, but remember it since strtok() trashes it
570*7c478bd9Sstevel@tonic-gate  */
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate 	(void) strcpy(buf, command);
573*7c478bd9Sstevel@tonic-gate 	(void) strtok(command, " \t");
574*7c478bd9Sstevel@tonic-gate 
575*7c478bd9Sstevel@tonic-gate /*
576*7c478bd9Sstevel@tonic-gate  * check out the command - let addition succeed if it doesn't exist (assume
577*7c478bd9Sstevel@tonic-gate  * it will be added later); fail anything else
578*7c478bd9Sstevel@tonic-gate  */
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate 	if (access(command, 0) == 0) {
581*7c478bd9Sstevel@tonic-gate 		if (stat(command, &statbuf) < 0) {
582*7c478bd9Sstevel@tonic-gate 			Saferrno = E_SYSERR;
583*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "Could not stat <%s>\n", command);
584*7c478bd9Sstevel@tonic-gate 			cleandirs(tag);
585*7c478bd9Sstevel@tonic-gate 			quit();
586*7c478bd9Sstevel@tonic-gate 		}
587*7c478bd9Sstevel@tonic-gate 		if (!(statbuf.st_mode & 0111)) {
588*7c478bd9Sstevel@tonic-gate 			Saferrno = E_BADARGS;
589*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s not executable\n", command);
590*7c478bd9Sstevel@tonic-gate 			cleandirs(tag);
591*7c478bd9Sstevel@tonic-gate 			quit();
592*7c478bd9Sstevel@tonic-gate 		}
593*7c478bd9Sstevel@tonic-gate 		if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
594*7c478bd9Sstevel@tonic-gate 			Saferrno = E_BADARGS;
595*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s not a regular file\n", command);
596*7c478bd9Sstevel@tonic-gate 			cleandirs(tag);
597*7c478bd9Sstevel@tonic-gate 			quit();
598*7c478bd9Sstevel@tonic-gate 		}
599*7c478bd9Sstevel@tonic-gate 	}
600*7c478bd9Sstevel@tonic-gate 	else {
601*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "warning - %s does not exist\n", command);
602*7c478bd9Sstevel@tonic-gate 	}
603*7c478bd9Sstevel@tonic-gate 
604*7c478bd9Sstevel@tonic-gate /*
605*7c478bd9Sstevel@tonic-gate  * add the line
606*7c478bd9Sstevel@tonic-gate  */
607*7c478bd9Sstevel@tonic-gate 
608*7c478bd9Sstevel@tonic-gate 	fp = fopen(SACTAB, "a");
609*7c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
610*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
611*7c478bd9Sstevel@tonic-gate 		cleandirs(tag);
612*7c478bd9Sstevel@tonic-gate 		error("Could not open _sactab");
613*7c478bd9Sstevel@tonic-gate 	}
614*7c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "%s:%s:%s:%d:%s\t#%s\n", tag, type,
615*7c478bd9Sstevel@tonic-gate 		(flags ? pflags(flags, FALSE) : ""), count, buf,
616*7c478bd9Sstevel@tonic-gate 		(comment ? comment : ""));
617*7c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
618*7c478bd9Sstevel@tonic-gate 
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate /*
621*7c478bd9Sstevel@tonic-gate  * tell the SAC to read _sactab if its there (i.e. single user)
622*7c478bd9Sstevel@tonic-gate  */
623*7c478bd9Sstevel@tonic-gate 
624*7c478bd9Sstevel@tonic-gate 	if (sac_home())
625*7c478bd9Sstevel@tonic-gate 		read_db(NULL);
626*7c478bd9Sstevel@tonic-gate 	return;
627*7c478bd9Sstevel@tonic-gate }
628*7c478bd9Sstevel@tonic-gate 
629*7c478bd9Sstevel@tonic-gate 
630*7c478bd9Sstevel@tonic-gate /*
631*7c478bd9Sstevel@tonic-gate  * cleandirs - remove anything that might have been created (i.e. failed
632*7c478bd9Sstevel@tonic-gate  *	addition.  Saferrno is set elsewhere; this is strictly an attempt
633*7c478bd9Sstevel@tonic-gate  *	to clean up what mess we've left, so don't check to see if the
634*7c478bd9Sstevel@tonic-gate  *	cleanup worked.
635*7c478bd9Sstevel@tonic-gate  *
636*7c478bd9Sstevel@tonic-gate  *	args:	tag - tag of port monitor whose trees should be removed
637*7c478bd9Sstevel@tonic-gate  */
638*7c478bd9Sstevel@tonic-gate 
639*7c478bd9Sstevel@tonic-gate void
640*7c478bd9Sstevel@tonic-gate cleandirs(tag)
641*7c478bd9Sstevel@tonic-gate char *tag;
642*7c478bd9Sstevel@tonic-gate {
643*7c478bd9Sstevel@tonic-gate 	char buf[SIZE];		/* scratch buffer */
644*7c478bd9Sstevel@tonic-gate 
645*7c478bd9Sstevel@tonic-gate 	/* note: this removes the directory too, first zap /etc/saf/<tag> */
646*7c478bd9Sstevel@tonic-gate 	(void) sprintf(buf, "rm -rf %s/%s", HOME, tag);
647*7c478bd9Sstevel@tonic-gate 	(void) system(buf);
648*7c478bd9Sstevel@tonic-gate 
649*7c478bd9Sstevel@tonic-gate 	/* now remove /var/saf/<tag> */
650*7c478bd9Sstevel@tonic-gate 	(void) sprintf(buf, "%s/%s", ALTHOME, tag);
651*7c478bd9Sstevel@tonic-gate 	(void) rmdir(buf);
652*7c478bd9Sstevel@tonic-gate }
653*7c478bd9Sstevel@tonic-gate 
654*7c478bd9Sstevel@tonic-gate 
655*7c478bd9Sstevel@tonic-gate /*
656*7c478bd9Sstevel@tonic-gate  * rem_pm - remove a port monitor
657*7c478bd9Sstevel@tonic-gate  *
658*7c478bd9Sstevel@tonic-gate  *	args:	tag - tag of port monitor to be removed
659*7c478bd9Sstevel@tonic-gate  */
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate void
662*7c478bd9Sstevel@tonic-gate rem_pm(tag)
663*7c478bd9Sstevel@tonic-gate char *tag;
664*7c478bd9Sstevel@tonic-gate {
665*7c478bd9Sstevel@tonic-gate 	FILE *fp;		/* file pointer for _sactab */
666*7c478bd9Sstevel@tonic-gate 	FILE *tfp;		/* file pointer for temp file */
667*7c478bd9Sstevel@tonic-gate 	int line;		/* line number entry is on */
668*7c478bd9Sstevel@tonic-gate 	char *tname;		/* temp file name */
669*7c478bd9Sstevel@tonic-gate 	char buf[SIZE];		/* scratch buffer */
670*7c478bd9Sstevel@tonic-gate 
671*7c478bd9Sstevel@tonic-gate 	fp = fopen(SACTAB, "r");
672*7c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
673*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
674*7c478bd9Sstevel@tonic-gate 		error("Could not open _sactab");
675*7c478bd9Sstevel@tonic-gate 	}
676*7c478bd9Sstevel@tonic-gate 	if ((line = find_pm(fp, tag)) == 0) {
677*7c478bd9Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
678*7c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "Invalid request, %s does not exist", tag);
679*7c478bd9Sstevel@tonic-gate 		error(buf);
680*7c478bd9Sstevel@tonic-gate 	}
681*7c478bd9Sstevel@tonic-gate 	tname = make_tempname("_sactab");
682*7c478bd9Sstevel@tonic-gate 	tfp = open_temp(tname);
683*7c478bd9Sstevel@tonic-gate 	if (line != 1) {
684*7c478bd9Sstevel@tonic-gate 		if (copy_file(fp, tfp, 1, line - 1)) {
685*7c478bd9Sstevel@tonic-gate 			(void) unlink(tname);
686*7c478bd9Sstevel@tonic-gate 			Saferrno = E_SYSERR;
687*7c478bd9Sstevel@tonic-gate 			error("error accessing temp file");
688*7c478bd9Sstevel@tonic-gate 		}
689*7c478bd9Sstevel@tonic-gate 	}
690*7c478bd9Sstevel@tonic-gate 	if (copy_file(fp, tfp, line + 1, -1)) {
691*7c478bd9Sstevel@tonic-gate 		(void) unlink(tname);
692*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
693*7c478bd9Sstevel@tonic-gate 		error("error accessing temp file");
694*7c478bd9Sstevel@tonic-gate 	}
695*7c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
696*7c478bd9Sstevel@tonic-gate 	if (fclose(tfp) == EOF) {
697*7c478bd9Sstevel@tonic-gate 		(void) unlink(tname);
698*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
699*7c478bd9Sstevel@tonic-gate 		error("error closing tempfile");
700*7c478bd9Sstevel@tonic-gate 	}
701*7c478bd9Sstevel@tonic-gate 	/* note - replace only returns if successful */
702*7c478bd9Sstevel@tonic-gate 	replace("_sactab", tname);
703*7c478bd9Sstevel@tonic-gate 
704*7c478bd9Sstevel@tonic-gate /*
705*7c478bd9Sstevel@tonic-gate  * tell the SAC to read _sactab if its there (i.e. single user)
706*7c478bd9Sstevel@tonic-gate  */
707*7c478bd9Sstevel@tonic-gate 
708*7c478bd9Sstevel@tonic-gate 	if (sac_home())
709*7c478bd9Sstevel@tonic-gate 		read_db(NULL);
710*7c478bd9Sstevel@tonic-gate 	return;
711*7c478bd9Sstevel@tonic-gate }
712*7c478bd9Sstevel@tonic-gate 
713*7c478bd9Sstevel@tonic-gate 
714*7c478bd9Sstevel@tonic-gate /*
715*7c478bd9Sstevel@tonic-gate  * start_pm - start a particular port monitor
716*7c478bd9Sstevel@tonic-gate  *
717*7c478bd9Sstevel@tonic-gate  *	args:	tag - tag of port monitor to be started
718*7c478bd9Sstevel@tonic-gate  */
719*7c478bd9Sstevel@tonic-gate 
720*7c478bd9Sstevel@tonic-gate void
721*7c478bd9Sstevel@tonic-gate start_pm(tag)
722*7c478bd9Sstevel@tonic-gate char *tag;
723*7c478bd9Sstevel@tonic-gate {
724*7c478bd9Sstevel@tonic-gate 	struct admcmd cmd;			/* command structure */
725*7c478bd9Sstevel@tonic-gate 	register struct admcmd *ap = &cmd;	/* and a pointer to it */
726*7c478bd9Sstevel@tonic-gate 
727*7c478bd9Sstevel@tonic-gate 	ap->ac_mtype = AC_START;
728*7c478bd9Sstevel@tonic-gate 	(void) strcpy(ap->ac_tag, tag);
729*7c478bd9Sstevel@tonic-gate 	ap->ac_pid = getpid();
730*7c478bd9Sstevel@tonic-gate 	sendcmd(ap, NULL, tag);
731*7c478bd9Sstevel@tonic-gate 	return;
732*7c478bd9Sstevel@tonic-gate }
733*7c478bd9Sstevel@tonic-gate 
734*7c478bd9Sstevel@tonic-gate 
735*7c478bd9Sstevel@tonic-gate /*
736*7c478bd9Sstevel@tonic-gate  * kill_pm - stop a particular port monitor
737*7c478bd9Sstevel@tonic-gate  *
738*7c478bd9Sstevel@tonic-gate  *	args:	tag - tag of port monitor to be stopped
739*7c478bd9Sstevel@tonic-gate  */
740*7c478bd9Sstevel@tonic-gate 
741*7c478bd9Sstevel@tonic-gate void
742*7c478bd9Sstevel@tonic-gate kill_pm(tag)
743*7c478bd9Sstevel@tonic-gate char *tag;
744*7c478bd9Sstevel@tonic-gate {
745*7c478bd9Sstevel@tonic-gate 	struct admcmd cmd;			/* command structure */
746*7c478bd9Sstevel@tonic-gate 	register struct admcmd *ap = &cmd;	/* and a pointer to it */
747*7c478bd9Sstevel@tonic-gate 
748*7c478bd9Sstevel@tonic-gate 	ap->ac_mtype = AC_KILL;
749*7c478bd9Sstevel@tonic-gate 	(void) strcpy(ap->ac_tag, tag);
750*7c478bd9Sstevel@tonic-gate 	ap->ac_pid = getpid();
751*7c478bd9Sstevel@tonic-gate 	sendcmd(ap, NULL, tag);
752*7c478bd9Sstevel@tonic-gate 	return;
753*7c478bd9Sstevel@tonic-gate }
754*7c478bd9Sstevel@tonic-gate 
755*7c478bd9Sstevel@tonic-gate 
756*7c478bd9Sstevel@tonic-gate /*
757*7c478bd9Sstevel@tonic-gate  * enable_pm - enable a particular port monitor
758*7c478bd9Sstevel@tonic-gate  *
759*7c478bd9Sstevel@tonic-gate  *	args:	tag - tag of port monitor to be enabled
760*7c478bd9Sstevel@tonic-gate  */
761*7c478bd9Sstevel@tonic-gate 
762*7c478bd9Sstevel@tonic-gate void
763*7c478bd9Sstevel@tonic-gate enable_pm(tag)
764*7c478bd9Sstevel@tonic-gate char *tag;
765*7c478bd9Sstevel@tonic-gate {
766*7c478bd9Sstevel@tonic-gate 	struct admcmd cmd;			/* command structure */
767*7c478bd9Sstevel@tonic-gate 	register struct admcmd *ap = &cmd;	/* and a pointer to it */
768*7c478bd9Sstevel@tonic-gate 
769*7c478bd9Sstevel@tonic-gate 	ap->ac_mtype = AC_ENABLE;
770*7c478bd9Sstevel@tonic-gate 	(void) strcpy(ap->ac_tag, tag);
771*7c478bd9Sstevel@tonic-gate 	ap->ac_pid = getpid();
772*7c478bd9Sstevel@tonic-gate 	sendcmd(ap, NULL, tag);
773*7c478bd9Sstevel@tonic-gate 	return;
774*7c478bd9Sstevel@tonic-gate }
775*7c478bd9Sstevel@tonic-gate 
776*7c478bd9Sstevel@tonic-gate 
777*7c478bd9Sstevel@tonic-gate /*
778*7c478bd9Sstevel@tonic-gate  * disable_pm - disable a particular port monitor
779*7c478bd9Sstevel@tonic-gate  *
780*7c478bd9Sstevel@tonic-gate  *	args:	tag - tag of port monitor to be disabled
781*7c478bd9Sstevel@tonic-gate  */
782*7c478bd9Sstevel@tonic-gate 
783*7c478bd9Sstevel@tonic-gate void
784*7c478bd9Sstevel@tonic-gate disable_pm(tag)
785*7c478bd9Sstevel@tonic-gate char *tag;
786*7c478bd9Sstevel@tonic-gate {
787*7c478bd9Sstevel@tonic-gate 	struct admcmd cmd;			/* command structure */
788*7c478bd9Sstevel@tonic-gate 	register struct admcmd *ap = &cmd;	/* and a pointer to it */
789*7c478bd9Sstevel@tonic-gate 
790*7c478bd9Sstevel@tonic-gate 	ap->ac_mtype = AC_DISABLE;
791*7c478bd9Sstevel@tonic-gate 	(void) strcpy(ap->ac_tag, tag);
792*7c478bd9Sstevel@tonic-gate 	ap->ac_pid = getpid();
793*7c478bd9Sstevel@tonic-gate 	sendcmd(ap, NULL, tag);
794*7c478bd9Sstevel@tonic-gate 	return;
795*7c478bd9Sstevel@tonic-gate }
796*7c478bd9Sstevel@tonic-gate 
797*7c478bd9Sstevel@tonic-gate 
798*7c478bd9Sstevel@tonic-gate /*
799*7c478bd9Sstevel@tonic-gate  * read_db - tell SAC or a port monitor to read its administrative file.
800*7c478bd9Sstevel@tonic-gate  *
801*7c478bd9Sstevel@tonic-gate  *	args:	tag - tag of port monitor that should read its administrative
802*7c478bd9Sstevel@tonic-gate  *		      file.  If NULL, it means SAC should.
803*7c478bd9Sstevel@tonic-gate  */
804*7c478bd9Sstevel@tonic-gate 
805*7c478bd9Sstevel@tonic-gate void
806*7c478bd9Sstevel@tonic-gate read_db(tag)
807*7c478bd9Sstevel@tonic-gate char *tag;
808*7c478bd9Sstevel@tonic-gate {
809*7c478bd9Sstevel@tonic-gate 	struct admcmd cmd;			/* command structure */
810*7c478bd9Sstevel@tonic-gate 	register struct admcmd *ap = &cmd;	/* and a pointer to it */
811*7c478bd9Sstevel@tonic-gate 
812*7c478bd9Sstevel@tonic-gate 	ap->ac_mtype = (tag) ? AC_PMREAD : AC_SACREAD;
813*7c478bd9Sstevel@tonic-gate 	if (tag)
814*7c478bd9Sstevel@tonic-gate 		(void) strcpy(ap->ac_tag, tag);
815*7c478bd9Sstevel@tonic-gate 	ap->ac_pid = getpid();
816*7c478bd9Sstevel@tonic-gate 	sendcmd(ap, NULL, tag);
817*7c478bd9Sstevel@tonic-gate 	return;
818*7c478bd9Sstevel@tonic-gate }
819*7c478bd9Sstevel@tonic-gate 
820*7c478bd9Sstevel@tonic-gate 
821*7c478bd9Sstevel@tonic-gate /*
822*7c478bd9Sstevel@tonic-gate  * list_pms - request information about port monitors from SAC and output
823*7c478bd9Sstevel@tonic-gate  *		requested info
824*7c478bd9Sstevel@tonic-gate  *
825*7c478bd9Sstevel@tonic-gate  *	args:	pmtag - tag of port monitor to be listed (may be null)
826*7c478bd9Sstevel@tonic-gate  *		pmtype - type of port monitors to be listed (may be null)
827*7c478bd9Sstevel@tonic-gate  *		oflag - true if output should be easily parseable
828*7c478bd9Sstevel@tonic-gate  */
829*7c478bd9Sstevel@tonic-gate 
830*7c478bd9Sstevel@tonic-gate void
831*7c478bd9Sstevel@tonic-gate list_pms(pmtag, pmtype, oflag)
832*7c478bd9Sstevel@tonic-gate char *pmtag;
833*7c478bd9Sstevel@tonic-gate char *pmtype;
834*7c478bd9Sstevel@tonic-gate int oflag;
835*7c478bd9Sstevel@tonic-gate {
836*7c478bd9Sstevel@tonic-gate 	struct admcmd acmd;			/* command structure */
837*7c478bd9Sstevel@tonic-gate 	register struct admcmd *ap = &acmd;	/* and a pointer to it */
838*7c478bd9Sstevel@tonic-gate 	int nprint = 0;				/* count # of PMs printed */
839*7c478bd9Sstevel@tonic-gate 	char *p;				/* scratch pointer */
840*7c478bd9Sstevel@tonic-gate 	char *tag;				/* returned tag */
841*7c478bd9Sstevel@tonic-gate 	char *type;				/* returned type */
842*7c478bd9Sstevel@tonic-gate 	char *flags;				/* returned flags */
843*7c478bd9Sstevel@tonic-gate 	char *rsmax;				/* returned restart count */
844*7c478bd9Sstevel@tonic-gate 	char *state;				/* returned state */
845*7c478bd9Sstevel@tonic-gate 	char *cmd;				/* returned command string */
846*7c478bd9Sstevel@tonic-gate 	char *comment;				/* returned comment string */
847*7c478bd9Sstevel@tonic-gate 
848*7c478bd9Sstevel@tonic-gate /*
849*7c478bd9Sstevel@tonic-gate  * if sac isn't there (single user), provide info direct from _sactab
850*7c478bd9Sstevel@tonic-gate  * note: when this routine returns, the process exits, so there is no
851*7c478bd9Sstevel@tonic-gate  * need to free up any memory
852*7c478bd9Sstevel@tonic-gate  */
853*7c478bd9Sstevel@tonic-gate 
854*7c478bd9Sstevel@tonic-gate 	p = NULL;
855*7c478bd9Sstevel@tonic-gate 	if (sac_home()) {
856*7c478bd9Sstevel@tonic-gate 		ap->ac_mtype = AC_STATUS;
857*7c478bd9Sstevel@tonic-gate 		ap->ac_tag[0] = '\0';
858*7c478bd9Sstevel@tonic-gate 		ap->ac_pid = getpid();
859*7c478bd9Sstevel@tonic-gate 		sendcmd(ap, &p, NULL);
860*7c478bd9Sstevel@tonic-gate 	}
861*7c478bd9Sstevel@tonic-gate 	else {
862*7c478bd9Sstevel@tonic-gate 		single_print(&p);
863*7c478bd9Sstevel@tonic-gate 	}
864*7c478bd9Sstevel@tonic-gate 
865*7c478bd9Sstevel@tonic-gate /*
866*7c478bd9Sstevel@tonic-gate  * SAC sends back info in condensed form, we have to separate it out
867*7c478bd9Sstevel@tonic-gate  * fields come in ':' separated, records are separated by newlines
868*7c478bd9Sstevel@tonic-gate  */
869*7c478bd9Sstevel@tonic-gate 
870*7c478bd9Sstevel@tonic-gate 	while (p && *p) {
871*7c478bd9Sstevel@tonic-gate 		tag = getfield(&p, ':');	/* PM tag */
872*7c478bd9Sstevel@tonic-gate 		type = getfield(&p, ':');	/* PM type */
873*7c478bd9Sstevel@tonic-gate 		flags = getfield(&p, ':');	/* flags */
874*7c478bd9Sstevel@tonic-gate 		rsmax = getfield(&p, ':');	/* restart count */
875*7c478bd9Sstevel@tonic-gate 		state = pstate((unchar) atoi(getfield(&p, ':')));	/* state in nice output format */
876*7c478bd9Sstevel@tonic-gate 		cmd = getfield(&p, ':');	/* command */
877*7c478bd9Sstevel@tonic-gate 		comment = getfield(&p, '\n');	/* comment */
878*7c478bd9Sstevel@tonic-gate 
879*7c478bd9Sstevel@tonic-gate 
880*7c478bd9Sstevel@tonic-gate /*
881*7c478bd9Sstevel@tonic-gate  * print out if no selectors specified, else check to see if
882*7c478bd9Sstevel@tonic-gate  * a selector matched
883*7c478bd9Sstevel@tonic-gate  */
884*7c478bd9Sstevel@tonic-gate 
885*7c478bd9Sstevel@tonic-gate 		if ((!pmtag && !pmtype) || (pmtag && !strcmp(pmtag, tag)) || (pmtype && !strcmp(pmtype, type))) {
886*7c478bd9Sstevel@tonic-gate 			if (oflag) {
887*7c478bd9Sstevel@tonic-gate 				(void) printf("%s:%s:%s:%s:%s:%s#%s\n", tag, type, pflags(atol(flags), FALSE),
888*7c478bd9Sstevel@tonic-gate 						rsmax, state, cmd, comment);
889*7c478bd9Sstevel@tonic-gate 			}
890*7c478bd9Sstevel@tonic-gate 			else {
891*7c478bd9Sstevel@tonic-gate 				if (nprint == 0) {
892*7c478bd9Sstevel@tonic-gate 					(void) printf("PMTAG          PMTYPE         FLGS RCNT STATUS     COMMAND\n");
893*7c478bd9Sstevel@tonic-gate 				}
894*7c478bd9Sstevel@tonic-gate 				(void) printf("%-14s %-14s %-4s %-4s %-10s %s #%s\n", tag, type, pflags(atol(flags), TRUE),
895*7c478bd9Sstevel@tonic-gate 						rsmax, state, cmd, comment);
896*7c478bd9Sstevel@tonic-gate 			}
897*7c478bd9Sstevel@tonic-gate 			nprint++;
898*7c478bd9Sstevel@tonic-gate 		}
899*7c478bd9Sstevel@tonic-gate 	}
900*7c478bd9Sstevel@tonic-gate 	/*
901*7c478bd9Sstevel@tonic-gate 	 * if we didn't find any valid ones, indicate an error (note: 1 and
902*7c478bd9Sstevel@tonic-gate 	 * only 1 of the if statements should be true)
903*7c478bd9Sstevel@tonic-gate 	 */
904*7c478bd9Sstevel@tonic-gate 	if (nprint == 0) {
905*7c478bd9Sstevel@tonic-gate 		if (pmtype)
906*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "Invalid request, %s does not exist\n", pmtype);
907*7c478bd9Sstevel@tonic-gate 		else if (pmtag)
908*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "Invalid request, %s does not exist\n", pmtag);
909*7c478bd9Sstevel@tonic-gate 		else if (!pmtag && !pmtype)
910*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "No port monitors defined\n");
911*7c478bd9Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
912*7c478bd9Sstevel@tonic-gate 	}
913*7c478bd9Sstevel@tonic-gate 	return;
914*7c478bd9Sstevel@tonic-gate }
915*7c478bd9Sstevel@tonic-gate 
916*7c478bd9Sstevel@tonic-gate 
917*7c478bd9Sstevel@tonic-gate /*
918*7c478bd9Sstevel@tonic-gate  * getfield - retrieve and return a field from the sac "status" string (input
919*7c478bd9Sstevel@tonic-gate  *	argument is modified to point to next field as a side-effect)
920*7c478bd9Sstevel@tonic-gate  *
921*7c478bd9Sstevel@tonic-gate  *	args:	p - address of remaining portion of string
922*7c478bd9Sstevel@tonic-gate  *		sepchar - field terminator character
923*7c478bd9Sstevel@tonic-gate  */
924*7c478bd9Sstevel@tonic-gate 
925*7c478bd9Sstevel@tonic-gate char *
926*7c478bd9Sstevel@tonic-gate getfield(p, sepchar)
927*7c478bd9Sstevel@tonic-gate char **p;
928*7c478bd9Sstevel@tonic-gate char sepchar;
929*7c478bd9Sstevel@tonic-gate {
930*7c478bd9Sstevel@tonic-gate 	char *savep;	/* for saving argument */
931*7c478bd9Sstevel@tonic-gate 
932*7c478bd9Sstevel@tonic-gate 	savep = *p;
933*7c478bd9Sstevel@tonic-gate 	*p = strchr(*p, sepchar);
934*7c478bd9Sstevel@tonic-gate 	if (*p == NULL) {
935*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
936*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Improper message from SAC\n");
937*7c478bd9Sstevel@tonic-gate 		return(NULL);
938*7c478bd9Sstevel@tonic-gate 	}
939*7c478bd9Sstevel@tonic-gate 	**p = '\0';
940*7c478bd9Sstevel@tonic-gate 	(*p)++;
941*7c478bd9Sstevel@tonic-gate 	return(savep);
942*7c478bd9Sstevel@tonic-gate }
943*7c478bd9Sstevel@tonic-gate 
944*7c478bd9Sstevel@tonic-gate 
945*7c478bd9Sstevel@tonic-gate /*
946*7c478bd9Sstevel@tonic-gate  * single_print - print out _sactab if sac not at home (should only happen
947*7c478bd9Sstevel@tonic-gate  *	in single user mode
948*7c478bd9Sstevel@tonic-gate  *
949*7c478bd9Sstevel@tonic-gate  *	args:	p - address of pointer where formatted data should be
950*7c478bd9Sstevel@tonic-gate  *		    placed (space allocated here)
951*7c478bd9Sstevel@tonic-gate  */
952*7c478bd9Sstevel@tonic-gate 
953*7c478bd9Sstevel@tonic-gate void
954*7c478bd9Sstevel@tonic-gate single_print(p)
955*7c478bd9Sstevel@tonic-gate char **p;
956*7c478bd9Sstevel@tonic-gate {
957*7c478bd9Sstevel@tonic-gate 	FILE *fp;				/* file pointer for _sactab */
958*7c478bd9Sstevel@tonic-gate 	struct stat statbuf;			/* file status info */
959*7c478bd9Sstevel@tonic-gate 	register char *tp1;			/* scratch pointer */
960*7c478bd9Sstevel@tonic-gate 	register char *tp2;			/* scratch pointer */
961*7c478bd9Sstevel@tonic-gate 	struct sactab stab;			/* place to hold parsed info */
962*7c478bd9Sstevel@tonic-gate 	register struct sactab *sp = &stab;	/* and a pointer to it */
963*7c478bd9Sstevel@tonic-gate 	char buf[SIZE];				/* scratch buffer */
964*7c478bd9Sstevel@tonic-gate 
965*7c478bd9Sstevel@tonic-gate 	fp = fopen(SACTAB, "r");
966*7c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
967*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
968*7c478bd9Sstevel@tonic-gate 		error("Could not open _sactab");
969*7c478bd9Sstevel@tonic-gate 	}
970*7c478bd9Sstevel@tonic-gate 	if (fstat(fileno(fp), &statbuf) < 0) {
971*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
972*7c478bd9Sstevel@tonic-gate 		error("could not stat _sactab");
973*7c478bd9Sstevel@tonic-gate 	}
974*7c478bd9Sstevel@tonic-gate 
975*7c478bd9Sstevel@tonic-gate /*
976*7c478bd9Sstevel@tonic-gate  * allocate space to build return string, twice file size should be more
977*7c478bd9Sstevel@tonic-gate  * than enough (and make sure it's zero'ed out)
978*7c478bd9Sstevel@tonic-gate  */
979*7c478bd9Sstevel@tonic-gate 
980*7c478bd9Sstevel@tonic-gate 	tp1 = calloc(2 * statbuf.st_size, sizeof(char));
981*7c478bd9Sstevel@tonic-gate 	if (tp1 == NULL) {
982*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
983*7c478bd9Sstevel@tonic-gate 		error("could not allocate storage");
984*7c478bd9Sstevel@tonic-gate 	}
985*7c478bd9Sstevel@tonic-gate 
986*7c478bd9Sstevel@tonic-gate /*
987*7c478bd9Sstevel@tonic-gate  * read the file and build the string
988*7c478bd9Sstevel@tonic-gate  */
989*7c478bd9Sstevel@tonic-gate 
990*7c478bd9Sstevel@tonic-gate 	while (fgets(buf, SIZE, fp)) {
991*7c478bd9Sstevel@tonic-gate 		tp2 = trim(buf);
992*7c478bd9Sstevel@tonic-gate 		if (*tp2 == '\0')
993*7c478bd9Sstevel@tonic-gate 			continue;
994*7c478bd9Sstevel@tonic-gate 		parse(tp2, &stab);
995*7c478bd9Sstevel@tonic-gate 		(void) sprintf(buf, "%s:%s:%d:%d:%d:%s:%s\n", sp->sc_tag, sp->sc_type,
996*7c478bd9Sstevel@tonic-gate 			sp->sc_flags, sp->sc_rsmax, SSTATE, sp->sc_cmd, sp->sc_comment);
997*7c478bd9Sstevel@tonic-gate 		(void) strcat(tp1, buf);
998*7c478bd9Sstevel@tonic-gate 		free(sp->sc_cmd);
999*7c478bd9Sstevel@tonic-gate 		free(sp->sc_comment);
1000*7c478bd9Sstevel@tonic-gate 	}
1001*7c478bd9Sstevel@tonic-gate 	if (!feof(fp)) {
1002*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
1003*7c478bd9Sstevel@tonic-gate 		error("error reading _sactab");
1004*7c478bd9Sstevel@tonic-gate 	}
1005*7c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
1006*7c478bd9Sstevel@tonic-gate 
1007*7c478bd9Sstevel@tonic-gate /*
1008*7c478bd9Sstevel@tonic-gate  * point at the just-built string
1009*7c478bd9Sstevel@tonic-gate  */
1010*7c478bd9Sstevel@tonic-gate 
1011*7c478bd9Sstevel@tonic-gate 	*p = tp1;
1012*7c478bd9Sstevel@tonic-gate 	return;
1013*7c478bd9Sstevel@tonic-gate }
1014*7c478bd9Sstevel@tonic-gate 
1015*7c478bd9Sstevel@tonic-gate 
1016*7c478bd9Sstevel@tonic-gate /*
1017*7c478bd9Sstevel@tonic-gate  * openpipe - open up command pipe to SAC
1018*7c478bd9Sstevel@tonic-gate  */
1019*7c478bd9Sstevel@tonic-gate 
1020*7c478bd9Sstevel@tonic-gate openpipe()
1021*7c478bd9Sstevel@tonic-gate {
1022*7c478bd9Sstevel@tonic-gate 	int fd;		/* file descriptor associated with command pipe */
1023*7c478bd9Sstevel@tonic-gate 
1024*7c478bd9Sstevel@tonic-gate 	fd = open(CMDPIPE, O_RDWR);
1025*7c478bd9Sstevel@tonic-gate 	if (fd < 0) {
1026*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
1027*7c478bd9Sstevel@tonic-gate 		error(SACERR);
1028*7c478bd9Sstevel@tonic-gate 	}
1029*7c478bd9Sstevel@tonic-gate 
1030*7c478bd9Sstevel@tonic-gate /*
1031*7c478bd9Sstevel@tonic-gate  * lock pipe to insure serial access, lock will disappear if process dies
1032*7c478bd9Sstevel@tonic-gate  */
1033*7c478bd9Sstevel@tonic-gate 
1034*7c478bd9Sstevel@tonic-gate 	if (lockf(fd, F_LOCK, 0) < 0) {
1035*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
1036*7c478bd9Sstevel@tonic-gate 		error("unable to lock command pipe");
1037*7c478bd9Sstevel@tonic-gate 	}
1038*7c478bd9Sstevel@tonic-gate 	return(fd);
1039*7c478bd9Sstevel@tonic-gate }
1040*7c478bd9Sstevel@tonic-gate 
1041*7c478bd9Sstevel@tonic-gate 
1042*7c478bd9Sstevel@tonic-gate /*
1043*7c478bd9Sstevel@tonic-gate  * sendcmd - send a command to the SAC
1044*7c478bd9Sstevel@tonic-gate  *
1045*7c478bd9Sstevel@tonic-gate  *	args:	ap - pointer to command to send
1046*7c478bd9Sstevel@tonic-gate  *		info - pointer to return information from the SAC
1047*7c478bd9Sstevel@tonic-gate  *		tag - tag of port monitor to which the command applies (may
1048*7c478bd9Sstevel@tonic-gate  *		      be NULL)
1049*7c478bd9Sstevel@tonic-gate  */
1050*7c478bd9Sstevel@tonic-gate 
1051*7c478bd9Sstevel@tonic-gate void
1052*7c478bd9Sstevel@tonic-gate sendcmd(ap, info, tag)
1053*7c478bd9Sstevel@tonic-gate struct admcmd *ap;
1054*7c478bd9Sstevel@tonic-gate char **info;
1055*7c478bd9Sstevel@tonic-gate char *tag;
1056*7c478bd9Sstevel@tonic-gate {
1057*7c478bd9Sstevel@tonic-gate 	int fd;		/* file descriptor of command pipe */
1058*7c478bd9Sstevel@tonic-gate 
1059*7c478bd9Sstevel@tonic-gate 	fd = openpipe();
1060*7c478bd9Sstevel@tonic-gate 	if (write(fd, ap, sizeof(struct admcmd)) < 0) {
1061*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SYSERR;
1062*7c478bd9Sstevel@tonic-gate 		error(SACERR);
1063*7c478bd9Sstevel@tonic-gate 	}
1064*7c478bd9Sstevel@tonic-gate 	checkresp(fd, info, tag);
1065*7c478bd9Sstevel@tonic-gate 
1066*7c478bd9Sstevel@tonic-gate /*
1067*7c478bd9Sstevel@tonic-gate  * unlock the command pipe - not really necessary since we're about to close
1068*7c478bd9Sstevel@tonic-gate  */
1069*7c478bd9Sstevel@tonic-gate 
1070*7c478bd9Sstevel@tonic-gate 	(void) lockf(fd, F_ULOCK, 0);
1071*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
1072*7c478bd9Sstevel@tonic-gate 	return;
1073*7c478bd9Sstevel@tonic-gate }
1074*7c478bd9Sstevel@tonic-gate 
1075*7c478bd9Sstevel@tonic-gate 
1076*7c478bd9Sstevel@tonic-gate /*
1077*7c478bd9Sstevel@tonic-gate  * checkresp - check the SAC's response to our command
1078*7c478bd9Sstevel@tonic-gate  *
1079*7c478bd9Sstevel@tonic-gate  *	args:	fd - file descriptor of command pipe
1080*7c478bd9Sstevel@tonic-gate  *		info - pointer to return and info send along by SAC
1081*7c478bd9Sstevel@tonic-gate  *		tag - tag of port monitor that the command had been
1082*7c478bd9Sstevel@tonic-gate  *		      for, only used for error reporting
1083*7c478bd9Sstevel@tonic-gate  */
1084*7c478bd9Sstevel@tonic-gate 
1085*7c478bd9Sstevel@tonic-gate void
1086*7c478bd9Sstevel@tonic-gate checkresp(fd, info, tag)
1087*7c478bd9Sstevel@tonic-gate int fd;
1088*7c478bd9Sstevel@tonic-gate char **info;
1089*7c478bd9Sstevel@tonic-gate char *tag;
1090*7c478bd9Sstevel@tonic-gate {
1091*7c478bd9Sstevel@tonic-gate 	struct admack ack;			/* acknowledgment struct */
1092*7c478bd9Sstevel@tonic-gate 	register struct admack *ak = &ack;	/* and a pointer to it */
1093*7c478bd9Sstevel@tonic-gate 	pid_t pid;				/* my pid */
1094*7c478bd9Sstevel@tonic-gate 	struct sigaction sigact;		/* signal handler setup */
1095*7c478bd9Sstevel@tonic-gate 
1096*7c478bd9Sstevel@tonic-gate /*
1097*7c478bd9Sstevel@tonic-gate  * make sure this ack is meant for me, put an alarm around the read
1098*7c478bd9Sstevel@tonic-gate  * so we don't hang out forever.
1099*7c478bd9Sstevel@tonic-gate  */
1100*7c478bd9Sstevel@tonic-gate 
1101*7c478bd9Sstevel@tonic-gate 	pid = getpid();
1102*7c478bd9Sstevel@tonic-gate 	sigact.sa_flags = 0;
1103*7c478bd9Sstevel@tonic-gate 	sigact.sa_handler = catch;
1104*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&sigact.sa_mask);
1105*7c478bd9Sstevel@tonic-gate 	(void) sigaddset(&sigact.sa_mask, SIGALRM);
1106*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGALRM, &sigact, NULL);
1107*7c478bd9Sstevel@tonic-gate 	(void) alarm(10);
1108*7c478bd9Sstevel@tonic-gate 	do {
1109*7c478bd9Sstevel@tonic-gate 		if (read(fd, ak, sizeof(ack)) != sizeof(ack)) {
1110*7c478bd9Sstevel@tonic-gate 			Saferrno = E_SACNOTRUN;
1111*7c478bd9Sstevel@tonic-gate 			error(SACERR);
1112*7c478bd9Sstevel@tonic-gate 		}
1113*7c478bd9Sstevel@tonic-gate 	} while (pid != ak->ak_pid);
1114*7c478bd9Sstevel@tonic-gate 	(void) alarm(0);
1115*7c478bd9Sstevel@tonic-gate 
1116*7c478bd9Sstevel@tonic-gate /*
1117*7c478bd9Sstevel@tonic-gate  * check out what happened
1118*7c478bd9Sstevel@tonic-gate  */
1119*7c478bd9Sstevel@tonic-gate 
1120*7c478bd9Sstevel@tonic-gate 	switch (ak->ak_resp) {
1121*7c478bd9Sstevel@tonic-gate 	case AK_ACK:
1122*7c478bd9Sstevel@tonic-gate 		/* everything was A-OK */
1123*7c478bd9Sstevel@tonic-gate 		if (info && ak->ak_size) {
1124*7c478bd9Sstevel@tonic-gate 			/* there is return info and a place to put it */
1125*7c478bd9Sstevel@tonic-gate 			if ((*info = malloc((unsigned) (ak->ak_size + 1))) == NULL) {
1126*7c478bd9Sstevel@tonic-gate 				Saferrno = E_SYSERR;
1127*7c478bd9Sstevel@tonic-gate 				error("could not allocate storage");
1128*7c478bd9Sstevel@tonic-gate 			}
1129*7c478bd9Sstevel@tonic-gate 			if (read(fd, *info, (unsigned) ak->ak_size) != ak->ak_size) {
1130*7c478bd9Sstevel@tonic-gate 				Saferrno = E_SYSERR;
1131*7c478bd9Sstevel@tonic-gate 				error(SACERR);
1132*7c478bd9Sstevel@tonic-gate 			}
1133*7c478bd9Sstevel@tonic-gate 			/* make sure "string" is null-terminated */
1134*7c478bd9Sstevel@tonic-gate 			(*info)[ak->ak_size] = '\0';
1135*7c478bd9Sstevel@tonic-gate 		}
1136*7c478bd9Sstevel@tonic-gate 		return;
1137*7c478bd9Sstevel@tonic-gate 	/* something went wrong - see what */
1138*7c478bd9Sstevel@tonic-gate 	case AK_PMRUN:
1139*7c478bd9Sstevel@tonic-gate 		Saferrno = E_PMRUN;
1140*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Port monitor, %s, is already running\n", tag);
1141*7c478bd9Sstevel@tonic-gate 		break;
1142*7c478bd9Sstevel@tonic-gate 	case AK_PMNOTRUN:
1143*7c478bd9Sstevel@tonic-gate 		Saferrno = E_PMNOTRUN;
1144*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Port monitor, %s, is not running\n", tag);
1145*7c478bd9Sstevel@tonic-gate 		break;
1146*7c478bd9Sstevel@tonic-gate 	case AK_NOPM:
1147*7c478bd9Sstevel@tonic-gate 		Saferrno = E_NOEXIST;
1148*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Invalid request, %s does not exist\n", tag);
1149*7c478bd9Sstevel@tonic-gate 		break;
1150*7c478bd9Sstevel@tonic-gate 	case AK_UNKNOWN:
1151*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
1152*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Internal error - sent invalid command\n");
1153*7c478bd9Sstevel@tonic-gate 		break;
1154*7c478bd9Sstevel@tonic-gate 	case AK_NOCONTACT:
1155*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
1156*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Could not contact %s\n", tag);
1157*7c478bd9Sstevel@tonic-gate 		break;
1158*7c478bd9Sstevel@tonic-gate 	case AK_PMLOCK:
1159*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
1160*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Could not start %s - _pid file locked\n", tag);
1161*7c478bd9Sstevel@tonic-gate 		break;
1162*7c478bd9Sstevel@tonic-gate 	case AK_RECOVER:
1163*7c478bd9Sstevel@tonic-gate 		Saferrno = E_RECOVER;
1164*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Port monitor, %s, is in recovery\n", tag);
1165*7c478bd9Sstevel@tonic-gate 		break;
1166*7c478bd9Sstevel@tonic-gate 	case AK_REQFAIL:
1167*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
1168*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "This request could not be completed - see sac log file for details\n");
1169*7c478bd9Sstevel@tonic-gate 		break;
1170*7c478bd9Sstevel@tonic-gate 	default:
1171*7c478bd9Sstevel@tonic-gate 		Saferrno = E_SAFERR;
1172*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "unknown response\n");
1173*7c478bd9Sstevel@tonic-gate 		break;
1174*7c478bd9Sstevel@tonic-gate 	}
1175*7c478bd9Sstevel@tonic-gate }
1176*7c478bd9Sstevel@tonic-gate 
1177*7c478bd9Sstevel@tonic-gate 
1178*7c478bd9Sstevel@tonic-gate /*
1179*7c478bd9Sstevel@tonic-gate  * catch - catcher for SIGALRM, don't need to do anything
1180*7c478bd9Sstevel@tonic-gate  */
1181*7c478bd9Sstevel@tonic-gate 
1182*7c478bd9Sstevel@tonic-gate void
1183*7c478bd9Sstevel@tonic-gate catch()
1184*7c478bd9Sstevel@tonic-gate {
1185*7c478bd9Sstevel@tonic-gate }
1186*7c478bd9Sstevel@tonic-gate 
1187*7c478bd9Sstevel@tonic-gate 
1188*7c478bd9Sstevel@tonic-gate /*
1189*7c478bd9Sstevel@tonic-gate  * pflags - put port monitor flags into intelligible form for output
1190*7c478bd9Sstevel@tonic-gate  *
1191*7c478bd9Sstevel@tonic-gate  *	args:	flags - binary representation of flags
1192*7c478bd9Sstevel@tonic-gate  *		dflag - true if a "-" should be returned if no flags
1193*7c478bd9Sstevel@tonic-gate  */
1194*7c478bd9Sstevel@tonic-gate 
1195*7c478bd9Sstevel@tonic-gate char *
1196*7c478bd9Sstevel@tonic-gate pflags(flags, dflag)
1197*7c478bd9Sstevel@tonic-gate long flags;
1198*7c478bd9Sstevel@tonic-gate int dflag;
1199*7c478bd9Sstevel@tonic-gate {
1200*7c478bd9Sstevel@tonic-gate 	register int i;			/* scratch counter */
1201*7c478bd9Sstevel@tonic-gate 	static char buf[SIZE];		/* formatted flags */
1202*7c478bd9Sstevel@tonic-gate 
1203*7c478bd9Sstevel@tonic-gate 	if (flags == 0) {
1204*7c478bd9Sstevel@tonic-gate 		if (dflag)
1205*7c478bd9Sstevel@tonic-gate 			return("-");
1206*7c478bd9Sstevel@tonic-gate 		else
1207*7c478bd9Sstevel@tonic-gate 			return("");
1208*7c478bd9Sstevel@tonic-gate 	}
1209*7c478bd9Sstevel@tonic-gate 	i = 0;
1210*7c478bd9Sstevel@tonic-gate 	if (flags & D_FLAG) {
1211*7c478bd9Sstevel@tonic-gate 		buf[i++] = 'd';
1212*7c478bd9Sstevel@tonic-gate 		flags &= ~D_FLAG;
1213*7c478bd9Sstevel@tonic-gate 	}
1214*7c478bd9Sstevel@tonic-gate 	if (flags & X_FLAG) {
1215*7c478bd9Sstevel@tonic-gate 		buf[i++] = 'x';
1216*7c478bd9Sstevel@tonic-gate 		flags &= ~X_FLAG;
1217*7c478bd9Sstevel@tonic-gate 	}
1218*7c478bd9Sstevel@tonic-gate 	if (flags) {
1219*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Bad information from SAC\n");
1220*7c478bd9Sstevel@tonic-gate 		exit(1);
1221*7c478bd9Sstevel@tonic-gate 	}
1222*7c478bd9Sstevel@tonic-gate 	buf[i] = '\0';
1223*7c478bd9Sstevel@tonic-gate 	return(buf);
1224*7c478bd9Sstevel@tonic-gate }
1225*7c478bd9Sstevel@tonic-gate 
1226*7c478bd9Sstevel@tonic-gate 
1227*7c478bd9Sstevel@tonic-gate /*
1228*7c478bd9Sstevel@tonic-gate  * sac_home - returns true is sac has a lock on its logfile, false
1229*7c478bd9Sstevel@tonic-gate  *	otherwise (useful to avoid errors for administrative actions in
1230*7c478bd9Sstevel@tonic-gate  *	single user mode)
1231*7c478bd9Sstevel@tonic-gate  */
1232*7c478bd9Sstevel@tonic-gate 
1233*7c478bd9Sstevel@tonic-gate sac_home()
1234*7c478bd9Sstevel@tonic-gate {
1235*7c478bd9Sstevel@tonic-gate 	int fd;		/* fd to sac logfile */
1236*7c478bd9Sstevel@tonic-gate 
1237*7c478bd9Sstevel@tonic-gate 	fd = open(LOGFILE, O_RDONLY);
1238*7c478bd9Sstevel@tonic-gate 	if (fd < 0) {
1239*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "warning - could not ascertain sac status\n");
1240*7c478bd9Sstevel@tonic-gate 		return(FALSE);
1241*7c478bd9Sstevel@tonic-gate 	}
1242*7c478bd9Sstevel@tonic-gate 	if (lockf(fd, F_TEST, 0) < 0) {
1243*7c478bd9Sstevel@tonic-gate 		/* everything is ok */
1244*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
1245*7c478bd9Sstevel@tonic-gate 		return(TRUE);
1246*7c478bd9Sstevel@tonic-gate 	}
1247*7c478bd9Sstevel@tonic-gate 	else {
1248*7c478bd9Sstevel@tonic-gate 		/* no one home */
1249*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
1250*7c478bd9Sstevel@tonic-gate 		return(FALSE);
1251*7c478bd9Sstevel@tonic-gate 	}
1252*7c478bd9Sstevel@tonic-gate }
1253