xref: /titanic_50/usr/src/lib/libnsl/saf/doconfig.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 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
30*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include <stdio.h>
34*7c478bd9Sstevel@tonic-gate #include <string.h>
35*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
36*7c478bd9Sstevel@tonic-gate #include <unistd.h>
37*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
38*7c478bd9Sstevel@tonic-gate #include <ulimit.h>
39*7c478bd9Sstevel@tonic-gate #include <wait.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
41*7c478bd9Sstevel@tonic-gate #include <rpc/trace.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
43*7c478bd9Sstevel@tonic-gate #include <stropts.h>
44*7c478bd9Sstevel@tonic-gate #include <ctype.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/conf.h>
46*7c478bd9Sstevel@tonic-gate #include <errno.h>
47*7c478bd9Sstevel@tonic-gate #include <signal.h>
48*7c478bd9Sstevel@tonic-gate #include "sac.h"
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate #if defined(sparc)
51*7c478bd9Sstevel@tonic-gate #define	_STAT _stat
52*7c478bd9Sstevel@tonic-gate #define	_FSTAT _fstat
53*7c478bd9Sstevel@tonic-gate #else  /* !sparc */
54*7c478bd9Sstevel@tonic-gate #define	_STAT stat
55*7c478bd9Sstevel@tonic-gate #define	_FSTAT fstat
56*7c478bd9Sstevel@tonic-gate #endif /* sparc */
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate extern int	_stat(const char *, struct stat *);
59*7c478bd9Sstevel@tonic-gate extern int	_fstat(int, struct stat *);
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate #define	COMMENT	'#'
62*7c478bd9Sstevel@tonic-gate #define	NOWAIT	0
63*7c478bd9Sstevel@tonic-gate #define	WAIT	1
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate extern char	**_environ;
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate static char	*eatwhite();
68*7c478bd9Sstevel@tonic-gate static int	doassign();
69*7c478bd9Sstevel@tonic-gate static int	dopush();
70*7c478bd9Sstevel@tonic-gate static int	dopop();
71*7c478bd9Sstevel@tonic-gate static int	dorun();
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate /*
74*7c478bd9Sstevel@tonic-gate  * doconfig - the configuration script interpreter, if all is ok,
75*7c478bd9Sstevel@tonic-gate  *	      return 0.  If there is a "system" error, return -1.
76*7c478bd9Sstevel@tonic-gate  *	      If there is an error performing a command, or there
77*7c478bd9Sstevel@tonic-gate  *	      is a syntax error, return the line number in error.
78*7c478bd9Sstevel@tonic-gate  *
79*7c478bd9Sstevel@tonic-gate  *	args:	fd - file descriptor to push and pop from
80*7c478bd9Sstevel@tonic-gate  *		script - name of the configuration script
81*7c478bd9Sstevel@tonic-gate  *		rflag - restriction flag to determine what "commands"
82*7c478bd9Sstevel@tonic-gate  *			can be run
83*7c478bd9Sstevel@tonic-gate  */
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate int
86*7c478bd9Sstevel@tonic-gate doconfig(int fd, char *script, long rflag)
87*7c478bd9Sstevel@tonic-gate {
88*7c478bd9Sstevel@tonic-gate 	int line;		/* line counter */
89*7c478bd9Sstevel@tonic-gate 	struct stat statbuf;	/* place for stat */
90*7c478bd9Sstevel@tonic-gate 	FILE *fp;		/* file pointer for config script */
91*7c478bd9Sstevel@tonic-gate 	char buf[BUFSIZ + 1];	/* scratch buffer */
92*7c478bd9Sstevel@tonic-gate 	char *bp;		/* scratch pointer */
93*7c478bd9Sstevel@tonic-gate 	char *p;		/* scratch pointer */
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate 	/* if the script does not exist, then there is nothing to do */
96*7c478bd9Sstevel@tonic-gate 	trace3(TR_doconfig, 0, fd, rflag);
97*7c478bd9Sstevel@tonic-gate 	if (_STAT(script, &statbuf) < 0) {
98*7c478bd9Sstevel@tonic-gate 		trace1(TR_doconfig, 1);
99*7c478bd9Sstevel@tonic-gate 		return (0);
100*7c478bd9Sstevel@tonic-gate 	}
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate 	fp = fopen(script, "r");
103*7c478bd9Sstevel@tonic-gate 	if (fp == NULL) {
104*7c478bd9Sstevel@tonic-gate 		trace1(TR_doconfig, 1);
105*7c478bd9Sstevel@tonic-gate 		return (-1);
106*7c478bd9Sstevel@tonic-gate 	}
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 	line = 0;
109*7c478bd9Sstevel@tonic-gate 	while (fgets(buf, BUFSIZ, fp)) {
110*7c478bd9Sstevel@tonic-gate 		line++;
111*7c478bd9Sstevel@tonic-gate 		p = strchr(buf, '\n');
112*7c478bd9Sstevel@tonic-gate 		/* if no \n, then line is too long */
113*7c478bd9Sstevel@tonic-gate 		if (p == NULL) {
114*7c478bd9Sstevel@tonic-gate 			(void) fclose(fp);
115*7c478bd9Sstevel@tonic-gate 			trace1(TR_doconfig, 1);
116*7c478bd9Sstevel@tonic-gate 			return (line);
117*7c478bd9Sstevel@tonic-gate 		}
118*7c478bd9Sstevel@tonic-gate 		*p = '\0';
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate 		/* remove comments */
121*7c478bd9Sstevel@tonic-gate 		p = strchr(buf, COMMENT);
122*7c478bd9Sstevel@tonic-gate 		if (p)
123*7c478bd9Sstevel@tonic-gate 			*p = '\0';
124*7c478bd9Sstevel@tonic-gate 
125*7c478bd9Sstevel@tonic-gate 		/* remove leading whitespace */
126*7c478bd9Sstevel@tonic-gate 		bp = eatwhite(buf);
127*7c478bd9Sstevel@tonic-gate 		/* see if anything is left */
128*7c478bd9Sstevel@tonic-gate 		if (*bp == '\0')
129*7c478bd9Sstevel@tonic-gate 			continue;
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate 		/* remove trailing whitespace */
132*7c478bd9Sstevel@tonic-gate 		p = &buf[strlen(buf) - 1];
133*7c478bd9Sstevel@tonic-gate 		while (*p && isspace(*p))
134*7c478bd9Sstevel@tonic-gate 			*p-- = '\0';
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 		/* get the command */
137*7c478bd9Sstevel@tonic-gate 		p = bp;
138*7c478bd9Sstevel@tonic-gate 		while (*p && !isspace(*p))
139*7c478bd9Sstevel@tonic-gate 			p++;
140*7c478bd9Sstevel@tonic-gate 		if (*p)
141*7c478bd9Sstevel@tonic-gate 			*p++ = '\0';
142*7c478bd9Sstevel@tonic-gate 		/* skip any whitespace here too (between command and args) */
143*7c478bd9Sstevel@tonic-gate 		p = eatwhite(p);
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 		if (!strcmp(bp, "assign")) {
146*7c478bd9Sstevel@tonic-gate 			if ((rflag & NOASSIGN) || doassign(p)) {
147*7c478bd9Sstevel@tonic-gate 				(void) fclose(fp);
148*7c478bd9Sstevel@tonic-gate 				trace1(TR_doconfig, 1);
149*7c478bd9Sstevel@tonic-gate 				return (line);
150*7c478bd9Sstevel@tonic-gate 			}
151*7c478bd9Sstevel@tonic-gate 		} else if (!strcmp(bp, "push")) {
152*7c478bd9Sstevel@tonic-gate 			if (dopush(fd, p)) {
153*7c478bd9Sstevel@tonic-gate 				(void) fclose(fp);
154*7c478bd9Sstevel@tonic-gate 				trace1(TR_doconfig, 1);
155*7c478bd9Sstevel@tonic-gate 				return (line);
156*7c478bd9Sstevel@tonic-gate 			}
157*7c478bd9Sstevel@tonic-gate 		} else if (!strcmp(bp, "pop")) {
158*7c478bd9Sstevel@tonic-gate 			if (dopop(fd, p)) {
159*7c478bd9Sstevel@tonic-gate 				(void) fclose(fp);
160*7c478bd9Sstevel@tonic-gate 				trace1(TR_doconfig, 1);
161*7c478bd9Sstevel@tonic-gate 				return (line);
162*7c478bd9Sstevel@tonic-gate 			}
163*7c478bd9Sstevel@tonic-gate 		} else if (!strcmp(bp, "run")) {
164*7c478bd9Sstevel@tonic-gate 			if ((rflag & NORUN) || dorun(p, NOWAIT)) {
165*7c478bd9Sstevel@tonic-gate 				(void) fclose(fp);
166*7c478bd9Sstevel@tonic-gate 				trace1(TR_doconfig, 1);
167*7c478bd9Sstevel@tonic-gate 				return (line);
168*7c478bd9Sstevel@tonic-gate 			}
169*7c478bd9Sstevel@tonic-gate 		} else if (!strcmp(bp, "runwait")) {
170*7c478bd9Sstevel@tonic-gate 			if ((rflag & NORUN) || dorun(p, WAIT)) {
171*7c478bd9Sstevel@tonic-gate 				(void) fclose(fp);
172*7c478bd9Sstevel@tonic-gate 				trace1(TR_doconfig, 1);
173*7c478bd9Sstevel@tonic-gate 				return (line);
174*7c478bd9Sstevel@tonic-gate 			}
175*7c478bd9Sstevel@tonic-gate 		} else {
176*7c478bd9Sstevel@tonic-gate 			/* unknown command */
177*7c478bd9Sstevel@tonic-gate 			(void) fclose(fp);
178*7c478bd9Sstevel@tonic-gate 			trace1(TR_doconfig, 1);
179*7c478bd9Sstevel@tonic-gate 			return (line);
180*7c478bd9Sstevel@tonic-gate 		}
181*7c478bd9Sstevel@tonic-gate 	}
182*7c478bd9Sstevel@tonic-gate 	if (!feof(fp)) {
183*7c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
184*7c478bd9Sstevel@tonic-gate 		trace1(TR_doconfig, 1);
185*7c478bd9Sstevel@tonic-gate 		return (-1);
186*7c478bd9Sstevel@tonic-gate 	} else {
187*7c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
188*7c478bd9Sstevel@tonic-gate 		trace1(TR_doconfig, 1);
189*7c478bd9Sstevel@tonic-gate 		return (0);
190*7c478bd9Sstevel@tonic-gate 	}
191*7c478bd9Sstevel@tonic-gate }
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate /*
195*7c478bd9Sstevel@tonic-gate  * doassign - handle an `assign' command
196*7c478bd9Sstevel@tonic-gate  *
197*7c478bd9Sstevel@tonic-gate  *	args:	p - assignment string
198*7c478bd9Sstevel@tonic-gate  */
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate static int
202*7c478bd9Sstevel@tonic-gate doassign(char *p)
203*7c478bd9Sstevel@tonic-gate {
204*7c478bd9Sstevel@tonic-gate 	char *var;		/* environment variable to be assigned */
205*7c478bd9Sstevel@tonic-gate 	char val[BUFSIZ];	/* and the value to be assigned to it */
206*7c478bd9Sstevel@tonic-gate 	char scratch[BUFSIZ];	/* scratch buffer */
207*7c478bd9Sstevel@tonic-gate 	char delim;		/* delimiter char seen (for quoted strings ) */
208*7c478bd9Sstevel@tonic-gate 	char *tp;		/* scratch pointer */
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 	trace1(TR_doassign, 0);
211*7c478bd9Sstevel@tonic-gate 	if (*p == '\0') {
212*7c478bd9Sstevel@tonic-gate 		trace1(TR_doassign, 1);
213*7c478bd9Sstevel@tonic-gate 		return (-1);
214*7c478bd9Sstevel@tonic-gate 	}
215*7c478bd9Sstevel@tonic-gate 	var = p;
216*7c478bd9Sstevel@tonic-gate 	/* skip first token, but stop if we see a '=' */
217*7c478bd9Sstevel@tonic-gate 	while (*p && !isspace(*p) && (*p != '='))
218*7c478bd9Sstevel@tonic-gate 		p++;
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	/* if we found end of string, it's an error */
221*7c478bd9Sstevel@tonic-gate 	if (*p == '\0') {
222*7c478bd9Sstevel@tonic-gate 		trace1(TR_doassign, 1);
223*7c478bd9Sstevel@tonic-gate 		return (-1);
224*7c478bd9Sstevel@tonic-gate 	}
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate 	/* if we found a space, look for the '=', otherwise it's an error */
227*7c478bd9Sstevel@tonic-gate 	if (isspace(*p)) {
228*7c478bd9Sstevel@tonic-gate 		*p++ = '\0';
229*7c478bd9Sstevel@tonic-gate 		while (*p && isspace(*p))
230*7c478bd9Sstevel@tonic-gate 			p++;
231*7c478bd9Sstevel@tonic-gate 		if (*p == '\0') {
232*7c478bd9Sstevel@tonic-gate 			trace1(TR_doassign, 1);
233*7c478bd9Sstevel@tonic-gate 			return (-1);
234*7c478bd9Sstevel@tonic-gate 		}
235*7c478bd9Sstevel@tonic-gate 		if (*p == '=')
236*7c478bd9Sstevel@tonic-gate 			p++;
237*7c478bd9Sstevel@tonic-gate 		else {
238*7c478bd9Sstevel@tonic-gate 			trace1(TR_doassign, 1);
239*7c478bd9Sstevel@tonic-gate 			return (-1);
240*7c478bd9Sstevel@tonic-gate 		}
241*7c478bd9Sstevel@tonic-gate 	} else {
242*7c478bd9Sstevel@tonic-gate 		/* skip over '=' */
243*7c478bd9Sstevel@tonic-gate 		*p = '\0';
244*7c478bd9Sstevel@tonic-gate 		p++;
245*7c478bd9Sstevel@tonic-gate 	}
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate 	/* skip over any whitespace */
248*7c478bd9Sstevel@tonic-gate 	p = eatwhite(p);
249*7c478bd9Sstevel@tonic-gate 	if (*p == '\'' || *p == '"') {
250*7c478bd9Sstevel@tonic-gate 		/* handle quoted values */
251*7c478bd9Sstevel@tonic-gate 		delim = *p++;
252*7c478bd9Sstevel@tonic-gate 		tp = val;
253*7c478bd9Sstevel@tonic-gate 		for (;;) {
254*7c478bd9Sstevel@tonic-gate 			if (*p == '\0') {
255*7c478bd9Sstevel@tonic-gate 				trace1(TR_doassign, 1);
256*7c478bd9Sstevel@tonic-gate 				return (-1);
257*7c478bd9Sstevel@tonic-gate 			} else if (*p == delim) {
258*7c478bd9Sstevel@tonic-gate 				if (*(p - 1) != '\\')
259*7c478bd9Sstevel@tonic-gate 					break;
260*7c478bd9Sstevel@tonic-gate 				else
261*7c478bd9Sstevel@tonic-gate 					*(tp - 1) = *p++;
262*7c478bd9Sstevel@tonic-gate 			} else
263*7c478bd9Sstevel@tonic-gate 				*tp++ = *p++;
264*7c478bd9Sstevel@tonic-gate 		}
265*7c478bd9Sstevel@tonic-gate 		*tp = '\0';
266*7c478bd9Sstevel@tonic-gate 		/* these assignments make the comment below true (values of tp and p */
267*7c478bd9Sstevel@tonic-gate 		tp = ++p;
268*7c478bd9Sstevel@tonic-gate 		p = val;
269*7c478bd9Sstevel@tonic-gate 	} else {
270*7c478bd9Sstevel@tonic-gate 		tp = p;
271*7c478bd9Sstevel@tonic-gate 		/* look for end of token */
272*7c478bd9Sstevel@tonic-gate 		while (*tp && !isspace(*tp))
273*7c478bd9Sstevel@tonic-gate 			tp++;
274*7c478bd9Sstevel@tonic-gate 	}
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate /*
277*7c478bd9Sstevel@tonic-gate  * at this point, p points to the value, and tp points to the
278*7c478bd9Sstevel@tonic-gate  * end of the token.  check to make sure there is no garbage on
279*7c478bd9Sstevel@tonic-gate  * the end of the line
280*7c478bd9Sstevel@tonic-gate  */
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate 	if (*tp) {
283*7c478bd9Sstevel@tonic-gate 		trace1(TR_doassign, 1);
284*7c478bd9Sstevel@tonic-gate 		return (-1);
285*7c478bd9Sstevel@tonic-gate 	}
286*7c478bd9Sstevel@tonic-gate 	sprintf(scratch, "%s=%s", var, p);
287*7c478bd9Sstevel@tonic-gate 	/* note: need to malloc fresh space so putenv works */
288*7c478bd9Sstevel@tonic-gate 	tp = malloc(strlen(scratch) + 1);
289*7c478bd9Sstevel@tonic-gate 	if (tp == NULL) {
290*7c478bd9Sstevel@tonic-gate 		trace1(TR_doassign, 1);
291*7c478bd9Sstevel@tonic-gate 		return (-1);
292*7c478bd9Sstevel@tonic-gate 	}
293*7c478bd9Sstevel@tonic-gate 	strcpy(tp, scratch);
294*7c478bd9Sstevel@tonic-gate 	if (putenv(tp)) {
295*7c478bd9Sstevel@tonic-gate 		trace1(TR_doassign, 1);
296*7c478bd9Sstevel@tonic-gate 		return (-1);
297*7c478bd9Sstevel@tonic-gate 	} else {
298*7c478bd9Sstevel@tonic-gate 		trace1(TR_doassign, 1);
299*7c478bd9Sstevel@tonic-gate 		return (0);
300*7c478bd9Sstevel@tonic-gate 	}
301*7c478bd9Sstevel@tonic-gate }
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate /*
305*7c478bd9Sstevel@tonic-gate  * dopush - handle a `push' command
306*7c478bd9Sstevel@tonic-gate  *
307*7c478bd9Sstevel@tonic-gate  *	args:	fd - file descriptor to push on
308*7c478bd9Sstevel@tonic-gate  *		p - list of modules to push
309*7c478bd9Sstevel@tonic-gate  */
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate static int
313*7c478bd9Sstevel@tonic-gate dopush(int fd, char *p)
314*7c478bd9Sstevel@tonic-gate {
315*7c478bd9Sstevel@tonic-gate 	char *tp;	/* scratch pointer */
316*7c478bd9Sstevel@tonic-gate 	int i;		/* scratch variable */
317*7c478bd9Sstevel@tonic-gate 	int npush;	/* count # of modules pushed */
318*7c478bd9Sstevel@tonic-gate 
319*7c478bd9Sstevel@tonic-gate 	trace2(TR_dopush, 0, fd);
320*7c478bd9Sstevel@tonic-gate 	if (*p == '\0') {
321*7c478bd9Sstevel@tonic-gate 		trace1(TR_dopush, 1);
322*7c478bd9Sstevel@tonic-gate 		return (-1);
323*7c478bd9Sstevel@tonic-gate 	}
324*7c478bd9Sstevel@tonic-gate 	npush = 0;
325*7c478bd9Sstevel@tonic-gate 	for (;;) {
326*7c478bd9Sstevel@tonic-gate 		if (*p == '\0') {	/* found end of line */
327*7c478bd9Sstevel@tonic-gate 			trace1(TR_dopush, 1);
328*7c478bd9Sstevel@tonic-gate 			return (0);
329*7c478bd9Sstevel@tonic-gate 		}
330*7c478bd9Sstevel@tonic-gate 		p = eatwhite(p);
331*7c478bd9Sstevel@tonic-gate 		if (*p == '\0') {
332*7c478bd9Sstevel@tonic-gate 			trace1(TR_dopush, 1);
333*7c478bd9Sstevel@tonic-gate 			return (-1);
334*7c478bd9Sstevel@tonic-gate 		}
335*7c478bd9Sstevel@tonic-gate 		tp = p;
336*7c478bd9Sstevel@tonic-gate 		while (*tp && !isspace(*tp) && (*tp != ','))
337*7c478bd9Sstevel@tonic-gate 			tp++;
338*7c478bd9Sstevel@tonic-gate 		if (*tp)
339*7c478bd9Sstevel@tonic-gate 			*tp++ = '\0';
340*7c478bd9Sstevel@tonic-gate 		if (ioctl(fd, I_PUSH, p) < 0) {
341*7c478bd9Sstevel@tonic-gate 
342*7c478bd9Sstevel@tonic-gate /*
343*7c478bd9Sstevel@tonic-gate  * try to pop all that we've done, if pop fails it doesn't matter because
344*7c478bd9Sstevel@tonic-gate  * nothing can be done anyhow
345*7c478bd9Sstevel@tonic-gate  */
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < npush; ++i)
348*7c478bd9Sstevel@tonic-gate 				ioctl(fd, I_POP, 0);
349*7c478bd9Sstevel@tonic-gate 			trace1(TR_dopush, 1);
350*7c478bd9Sstevel@tonic-gate 			return (-1);
351*7c478bd9Sstevel@tonic-gate 		} else {
352*7c478bd9Sstevel@tonic-gate 			/* count the number of modules we've pushed */
353*7c478bd9Sstevel@tonic-gate 			npush++;
354*7c478bd9Sstevel@tonic-gate 			p = tp;
355*7c478bd9Sstevel@tonic-gate 		}
356*7c478bd9Sstevel@tonic-gate 	}
357*7c478bd9Sstevel@tonic-gate }
358*7c478bd9Sstevel@tonic-gate 
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate /*
361*7c478bd9Sstevel@tonic-gate  * dopop - handle a `pop' command
362*7c478bd9Sstevel@tonic-gate  *
363*7c478bd9Sstevel@tonic-gate  *	args:	fd - file descriptor to pop from
364*7c478bd9Sstevel@tonic-gate  *		p - name of module to pop to or ALL (null means pop top only)
365*7c478bd9Sstevel@tonic-gate  */
366*7c478bd9Sstevel@tonic-gate 
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate static int
369*7c478bd9Sstevel@tonic-gate dopop(int fd, char *p)
370*7c478bd9Sstevel@tonic-gate {
371*7c478bd9Sstevel@tonic-gate 	char *modp;		/* module name from argument to pop */
372*7c478bd9Sstevel@tonic-gate 	char buf[FMNAMESZ + 1];	/* scratch buffer */
373*7c478bd9Sstevel@tonic-gate 
374*7c478bd9Sstevel@tonic-gate 	trace2(TR_dopop, 0, fd);
375*7c478bd9Sstevel@tonic-gate 	if (*p == '\0') {
376*7c478bd9Sstevel@tonic-gate 		/* just a pop with no args */
377*7c478bd9Sstevel@tonic-gate 		if (ioctl(fd, I_POP, 0) < 0) {
378*7c478bd9Sstevel@tonic-gate 			trace1(TR_dopop, 1);
379*7c478bd9Sstevel@tonic-gate 			return (-1);
380*7c478bd9Sstevel@tonic-gate 		} else {
381*7c478bd9Sstevel@tonic-gate 			trace1(TR_dopop, 1);
382*7c478bd9Sstevel@tonic-gate 			return (0);
383*7c478bd9Sstevel@tonic-gate 		}
384*7c478bd9Sstevel@tonic-gate 	}
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate 	/* skip any whitespace in between */
387*7c478bd9Sstevel@tonic-gate 	p = eatwhite(p);
388*7c478bd9Sstevel@tonic-gate 	modp = p;
389*7c478bd9Sstevel@tonic-gate 	/* find end of module name */
390*7c478bd9Sstevel@tonic-gate 	while (*p && !isspace(*p))
391*7c478bd9Sstevel@tonic-gate 		p++;
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate 	if (*p) {	/* if not end of line, extra junk on line */
394*7c478bd9Sstevel@tonic-gate 		trace1(TR_dopop, 1);
395*7c478bd9Sstevel@tonic-gate 		return (-1);
396*7c478bd9Sstevel@tonic-gate 	}
397*7c478bd9Sstevel@tonic-gate 	if (!strcmp(modp, "ALL")) {
398*7c478bd9Sstevel@tonic-gate 		/* it's the magic name, pop them all */
399*7c478bd9Sstevel@tonic-gate 		while (ioctl(fd, I_POP, 0) == 0)
400*7c478bd9Sstevel@tonic-gate 			;
401*7c478bd9Sstevel@tonic-gate 		/* After all popped, we'll get an EINVAL, which is expected */
402*7c478bd9Sstevel@tonic-gate 		if (errno != EINVAL) {
403*7c478bd9Sstevel@tonic-gate 			trace1(TR_dopop, 1);
404*7c478bd9Sstevel@tonic-gate 			return (-1);
405*7c478bd9Sstevel@tonic-gate 		} else {
406*7c478bd9Sstevel@tonic-gate 			trace1(TR_dopop, 1);
407*7c478bd9Sstevel@tonic-gate 			return (0);
408*7c478bd9Sstevel@tonic-gate 		}
409*7c478bd9Sstevel@tonic-gate 	} else {
410*7c478bd9Sstevel@tonic-gate 		/* check to see if the named module is on the stream */
411*7c478bd9Sstevel@tonic-gate 		if (ioctl(fd, I_FIND, modp) != 1) {
412*7c478bd9Sstevel@tonic-gate 			trace1(TR_dopop, 1);
413*7c478bd9Sstevel@tonic-gate 			return (-1);
414*7c478bd9Sstevel@tonic-gate 		}
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate 		/* pop them until the right one is on top */
417*7c478bd9Sstevel@tonic-gate 		for (;;) {
418*7c478bd9Sstevel@tonic-gate 			if (ioctl(fd, I_LOOK, buf) < 0) {
419*7c478bd9Sstevel@tonic-gate 				trace1(TR_dopop, 1);
420*7c478bd9Sstevel@tonic-gate 				return (-1);
421*7c478bd9Sstevel@tonic-gate 			}
422*7c478bd9Sstevel@tonic-gate 			if (!strcmp(modp, buf)) {
423*7c478bd9Sstevel@tonic-gate 				trace1(TR_dopop, 1);
424*7c478bd9Sstevel@tonic-gate 				/* we're done */
425*7c478bd9Sstevel@tonic-gate 				return (0);
426*7c478bd9Sstevel@tonic-gate 			}
427*7c478bd9Sstevel@tonic-gate 			if (ioctl(fd, I_POP, 0) < 0) {
428*7c478bd9Sstevel@tonic-gate 				trace1(TR_dopop, 1);
429*7c478bd9Sstevel@tonic-gate 				return (-1);
430*7c478bd9Sstevel@tonic-gate 			}
431*7c478bd9Sstevel@tonic-gate 		}
432*7c478bd9Sstevel@tonic-gate 	}
433*7c478bd9Sstevel@tonic-gate }
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate 
436*7c478bd9Sstevel@tonic-gate /*
437*7c478bd9Sstevel@tonic-gate  * dorun - handle a `run' command
438*7c478bd9Sstevel@tonic-gate  *
439*7c478bd9Sstevel@tonic-gate  *	args:	p - command line to run
440*7c478bd9Sstevel@tonic-gate  *		waitflag - flag indicating whether a wait should be done
441*7c478bd9Sstevel@tonic-gate  */
442*7c478bd9Sstevel@tonic-gate 
443*7c478bd9Sstevel@tonic-gate 
444*7c478bd9Sstevel@tonic-gate static int
445*7c478bd9Sstevel@tonic-gate dorun(char *p, int waitflg)
446*7c478bd9Sstevel@tonic-gate {
447*7c478bd9Sstevel@tonic-gate 	char *tp;		/* scratch pointer */
448*7c478bd9Sstevel@tonic-gate 	char *ep;		/* scratch pointer (end of token) */
449*7c478bd9Sstevel@tonic-gate 	int nfiles;		/* # of possibly open files */
450*7c478bd9Sstevel@tonic-gate 	int i;			/* scratch variable */
451*7c478bd9Sstevel@tonic-gate 	char savech;		/* hold area */
452*7c478bd9Sstevel@tonic-gate 	int status;		/* return status from wait */
453*7c478bd9Sstevel@tonic-gate 	pid_t pid;		/* pid of child proc */
454*7c478bd9Sstevel@tonic-gate 	pid_t rpid;		/* returned pid from wait */
455*7c478bd9Sstevel@tonic-gate 	void (*func)();		/* return from signal */
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 	trace2(TR_dorun, 0, waitflg);
458*7c478bd9Sstevel@tonic-gate 	if (*p == '\0') {
459*7c478bd9Sstevel@tonic-gate 		trace1(TR_dorun, 1);
460*7c478bd9Sstevel@tonic-gate 		return (-1);
461*7c478bd9Sstevel@tonic-gate 	}
462*7c478bd9Sstevel@tonic-gate 
463*7c478bd9Sstevel@tonic-gate /*
464*7c478bd9Sstevel@tonic-gate  * get first token
465*7c478bd9Sstevel@tonic-gate  */
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate 	for (tp = p; *tp && !isspace(*tp); ++tp)
468*7c478bd9Sstevel@tonic-gate 		;
469*7c478bd9Sstevel@tonic-gate 	savech = '\0';
470*7c478bd9Sstevel@tonic-gate 	if (*tp) {
471*7c478bd9Sstevel@tonic-gate 		savech = *tp;
472*7c478bd9Sstevel@tonic-gate 		*tp = '\0';
473*7c478bd9Sstevel@tonic-gate 	}
474*7c478bd9Sstevel@tonic-gate 
475*7c478bd9Sstevel@tonic-gate /*
476*7c478bd9Sstevel@tonic-gate  * look for built-in's
477*7c478bd9Sstevel@tonic-gate  */
478*7c478bd9Sstevel@tonic-gate 
479*7c478bd9Sstevel@tonic-gate 	if (!strcmp(p, "cd")) {
480*7c478bd9Sstevel@tonic-gate 		*tp = savech;
481*7c478bd9Sstevel@tonic-gate 		tp = eatwhite(tp);
482*7c478bd9Sstevel@tonic-gate 		if (*tp == '\0')
483*7c478bd9Sstevel@tonic-gate 			/* if nothing there, try to cd to $HOME */
484*7c478bd9Sstevel@tonic-gate 			tp = getenv("HOME");
485*7c478bd9Sstevel@tonic-gate 		if (chdir(tp) < 0) {
486*7c478bd9Sstevel@tonic-gate 			trace1(TR_dorun, 1);
487*7c478bd9Sstevel@tonic-gate 			return (-1);
488*7c478bd9Sstevel@tonic-gate 		}
489*7c478bd9Sstevel@tonic-gate 	} else if (!strcmp(p, "ulimit")) {
490*7c478bd9Sstevel@tonic-gate 		*tp = savech;
491*7c478bd9Sstevel@tonic-gate 		tp = eatwhite(tp);
492*7c478bd9Sstevel@tonic-gate 		/* must have an argument */
493*7c478bd9Sstevel@tonic-gate 		if (*tp == '\0') {
494*7c478bd9Sstevel@tonic-gate 			trace1(TR_dorun, 1);
495*7c478bd9Sstevel@tonic-gate 			return (-1);
496*7c478bd9Sstevel@tonic-gate 		}
497*7c478bd9Sstevel@tonic-gate 		/* make sure nothing appears on line after arg */
498*7c478bd9Sstevel@tonic-gate 		for (ep = tp; *ep && !isspace(*ep); ++ep)
499*7c478bd9Sstevel@tonic-gate 			;
500*7c478bd9Sstevel@tonic-gate 		ep = eatwhite(ep);
501*7c478bd9Sstevel@tonic-gate 		if (*ep) {
502*7c478bd9Sstevel@tonic-gate 			trace1(TR_dorun, 1);
503*7c478bd9Sstevel@tonic-gate 			return (-1);
504*7c478bd9Sstevel@tonic-gate 		}
505*7c478bd9Sstevel@tonic-gate 		if (!isdigit(*tp)) {
506*7c478bd9Sstevel@tonic-gate 			trace1(TR_dorun, 1);
507*7c478bd9Sstevel@tonic-gate 			return (-1);
508*7c478bd9Sstevel@tonic-gate 		}
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate 		if (ulimit(2, atoi(tp)) < 0) {
511*7c478bd9Sstevel@tonic-gate 			trace1(TR_dorun, 1);
512*7c478bd9Sstevel@tonic-gate 			return (-1);
513*7c478bd9Sstevel@tonic-gate 		}
514*7c478bd9Sstevel@tonic-gate 	} else if (!strcmp(p, "umask")) {
515*7c478bd9Sstevel@tonic-gate 		*tp = savech;
516*7c478bd9Sstevel@tonic-gate 		tp = eatwhite(tp);
517*7c478bd9Sstevel@tonic-gate 		/* must have an argument */
518*7c478bd9Sstevel@tonic-gate 		if (*tp == '\0') {
519*7c478bd9Sstevel@tonic-gate 			trace1(TR_dorun, 1);
520*7c478bd9Sstevel@tonic-gate 			return (-1);
521*7c478bd9Sstevel@tonic-gate 		}
522*7c478bd9Sstevel@tonic-gate 		/* make sure nothing appears on line after arg */
523*7c478bd9Sstevel@tonic-gate 		for (ep = tp; *ep && !isspace(*ep); ++ep)
524*7c478bd9Sstevel@tonic-gate 			;
525*7c478bd9Sstevel@tonic-gate 		ep = eatwhite(ep);
526*7c478bd9Sstevel@tonic-gate 		if (*ep) {
527*7c478bd9Sstevel@tonic-gate 			trace1(TR_dorun, 1);
528*7c478bd9Sstevel@tonic-gate 			return (-1);
529*7c478bd9Sstevel@tonic-gate 		}
530*7c478bd9Sstevel@tonic-gate 		if (!isdigit(*tp)) {
531*7c478bd9Sstevel@tonic-gate 			trace1(TR_dorun, 1);
532*7c478bd9Sstevel@tonic-gate 			return (-1);
533*7c478bd9Sstevel@tonic-gate 		}
534*7c478bd9Sstevel@tonic-gate 		(void) umask(strtol(tp, NULL, 8));
535*7c478bd9Sstevel@tonic-gate 	} else {
536*7c478bd9Sstevel@tonic-gate 		/* not a built-in */
537*7c478bd9Sstevel@tonic-gate 		*tp = savech;
538*7c478bd9Sstevel@tonic-gate 		func = signal(SIGCLD, SIG_DFL);
539*7c478bd9Sstevel@tonic-gate 		if ((pid = fork()) < 0) {
540*7c478bd9Sstevel@tonic-gate 			signal(SIGCLD, func);
541*7c478bd9Sstevel@tonic-gate 			trace1(TR_dorun, 1);
542*7c478bd9Sstevel@tonic-gate 			return (-1);
543*7c478bd9Sstevel@tonic-gate 		} else if (pid) {
544*7c478bd9Sstevel@tonic-gate 			if (waitflg == WAIT) {
545*7c478bd9Sstevel@tonic-gate 				status = 0;
546*7c478bd9Sstevel@tonic-gate 				rpid = -1;
547*7c478bd9Sstevel@tonic-gate 				while (rpid != pid)
548*7c478bd9Sstevel@tonic-gate 					rpid = wait(&status);
549*7c478bd9Sstevel@tonic-gate 				if (status) {
550*7c478bd9Sstevel@tonic-gate 					/* child failed */
551*7c478bd9Sstevel@tonic-gate 					signal(SIGCLD, func);
552*7c478bd9Sstevel@tonic-gate 					trace1(TR_dorun, 1);
553*7c478bd9Sstevel@tonic-gate 					return (-1);
554*7c478bd9Sstevel@tonic-gate 				}
555*7c478bd9Sstevel@tonic-gate 			}
556*7c478bd9Sstevel@tonic-gate 			signal(SIGCLD, func);
557*7c478bd9Sstevel@tonic-gate 		} else {
558*7c478bd9Sstevel@tonic-gate 			/* set IFS for security */
559*7c478bd9Sstevel@tonic-gate 			(void) putenv("IFS=\" \"");
560*7c478bd9Sstevel@tonic-gate 			/*
561*7c478bd9Sstevel@tonic-gate 			 * need to close all files to prevent unauthorized
562*7c478bd9Sstevel@tonic-gate 			 * access in the children.  Setup stdin, stdout,
563*7c478bd9Sstevel@tonic-gate 			 * and stderr to /dev/null.
564*7c478bd9Sstevel@tonic-gate 			 */
565*7c478bd9Sstevel@tonic-gate 			nfiles = ulimit(4, 0);
566*7c478bd9Sstevel@tonic-gate 			closefrom(0);
567*7c478bd9Sstevel@tonic-gate 			/* stdin */
568*7c478bd9Sstevel@tonic-gate 			if (open("/dev/null", O_RDWR) != 0) {
569*7c478bd9Sstevel@tonic-gate 				trace1(TR_dorun, 1);
570*7c478bd9Sstevel@tonic-gate 				return (-1);
571*7c478bd9Sstevel@tonic-gate 			}
572*7c478bd9Sstevel@tonic-gate 			/* stdout */
573*7c478bd9Sstevel@tonic-gate 			if (dup(0) != 1) {
574*7c478bd9Sstevel@tonic-gate 				trace1(TR_dorun, 1);
575*7c478bd9Sstevel@tonic-gate 				return (-1);
576*7c478bd9Sstevel@tonic-gate 			}
577*7c478bd9Sstevel@tonic-gate 			/* stderr */
578*7c478bd9Sstevel@tonic-gate 			if (dup(0) != 2) {
579*7c478bd9Sstevel@tonic-gate 				trace1(TR_dorun, 1);
580*7c478bd9Sstevel@tonic-gate 				return (-1);
581*7c478bd9Sstevel@tonic-gate 			}
582*7c478bd9Sstevel@tonic-gate 			execle("/usr/bin/sh", "sh", "-c", p, 0, _environ);
583*7c478bd9Sstevel@tonic-gate 			/* if we get here, there is a problem - remember that
584*7c478bd9Sstevel@tonic-gate 			   this is the child */
585*7c478bd9Sstevel@tonic-gate 			trace1(TR_dorun, 1);
586*7c478bd9Sstevel@tonic-gate 			exit(1);
587*7c478bd9Sstevel@tonic-gate 		}
588*7c478bd9Sstevel@tonic-gate 	}
589*7c478bd9Sstevel@tonic-gate 	trace1(TR_dorun, 1);
590*7c478bd9Sstevel@tonic-gate 	return (0);
591*7c478bd9Sstevel@tonic-gate }
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate /*
595*7c478bd9Sstevel@tonic-gate  * eatwhite - swallow any leading whitespace, return pointer to first
596*7c478bd9Sstevel@tonic-gate  *	      non-white space character or to terminating null character
597*7c478bd9Sstevel@tonic-gate  *	      if nothing else is there
598*7c478bd9Sstevel@tonic-gate  *
599*7c478bd9Sstevel@tonic-gate  *	args:	p - string to parse
600*7c478bd9Sstevel@tonic-gate  */
601*7c478bd9Sstevel@tonic-gate 
602*7c478bd9Sstevel@tonic-gate static char *
603*7c478bd9Sstevel@tonic-gate eatwhite(char *p)
604*7c478bd9Sstevel@tonic-gate {
605*7c478bd9Sstevel@tonic-gate 	trace1(TR_eatwhite, 0);
606*7c478bd9Sstevel@tonic-gate 	while (*p && isspace(*p))
607*7c478bd9Sstevel@tonic-gate 		p++;
608*7c478bd9Sstevel@tonic-gate 	trace1(TR_eatwhite, 1);
609*7c478bd9Sstevel@tonic-gate 	return (p);
610*7c478bd9Sstevel@tonic-gate }
611