4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
40 #include <sys/types.h>
53 static char *eatwhite(char *);
54 static int doassign(char *);
55 static int dopush(int, char *);
56 static int dopop(int, char *);
57 static int dorun(char *, int);
60 * doconfig - the configuration script interpreter, if all is ok,
61 * return 0. If there is a "system" error, return -1.
62 * If there is an error performing a command, or there
63 * is a syntax error, return the line number in error.
65 * args: fd - file descriptor to push and pop from
66 * script - name of the configuration script
67 * rflag - restriction flag to determine what "commands"
72 doconfig(int fd
, char *script
, long rflag
)
74 int line
; /* line counter */
75 struct stat statbuf
; /* place for stat */
76 FILE *fp
; /* file pointer for config script */
77 char buf
[BUFSIZ
+ 1]; /* scratch buffer */
78 char *bp
; /* scratch pointer */
79 char *p
; /* scratch pointer */
81 /* if the script does not exist, then there is nothing to do */
82 if (stat(script
, &statbuf
) < 0)
85 fp
= fopen(script
, "rF");
90 while (fgets(buf
, BUFSIZ
, fp
)) {
92 p
= strchr(buf
, '\n');
93 /* if no \n, then line is too long */
100 /* remove comments */
101 p
= strchr(buf
, COMMENT
);
105 /* remove leading whitespace */
107 /* see if anything is left */
111 /* remove trailing whitespace */
112 p
= &buf
[strlen(buf
) - 1];
113 while (*p
&& isspace(*p
))
116 /* get the command */
118 while (*p
&& !isspace(*p
))
122 /* skip any whitespace here too (between command and args) */
125 if (strcmp(bp
, "assign") == 0) {
126 if ((rflag
& NOASSIGN
) || doassign(p
)) {
130 } else if (strcmp(bp
, "push") == 0) {
135 } else if (strcmp(bp
, "pop") == 0) {
140 } else if (strcmp(bp
, "run") == 0) {
141 if ((rflag
& NORUN
) || dorun(p
, NOWAIT
)) {
145 } else if (strcmp(bp
, "runwait") == 0) {
146 if ((rflag
& NORUN
) || dorun(p
, WAIT
)) {
151 /* unknown command */
166 * doassign - handle an `assign' command
168 * args: p - assignment string
175 char *var
; /* environment variable to be assigned */
176 char val
[BUFSIZ
]; /* and the value to be assigned to it */
177 char scratch
[BUFSIZ
]; /* scratch buffer */
178 char delim
; /* delimiter char seen (for quoted strings ) */
179 char *tp
; /* scratch pointer */
184 /* skip first token, but stop if we see a '=' */
185 while (*p
&& !isspace(*p
) && (*p
!= '='))
188 /* if we found end of string, it's an error */
192 /* if we found a space, look for the '=', otherwise it's an error */
195 while (*p
&& isspace(*p
))
209 /* skip over any whitespace */
211 if (*p
== '\'' || *p
== '"') {
212 /* handle quoted values */
218 } else if (*p
== delim
) {
219 if (*(p
- 1) != '\\')
228 * these assignments make the comment below true
229 * (values of tp and p
235 /* look for end of token */
236 while (*tp
&& !isspace(*tp
))
241 * at this point, p points to the value, and tp points to the
242 * end of the token. check to make sure there is no garbage on
243 * the end of the line
248 (void) snprintf(scratch
, sizeof (scratch
), "%s=%s", var
, p
);
249 /* note: need to malloc fresh space so putenv works */
250 tp
= malloc(strlen(scratch
) + 1);
253 (void) strcpy(tp
, scratch
);
261 * dopush - handle a `push' command
263 * args: fd - file descriptor to push on
264 * p - list of modules to push
269 dopush(int fd
, char *p
)
271 char *tp
; /* scratch pointer */
272 int i
; /* scratch variable */
273 int npush
; /* count # of modules pushed */
279 if (*p
== '\0') /* found end of line */
285 while (*tp
&& !isspace(*tp
) && (*tp
!= ','))
289 if (ioctl(fd
, I_PUSH
, p
) < 0) {
292 * try to pop all that we've done, if pop fails it doesn't matter because
293 * nothing can be done anyhow
296 for (i
= 0; i
< npush
; ++i
)
297 (void) ioctl(fd
, I_POP
, 0);
300 /* count the number of modules we've pushed */
308 * dopop - handle a `pop' command
310 * args: fd - file descriptor to pop from
311 * p - name of module to pop to or ALL (null means pop top only)
316 dopop(int fd
, char *p
)
318 char *modp
; /* module name from argument to pop */
319 char buf
[FMNAMESZ
+ 1]; /* scratch buffer */
322 /* just a pop with no args */
323 if (ioctl(fd
, I_POP
, 0) < 0)
328 /* skip any whitespace in between */
331 /* find end of module name */
332 while (*p
&& !isspace(*p
))
335 if (*p
) /* if not end of line, extra junk on line */
337 if (strcmp(modp
, "ALL") == 0) {
338 /* it's the magic name, pop them all */
339 while (ioctl(fd
, I_POP
, 0) == 0)
341 /* After all popped, we'll get an EINVAL, which is expected */
346 /* check to see if the named module is on the stream */
347 if (ioctl(fd
, I_FIND
, modp
) != 1)
350 /* pop them until the right one is on top */
352 if (ioctl(fd
, I_LOOK
, buf
) < 0)
354 if (strcmp(modp
, buf
) == 0)
357 if (ioctl(fd
, I_POP
, 0) < 0)
365 * dorun - handle a `run' command
367 * args: p - command line to run
368 * waitflag - flag indicating whether a wait should be done
373 dorun(char *p
, int waitflg
)
375 char *tp
; /* scratch pointer */
376 char *ep
; /* scratch pointer (end of token) */
377 char savech
; /* hold area */
378 int status
; /* return status from wait */
379 pid_t pid
; /* pid of child proc */
380 pid_t rpid
; /* returned pid from wait */
381 void (*func
)(); /* return from signal */
390 for (tp
= p
; *tp
&& !isspace(*tp
); ++tp
)
399 * look for built-in's
402 if (strcmp(p
, "cd") == 0) {
406 /* if nothing there, try to cd to $HOME */
410 } else if (strcmp(p
, "ulimit") == 0) {
413 /* must have an argument */
416 /* make sure nothing appears on line after arg */
417 for (ep
= tp
; *ep
&& !isspace(*ep
); ++ep
)
425 if (ulimit(2, atoi(tp
)) < 0)
427 } else if (strcmp(p
, "umask") == 0) {
430 /* must have an argument */
433 /* make sure nothing appears on line after arg */
434 for (ep
= tp
; *ep
&& !isspace(*ep
); ++ep
)
441 (void) umask(strtol(tp
, NULL
, 8));
445 func
= signal(SIGCLD
, SIG_DFL
);
446 if ((pid
= fork()) < 0) {
447 (void) signal(SIGCLD
, func
);
451 if (waitflg
== WAIT
) {
455 rpid
= wait(&status
);
458 (void) signal(SIGCLD
, func
);
462 (void) signal(SIGCLD
, func
);
464 /* set IFS for security */
465 (void) putenv("IFS=\" \"");
467 * need to close all files to prevent unauthorized
468 * access in the children. Setup stdin, stdout,
469 * and stderr to /dev/null.
473 if (open("/dev/null", O_RDWR
) != 0)
481 (void) execl("/usr/bin/sh", "sh", "-c", p
, NULL
);
483 * if we get here, there is a problem - remember that
494 * eatwhite - swallow any leading whitespace, return pointer to first
495 * non-white space character or to terminating null character
496 * if nothing else is there
498 * args: p - string to parse
504 while (*p
&& isspace(*p
))