17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 2261961e0fSrobinson 237c478bd9Sstevel@tonic-gate /* 24*e8031f0aSraf * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 317c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 327c478bd9Sstevel@tonic-gate 33*e8031f0aSraf #include "mt.h" 347c478bd9Sstevel@tonic-gate #include <stdio.h> 357c478bd9Sstevel@tonic-gate #include <string.h> 367c478bd9Sstevel@tonic-gate #include <stdlib.h> 377c478bd9Sstevel@tonic-gate #include <unistd.h> 387c478bd9Sstevel@tonic-gate #include <fcntl.h> 397c478bd9Sstevel@tonic-gate #include <ulimit.h> 407c478bd9Sstevel@tonic-gate #include <wait.h> 417c478bd9Sstevel@tonic-gate #include <sys/types.h> 427c478bd9Sstevel@tonic-gate #include <sys/stat.h> 437c478bd9Sstevel@tonic-gate #include <stropts.h> 447c478bd9Sstevel@tonic-gate #include <ctype.h> 457c478bd9Sstevel@tonic-gate #include <sys/conf.h> 467c478bd9Sstevel@tonic-gate #include <errno.h> 477c478bd9Sstevel@tonic-gate #include <signal.h> 487c478bd9Sstevel@tonic-gate #include "sac.h" 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate #define COMMENT '#' 517c478bd9Sstevel@tonic-gate #define NOWAIT 0 527c478bd9Sstevel@tonic-gate #define WAIT 1 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate extern char **_environ; 557c478bd9Sstevel@tonic-gate 5661961e0fSrobinson static char *eatwhite(char *); 5761961e0fSrobinson static int doassign(char *); 5861961e0fSrobinson static int dopush(int, char *); 5961961e0fSrobinson static int dopop(int, char *); 6061961e0fSrobinson static int dorun(char *, int); 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate /* 637c478bd9Sstevel@tonic-gate * doconfig - the configuration script interpreter, if all is ok, 647c478bd9Sstevel@tonic-gate * return 0. If there is a "system" error, return -1. 657c478bd9Sstevel@tonic-gate * If there is an error performing a command, or there 667c478bd9Sstevel@tonic-gate * is a syntax error, return the line number in error. 677c478bd9Sstevel@tonic-gate * 687c478bd9Sstevel@tonic-gate * args: fd - file descriptor to push and pop from 697c478bd9Sstevel@tonic-gate * script - name of the configuration script 707c478bd9Sstevel@tonic-gate * rflag - restriction flag to determine what "commands" 717c478bd9Sstevel@tonic-gate * can be run 727c478bd9Sstevel@tonic-gate */ 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate int 757c478bd9Sstevel@tonic-gate doconfig(int fd, char *script, long rflag) 767c478bd9Sstevel@tonic-gate { 777c478bd9Sstevel@tonic-gate int line; /* line counter */ 787c478bd9Sstevel@tonic-gate struct stat statbuf; /* place for stat */ 797c478bd9Sstevel@tonic-gate FILE *fp; /* file pointer for config script */ 807c478bd9Sstevel@tonic-gate char buf[BUFSIZ + 1]; /* scratch buffer */ 817c478bd9Sstevel@tonic-gate char *bp; /* scratch pointer */ 827c478bd9Sstevel@tonic-gate char *p; /* scratch pointer */ 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* if the script does not exist, then there is nothing to do */ 85*e8031f0aSraf if (stat(script, &statbuf) < 0) 867c478bd9Sstevel@tonic-gate return (0); 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate fp = fopen(script, "r"); 8961961e0fSrobinson if (fp == NULL) 907c478bd9Sstevel@tonic-gate return (-1); 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate line = 0; 937c478bd9Sstevel@tonic-gate while (fgets(buf, BUFSIZ, fp)) { 947c478bd9Sstevel@tonic-gate line++; 957c478bd9Sstevel@tonic-gate p = strchr(buf, '\n'); 967c478bd9Sstevel@tonic-gate /* if no \n, then line is too long */ 977c478bd9Sstevel@tonic-gate if (p == NULL) { 987c478bd9Sstevel@tonic-gate (void) fclose(fp); 997c478bd9Sstevel@tonic-gate return (line); 1007c478bd9Sstevel@tonic-gate } 1017c478bd9Sstevel@tonic-gate *p = '\0'; 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate /* remove comments */ 1047c478bd9Sstevel@tonic-gate p = strchr(buf, COMMENT); 1057c478bd9Sstevel@tonic-gate if (p) 1067c478bd9Sstevel@tonic-gate *p = '\0'; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate /* remove leading whitespace */ 1097c478bd9Sstevel@tonic-gate bp = eatwhite(buf); 1107c478bd9Sstevel@tonic-gate /* see if anything is left */ 1117c478bd9Sstevel@tonic-gate if (*bp == '\0') 1127c478bd9Sstevel@tonic-gate continue; 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate /* remove trailing whitespace */ 1157c478bd9Sstevel@tonic-gate p = &buf[strlen(buf) - 1]; 1167c478bd9Sstevel@tonic-gate while (*p && isspace(*p)) 1177c478bd9Sstevel@tonic-gate *p-- = '\0'; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate /* get the command */ 1207c478bd9Sstevel@tonic-gate p = bp; 1217c478bd9Sstevel@tonic-gate while (*p && !isspace(*p)) 1227c478bd9Sstevel@tonic-gate p++; 1237c478bd9Sstevel@tonic-gate if (*p) 1247c478bd9Sstevel@tonic-gate *p++ = '\0'; 1257c478bd9Sstevel@tonic-gate /* skip any whitespace here too (between command and args) */ 1267c478bd9Sstevel@tonic-gate p = eatwhite(p); 1277c478bd9Sstevel@tonic-gate 12861961e0fSrobinson if (strcmp(bp, "assign") == 0) { 1297c478bd9Sstevel@tonic-gate if ((rflag & NOASSIGN) || doassign(p)) { 1307c478bd9Sstevel@tonic-gate (void) fclose(fp); 1317c478bd9Sstevel@tonic-gate return (line); 1327c478bd9Sstevel@tonic-gate } 13361961e0fSrobinson } else if (strcmp(bp, "push") == 0) { 1347c478bd9Sstevel@tonic-gate if (dopush(fd, p)) { 1357c478bd9Sstevel@tonic-gate (void) fclose(fp); 1367c478bd9Sstevel@tonic-gate return (line); 1377c478bd9Sstevel@tonic-gate } 13861961e0fSrobinson } else if (strcmp(bp, "pop") == 0) { 1397c478bd9Sstevel@tonic-gate if (dopop(fd, p)) { 1407c478bd9Sstevel@tonic-gate (void) fclose(fp); 1417c478bd9Sstevel@tonic-gate return (line); 1427c478bd9Sstevel@tonic-gate } 14361961e0fSrobinson } else if (strcmp(bp, "run") == 0) { 1447c478bd9Sstevel@tonic-gate if ((rflag & NORUN) || dorun(p, NOWAIT)) { 1457c478bd9Sstevel@tonic-gate (void) fclose(fp); 1467c478bd9Sstevel@tonic-gate return (line); 1477c478bd9Sstevel@tonic-gate } 14861961e0fSrobinson } else if (strcmp(bp, "runwait") == 0) { 1497c478bd9Sstevel@tonic-gate if ((rflag & NORUN) || dorun(p, WAIT)) { 1507c478bd9Sstevel@tonic-gate (void) fclose(fp); 1517c478bd9Sstevel@tonic-gate return (line); 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate } else { 1547c478bd9Sstevel@tonic-gate /* unknown command */ 1557c478bd9Sstevel@tonic-gate (void) fclose(fp); 1567c478bd9Sstevel@tonic-gate return (line); 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate if (!feof(fp)) { 1607c478bd9Sstevel@tonic-gate (void) fclose(fp); 1617c478bd9Sstevel@tonic-gate return (-1); 1627c478bd9Sstevel@tonic-gate } 16361961e0fSrobinson (void) fclose(fp); 16461961e0fSrobinson return (0); 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate /* 1697c478bd9Sstevel@tonic-gate * doassign - handle an `assign' command 1707c478bd9Sstevel@tonic-gate * 1717c478bd9Sstevel@tonic-gate * args: p - assignment string 1727c478bd9Sstevel@tonic-gate */ 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate static int 1767c478bd9Sstevel@tonic-gate doassign(char *p) 1777c478bd9Sstevel@tonic-gate { 1787c478bd9Sstevel@tonic-gate char *var; /* environment variable to be assigned */ 1797c478bd9Sstevel@tonic-gate char val[BUFSIZ]; /* and the value to be assigned to it */ 1807c478bd9Sstevel@tonic-gate char scratch[BUFSIZ]; /* scratch buffer */ 1817c478bd9Sstevel@tonic-gate char delim; /* delimiter char seen (for quoted strings ) */ 1827c478bd9Sstevel@tonic-gate char *tp; /* scratch pointer */ 1837c478bd9Sstevel@tonic-gate 18461961e0fSrobinson if (*p == '\0') 1857c478bd9Sstevel@tonic-gate return (-1); 1867c478bd9Sstevel@tonic-gate var = p; 1877c478bd9Sstevel@tonic-gate /* skip first token, but stop if we see a '=' */ 1887c478bd9Sstevel@tonic-gate while (*p && !isspace(*p) && (*p != '=')) 1897c478bd9Sstevel@tonic-gate p++; 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* if we found end of string, it's an error */ 19261961e0fSrobinson if (*p == '\0') 1937c478bd9Sstevel@tonic-gate return (-1); 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate /* if we found a space, look for the '=', otherwise it's an error */ 1967c478bd9Sstevel@tonic-gate if (isspace(*p)) { 1977c478bd9Sstevel@tonic-gate *p++ = '\0'; 1987c478bd9Sstevel@tonic-gate while (*p && isspace(*p)) 1997c478bd9Sstevel@tonic-gate p++; 20061961e0fSrobinson if (*p == '\0') 2017c478bd9Sstevel@tonic-gate return (-1); 2027c478bd9Sstevel@tonic-gate if (*p == '=') 2037c478bd9Sstevel@tonic-gate p++; 20461961e0fSrobinson else 2057c478bd9Sstevel@tonic-gate return (-1); 2067c478bd9Sstevel@tonic-gate } else { 2077c478bd9Sstevel@tonic-gate /* skip over '=' */ 2087c478bd9Sstevel@tonic-gate *p = '\0'; 2097c478bd9Sstevel@tonic-gate p++; 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate /* skip over any whitespace */ 2137c478bd9Sstevel@tonic-gate p = eatwhite(p); 2147c478bd9Sstevel@tonic-gate if (*p == '\'' || *p == '"') { 2157c478bd9Sstevel@tonic-gate /* handle quoted values */ 2167c478bd9Sstevel@tonic-gate delim = *p++; 2177c478bd9Sstevel@tonic-gate tp = val; 2187c478bd9Sstevel@tonic-gate for (;;) { 2197c478bd9Sstevel@tonic-gate if (*p == '\0') { 2207c478bd9Sstevel@tonic-gate return (-1); 2217c478bd9Sstevel@tonic-gate } else if (*p == delim) { 2227c478bd9Sstevel@tonic-gate if (*(p - 1) != '\\') 2237c478bd9Sstevel@tonic-gate break; 2247c478bd9Sstevel@tonic-gate else 2257c478bd9Sstevel@tonic-gate *(tp - 1) = *p++; 2267c478bd9Sstevel@tonic-gate } else 2277c478bd9Sstevel@tonic-gate *tp++ = *p++; 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate *tp = '\0'; 23061961e0fSrobinson /* 23161961e0fSrobinson * these assignments make the comment below true 23261961e0fSrobinson * (values of tp and p 23361961e0fSrobinson */ 2347c478bd9Sstevel@tonic-gate tp = ++p; 2357c478bd9Sstevel@tonic-gate p = val; 2367c478bd9Sstevel@tonic-gate } else { 2377c478bd9Sstevel@tonic-gate tp = p; 2387c478bd9Sstevel@tonic-gate /* look for end of token */ 2397c478bd9Sstevel@tonic-gate while (*tp && !isspace(*tp)) 2407c478bd9Sstevel@tonic-gate tp++; 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate /* 2447c478bd9Sstevel@tonic-gate * at this point, p points to the value, and tp points to the 2457c478bd9Sstevel@tonic-gate * end of the token. check to make sure there is no garbage on 2467c478bd9Sstevel@tonic-gate * the end of the line 2477c478bd9Sstevel@tonic-gate */ 2487c478bd9Sstevel@tonic-gate 24961961e0fSrobinson if (*tp) 2507c478bd9Sstevel@tonic-gate return (-1); 25161961e0fSrobinson (void) snprintf(scratch, sizeof (scratch), "%s=%s", var, p); 2527c478bd9Sstevel@tonic-gate /* note: need to malloc fresh space so putenv works */ 2537c478bd9Sstevel@tonic-gate tp = malloc(strlen(scratch) + 1); 25461961e0fSrobinson if (tp == NULL) 2557c478bd9Sstevel@tonic-gate return (-1); 25661961e0fSrobinson (void) strcpy(tp, scratch); 25761961e0fSrobinson if (putenv(tp)) 2587c478bd9Sstevel@tonic-gate return (-1); 2597c478bd9Sstevel@tonic-gate return (0); 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate /* 2647c478bd9Sstevel@tonic-gate * dopush - handle a `push' command 2657c478bd9Sstevel@tonic-gate * 2667c478bd9Sstevel@tonic-gate * args: fd - file descriptor to push on 2677c478bd9Sstevel@tonic-gate * p - list of modules to push 2687c478bd9Sstevel@tonic-gate */ 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate static int 2727c478bd9Sstevel@tonic-gate dopush(int fd, char *p) 2737c478bd9Sstevel@tonic-gate { 2747c478bd9Sstevel@tonic-gate char *tp; /* scratch pointer */ 2757c478bd9Sstevel@tonic-gate int i; /* scratch variable */ 2767c478bd9Sstevel@tonic-gate int npush; /* count # of modules pushed */ 2777c478bd9Sstevel@tonic-gate 27861961e0fSrobinson if (*p == '\0') 2797c478bd9Sstevel@tonic-gate return (-1); 2807c478bd9Sstevel@tonic-gate npush = 0; 2817c478bd9Sstevel@tonic-gate for (;;) { 28261961e0fSrobinson if (*p == '\0') /* found end of line */ 2837c478bd9Sstevel@tonic-gate return (0); 2847c478bd9Sstevel@tonic-gate p = eatwhite(p); 28561961e0fSrobinson if (*p == '\0') 2867c478bd9Sstevel@tonic-gate return (-1); 2877c478bd9Sstevel@tonic-gate tp = p; 2887c478bd9Sstevel@tonic-gate while (*tp && !isspace(*tp) && (*tp != ',')) 2897c478bd9Sstevel@tonic-gate tp++; 2907c478bd9Sstevel@tonic-gate if (*tp) 2917c478bd9Sstevel@tonic-gate *tp++ = '\0'; 2927c478bd9Sstevel@tonic-gate if (ioctl(fd, I_PUSH, p) < 0) { 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate /* 2957c478bd9Sstevel@tonic-gate * try to pop all that we've done, if pop fails it doesn't matter because 2967c478bd9Sstevel@tonic-gate * nothing can be done anyhow 2977c478bd9Sstevel@tonic-gate */ 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate for (i = 0; i < npush; ++i) 30061961e0fSrobinson (void) ioctl(fd, I_POP, 0); 3017c478bd9Sstevel@tonic-gate return (-1); 30261961e0fSrobinson } 3037c478bd9Sstevel@tonic-gate /* count the number of modules we've pushed */ 3047c478bd9Sstevel@tonic-gate npush++; 3057c478bd9Sstevel@tonic-gate p = tp; 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate /* 3117c478bd9Sstevel@tonic-gate * dopop - handle a `pop' command 3127c478bd9Sstevel@tonic-gate * 3137c478bd9Sstevel@tonic-gate * args: fd - file descriptor to pop from 3147c478bd9Sstevel@tonic-gate * p - name of module to pop to or ALL (null means pop top only) 3157c478bd9Sstevel@tonic-gate */ 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate static int 3197c478bd9Sstevel@tonic-gate dopop(int fd, char *p) 3207c478bd9Sstevel@tonic-gate { 3217c478bd9Sstevel@tonic-gate char *modp; /* module name from argument to pop */ 3227c478bd9Sstevel@tonic-gate char buf[FMNAMESZ + 1]; /* scratch buffer */ 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate if (*p == '\0') { 3257c478bd9Sstevel@tonic-gate /* just a pop with no args */ 32661961e0fSrobinson if (ioctl(fd, I_POP, 0) < 0) 3277c478bd9Sstevel@tonic-gate return (-1); 3287c478bd9Sstevel@tonic-gate return (0); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate /* skip any whitespace in between */ 3327c478bd9Sstevel@tonic-gate p = eatwhite(p); 3337c478bd9Sstevel@tonic-gate modp = p; 3347c478bd9Sstevel@tonic-gate /* find end of module name */ 3357c478bd9Sstevel@tonic-gate while (*p && !isspace(*p)) 3367c478bd9Sstevel@tonic-gate p++; 3377c478bd9Sstevel@tonic-gate 33861961e0fSrobinson if (*p) /* if not end of line, extra junk on line */ 3397c478bd9Sstevel@tonic-gate return (-1); 34061961e0fSrobinson if (strcmp(modp, "ALL") == 0) { 3417c478bd9Sstevel@tonic-gate /* it's the magic name, pop them all */ 3427c478bd9Sstevel@tonic-gate while (ioctl(fd, I_POP, 0) == 0) 3437c478bd9Sstevel@tonic-gate ; 3447c478bd9Sstevel@tonic-gate /* After all popped, we'll get an EINVAL, which is expected */ 34561961e0fSrobinson if (errno != EINVAL) 3467c478bd9Sstevel@tonic-gate return (-1); 3477c478bd9Sstevel@tonic-gate return (0); 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate /* check to see if the named module is on the stream */ 35061961e0fSrobinson if (ioctl(fd, I_FIND, modp) != 1) 3517c478bd9Sstevel@tonic-gate return (-1); 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate /* pop them until the right one is on top */ 3547c478bd9Sstevel@tonic-gate for (;;) { 35561961e0fSrobinson if (ioctl(fd, I_LOOK, buf) < 0) 3567c478bd9Sstevel@tonic-gate return (-1); 35761961e0fSrobinson if (strcmp(modp, buf) == 0) 3587c478bd9Sstevel@tonic-gate /* we're done */ 3597c478bd9Sstevel@tonic-gate return (0); 36061961e0fSrobinson if (ioctl(fd, I_POP, 0) < 0) 3617c478bd9Sstevel@tonic-gate return (-1); 3627c478bd9Sstevel@tonic-gate } 36361961e0fSrobinson /* NOTREACHED */ 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate /* 3687c478bd9Sstevel@tonic-gate * dorun - handle a `run' command 3697c478bd9Sstevel@tonic-gate * 3707c478bd9Sstevel@tonic-gate * args: p - command line to run 3717c478bd9Sstevel@tonic-gate * waitflag - flag indicating whether a wait should be done 3727c478bd9Sstevel@tonic-gate */ 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate static int 3767c478bd9Sstevel@tonic-gate dorun(char *p, int waitflg) 3777c478bd9Sstevel@tonic-gate { 3787c478bd9Sstevel@tonic-gate char *tp; /* scratch pointer */ 3797c478bd9Sstevel@tonic-gate char *ep; /* scratch pointer (end of token) */ 3807c478bd9Sstevel@tonic-gate char savech; /* hold area */ 3817c478bd9Sstevel@tonic-gate int status; /* return status from wait */ 3827c478bd9Sstevel@tonic-gate pid_t pid; /* pid of child proc */ 3837c478bd9Sstevel@tonic-gate pid_t rpid; /* returned pid from wait */ 3847c478bd9Sstevel@tonic-gate void (*func)(); /* return from signal */ 3857c478bd9Sstevel@tonic-gate 38661961e0fSrobinson if (*p == '\0') 3877c478bd9Sstevel@tonic-gate return (-1); 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate /* 3907c478bd9Sstevel@tonic-gate * get first token 3917c478bd9Sstevel@tonic-gate */ 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate for (tp = p; *tp && !isspace(*tp); ++tp) 3947c478bd9Sstevel@tonic-gate ; 3957c478bd9Sstevel@tonic-gate savech = '\0'; 3967c478bd9Sstevel@tonic-gate if (*tp) { 3977c478bd9Sstevel@tonic-gate savech = *tp; 3987c478bd9Sstevel@tonic-gate *tp = '\0'; 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate /* 4027c478bd9Sstevel@tonic-gate * look for built-in's 4037c478bd9Sstevel@tonic-gate */ 4047c478bd9Sstevel@tonic-gate 40561961e0fSrobinson if (strcmp(p, "cd") == 0) { 4067c478bd9Sstevel@tonic-gate *tp = savech; 4077c478bd9Sstevel@tonic-gate tp = eatwhite(tp); 4087c478bd9Sstevel@tonic-gate if (*tp == '\0') 4097c478bd9Sstevel@tonic-gate /* if nothing there, try to cd to $HOME */ 4107c478bd9Sstevel@tonic-gate tp = getenv("HOME"); 41161961e0fSrobinson if (chdir(tp) < 0) 4127c478bd9Sstevel@tonic-gate return (-1); 41361961e0fSrobinson } else if (strcmp(p, "ulimit") == 0) { 4147c478bd9Sstevel@tonic-gate *tp = savech; 4157c478bd9Sstevel@tonic-gate tp = eatwhite(tp); 4167c478bd9Sstevel@tonic-gate /* must have an argument */ 41761961e0fSrobinson if (*tp == '\0') 4187c478bd9Sstevel@tonic-gate return (-1); 4197c478bd9Sstevel@tonic-gate /* make sure nothing appears on line after arg */ 4207c478bd9Sstevel@tonic-gate for (ep = tp; *ep && !isspace(*ep); ++ep) 4217c478bd9Sstevel@tonic-gate ; 4227c478bd9Sstevel@tonic-gate ep = eatwhite(ep); 42361961e0fSrobinson if (*ep) 4247c478bd9Sstevel@tonic-gate return (-1); 42561961e0fSrobinson if (!isdigit(*tp)) 4267c478bd9Sstevel@tonic-gate return (-1); 4277c478bd9Sstevel@tonic-gate 42861961e0fSrobinson if (ulimit(2, atoi(tp)) < 0) 4297c478bd9Sstevel@tonic-gate return (-1); 43061961e0fSrobinson } else if (strcmp(p, "umask") == 0) { 4317c478bd9Sstevel@tonic-gate *tp = savech; 4327c478bd9Sstevel@tonic-gate tp = eatwhite(tp); 4337c478bd9Sstevel@tonic-gate /* must have an argument */ 43461961e0fSrobinson if (*tp == '\0') 4357c478bd9Sstevel@tonic-gate return (-1); 4367c478bd9Sstevel@tonic-gate /* make sure nothing appears on line after arg */ 4377c478bd9Sstevel@tonic-gate for (ep = tp; *ep && !isspace(*ep); ++ep) 4387c478bd9Sstevel@tonic-gate ; 4397c478bd9Sstevel@tonic-gate ep = eatwhite(ep); 44061961e0fSrobinson if (*ep) 4417c478bd9Sstevel@tonic-gate return (-1); 44261961e0fSrobinson if (!isdigit(*tp)) 4437c478bd9Sstevel@tonic-gate return (-1); 4447c478bd9Sstevel@tonic-gate (void) umask(strtol(tp, NULL, 8)); 4457c478bd9Sstevel@tonic-gate } else { 4467c478bd9Sstevel@tonic-gate /* not a built-in */ 4477c478bd9Sstevel@tonic-gate *tp = savech; 4487c478bd9Sstevel@tonic-gate func = signal(SIGCLD, SIG_DFL); 4497c478bd9Sstevel@tonic-gate if ((pid = fork()) < 0) { 45061961e0fSrobinson (void) signal(SIGCLD, func); 4517c478bd9Sstevel@tonic-gate return (-1); 45261961e0fSrobinson } 45361961e0fSrobinson if (pid) { 4547c478bd9Sstevel@tonic-gate if (waitflg == WAIT) { 4557c478bd9Sstevel@tonic-gate status = 0; 4567c478bd9Sstevel@tonic-gate rpid = -1; 4577c478bd9Sstevel@tonic-gate while (rpid != pid) 4587c478bd9Sstevel@tonic-gate rpid = wait(&status); 4597c478bd9Sstevel@tonic-gate if (status) { 4607c478bd9Sstevel@tonic-gate /* child failed */ 46161961e0fSrobinson (void) signal(SIGCLD, func); 4627c478bd9Sstevel@tonic-gate return (-1); 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate } 46561961e0fSrobinson (void) signal(SIGCLD, func); 4667c478bd9Sstevel@tonic-gate } else { 4677c478bd9Sstevel@tonic-gate /* set IFS for security */ 4687c478bd9Sstevel@tonic-gate (void) putenv("IFS=\" \""); 4697c478bd9Sstevel@tonic-gate /* 4707c478bd9Sstevel@tonic-gate * need to close all files to prevent unauthorized 4717c478bd9Sstevel@tonic-gate * access in the children. Setup stdin, stdout, 4727c478bd9Sstevel@tonic-gate * and stderr to /dev/null. 4737c478bd9Sstevel@tonic-gate */ 4747c478bd9Sstevel@tonic-gate closefrom(0); 4757c478bd9Sstevel@tonic-gate /* stdin */ 47661961e0fSrobinson if (open("/dev/null", O_RDWR) != 0) 4777c478bd9Sstevel@tonic-gate return (-1); 4787c478bd9Sstevel@tonic-gate /* stdout */ 47961961e0fSrobinson if (dup(0) != 1) 4807c478bd9Sstevel@tonic-gate return (-1); 4817c478bd9Sstevel@tonic-gate /* stderr */ 48261961e0fSrobinson if (dup(0) != 2) 4837c478bd9Sstevel@tonic-gate return (-1); 48461961e0fSrobinson (void) execle("/usr/bin/sh", "sh", "-c", 48561961e0fSrobinson p, 0, _environ); 48661961e0fSrobinson /* 48761961e0fSrobinson * if we get here, there is a problem - remember that 48861961e0fSrobinson * this is the child 48961961e0fSrobinson */ 4907c478bd9Sstevel@tonic-gate exit(1); 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate return (0); 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate /* 4987c478bd9Sstevel@tonic-gate * eatwhite - swallow any leading whitespace, return pointer to first 4997c478bd9Sstevel@tonic-gate * non-white space character or to terminating null character 5007c478bd9Sstevel@tonic-gate * if nothing else is there 5017c478bd9Sstevel@tonic-gate * 5027c478bd9Sstevel@tonic-gate * args: p - string to parse 5037c478bd9Sstevel@tonic-gate */ 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate static char * 5067c478bd9Sstevel@tonic-gate eatwhite(char *p) 5077c478bd9Sstevel@tonic-gate { 5087c478bd9Sstevel@tonic-gate while (*p && isspace(*p)) 5097c478bd9Sstevel@tonic-gate p++; 5107c478bd9Sstevel@tonic-gate return (p); 5117c478bd9Sstevel@tonic-gate } 512