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 5004388ebScasper * Common Development and Distribution License (the "License"). 6004388ebScasper * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 2161961e0fSrobinson 227c478bd9Sstevel@tonic-gate /* 23*7257d1b4Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 287c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate 30*7257d1b4Sraf #pragma ident "%Z%%M% %I% %E% SMI" 31*7257d1b4Sraf 32e8031f0aSraf #include "mt.h" 337c478bd9Sstevel@tonic-gate #include <stdio.h> 347c478bd9Sstevel@tonic-gate #include <string.h> 357c478bd9Sstevel@tonic-gate #include <stdlib.h> 367c478bd9Sstevel@tonic-gate #include <unistd.h> 377c478bd9Sstevel@tonic-gate #include <fcntl.h> 387c478bd9Sstevel@tonic-gate #include <ulimit.h> 397c478bd9Sstevel@tonic-gate #include <wait.h> 407c478bd9Sstevel@tonic-gate #include <sys/types.h> 417c478bd9Sstevel@tonic-gate #include <sys/stat.h> 427c478bd9Sstevel@tonic-gate #include <stropts.h> 437c478bd9Sstevel@tonic-gate #include <ctype.h> 447c478bd9Sstevel@tonic-gate #include <sys/conf.h> 457c478bd9Sstevel@tonic-gate #include <errno.h> 467c478bd9Sstevel@tonic-gate #include <signal.h> 477c478bd9Sstevel@tonic-gate #include "sac.h" 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #define COMMENT '#' 507c478bd9Sstevel@tonic-gate #define NOWAIT 0 517c478bd9Sstevel@tonic-gate #define WAIT 1 527c478bd9Sstevel@tonic-gate 5361961e0fSrobinson static char *eatwhite(char *); 5461961e0fSrobinson static int doassign(char *); 5561961e0fSrobinson static int dopush(int, char *); 5661961e0fSrobinson static int dopop(int, char *); 5761961e0fSrobinson static int dorun(char *, int); 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate /* 607c478bd9Sstevel@tonic-gate * doconfig - the configuration script interpreter, if all is ok, 617c478bd9Sstevel@tonic-gate * return 0. If there is a "system" error, return -1. 627c478bd9Sstevel@tonic-gate * If there is an error performing a command, or there 637c478bd9Sstevel@tonic-gate * is a syntax error, return the line number in error. 647c478bd9Sstevel@tonic-gate * 657c478bd9Sstevel@tonic-gate * args: fd - file descriptor to push and pop from 667c478bd9Sstevel@tonic-gate * script - name of the configuration script 677c478bd9Sstevel@tonic-gate * rflag - restriction flag to determine what "commands" 687c478bd9Sstevel@tonic-gate * can be run 697c478bd9Sstevel@tonic-gate */ 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate int 727c478bd9Sstevel@tonic-gate doconfig(int fd, char *script, long rflag) 737c478bd9Sstevel@tonic-gate { 747c478bd9Sstevel@tonic-gate int line; /* line counter */ 757c478bd9Sstevel@tonic-gate struct stat statbuf; /* place for stat */ 767c478bd9Sstevel@tonic-gate FILE *fp; /* file pointer for config script */ 777c478bd9Sstevel@tonic-gate char buf[BUFSIZ + 1]; /* scratch buffer */ 787c478bd9Sstevel@tonic-gate char *bp; /* scratch pointer */ 797c478bd9Sstevel@tonic-gate char *p; /* scratch pointer */ 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate /* if the script does not exist, then there is nothing to do */ 82e8031f0aSraf if (stat(script, &statbuf) < 0) 837c478bd9Sstevel@tonic-gate return (0); 847c478bd9Sstevel@tonic-gate 85004388ebScasper fp = fopen(script, "rF"); 8661961e0fSrobinson if (fp == NULL) 877c478bd9Sstevel@tonic-gate return (-1); 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate line = 0; 907c478bd9Sstevel@tonic-gate while (fgets(buf, BUFSIZ, fp)) { 917c478bd9Sstevel@tonic-gate line++; 927c478bd9Sstevel@tonic-gate p = strchr(buf, '\n'); 937c478bd9Sstevel@tonic-gate /* if no \n, then line is too long */ 947c478bd9Sstevel@tonic-gate if (p == NULL) { 957c478bd9Sstevel@tonic-gate (void) fclose(fp); 967c478bd9Sstevel@tonic-gate return (line); 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate *p = '\0'; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate /* remove comments */ 1017c478bd9Sstevel@tonic-gate p = strchr(buf, COMMENT); 1027c478bd9Sstevel@tonic-gate if (p) 1037c478bd9Sstevel@tonic-gate *p = '\0'; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /* remove leading whitespace */ 1067c478bd9Sstevel@tonic-gate bp = eatwhite(buf); 1077c478bd9Sstevel@tonic-gate /* see if anything is left */ 1087c478bd9Sstevel@tonic-gate if (*bp == '\0') 1097c478bd9Sstevel@tonic-gate continue; 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* remove trailing whitespace */ 1127c478bd9Sstevel@tonic-gate p = &buf[strlen(buf) - 1]; 1137c478bd9Sstevel@tonic-gate while (*p && isspace(*p)) 1147c478bd9Sstevel@tonic-gate *p-- = '\0'; 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate /* get the command */ 1177c478bd9Sstevel@tonic-gate p = bp; 1187c478bd9Sstevel@tonic-gate while (*p && !isspace(*p)) 1197c478bd9Sstevel@tonic-gate p++; 1207c478bd9Sstevel@tonic-gate if (*p) 1217c478bd9Sstevel@tonic-gate *p++ = '\0'; 1227c478bd9Sstevel@tonic-gate /* skip any whitespace here too (between command and args) */ 1237c478bd9Sstevel@tonic-gate p = eatwhite(p); 1247c478bd9Sstevel@tonic-gate 12561961e0fSrobinson if (strcmp(bp, "assign") == 0) { 1267c478bd9Sstevel@tonic-gate if ((rflag & NOASSIGN) || doassign(p)) { 1277c478bd9Sstevel@tonic-gate (void) fclose(fp); 1287c478bd9Sstevel@tonic-gate return (line); 1297c478bd9Sstevel@tonic-gate } 13061961e0fSrobinson } else if (strcmp(bp, "push") == 0) { 1317c478bd9Sstevel@tonic-gate if (dopush(fd, p)) { 1327c478bd9Sstevel@tonic-gate (void) fclose(fp); 1337c478bd9Sstevel@tonic-gate return (line); 1347c478bd9Sstevel@tonic-gate } 13561961e0fSrobinson } else if (strcmp(bp, "pop") == 0) { 1367c478bd9Sstevel@tonic-gate if (dopop(fd, p)) { 1377c478bd9Sstevel@tonic-gate (void) fclose(fp); 1387c478bd9Sstevel@tonic-gate return (line); 1397c478bd9Sstevel@tonic-gate } 14061961e0fSrobinson } else if (strcmp(bp, "run") == 0) { 1417c478bd9Sstevel@tonic-gate if ((rflag & NORUN) || dorun(p, NOWAIT)) { 1427c478bd9Sstevel@tonic-gate (void) fclose(fp); 1437c478bd9Sstevel@tonic-gate return (line); 1447c478bd9Sstevel@tonic-gate } 14561961e0fSrobinson } else if (strcmp(bp, "runwait") == 0) { 1467c478bd9Sstevel@tonic-gate if ((rflag & NORUN) || dorun(p, WAIT)) { 1477c478bd9Sstevel@tonic-gate (void) fclose(fp); 1487c478bd9Sstevel@tonic-gate return (line); 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate } else { 1517c478bd9Sstevel@tonic-gate /* unknown command */ 1527c478bd9Sstevel@tonic-gate (void) fclose(fp); 1537c478bd9Sstevel@tonic-gate return (line); 1547c478bd9Sstevel@tonic-gate } 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate if (!feof(fp)) { 1577c478bd9Sstevel@tonic-gate (void) fclose(fp); 1587c478bd9Sstevel@tonic-gate return (-1); 1597c478bd9Sstevel@tonic-gate } 16061961e0fSrobinson (void) fclose(fp); 16161961e0fSrobinson return (0); 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate /* 1667c478bd9Sstevel@tonic-gate * doassign - handle an `assign' command 1677c478bd9Sstevel@tonic-gate * 1687c478bd9Sstevel@tonic-gate * args: p - assignment string 1697c478bd9Sstevel@tonic-gate */ 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate static int 1737c478bd9Sstevel@tonic-gate doassign(char *p) 1747c478bd9Sstevel@tonic-gate { 1757c478bd9Sstevel@tonic-gate char *var; /* environment variable to be assigned */ 1767c478bd9Sstevel@tonic-gate char val[BUFSIZ]; /* and the value to be assigned to it */ 1777c478bd9Sstevel@tonic-gate char scratch[BUFSIZ]; /* scratch buffer */ 1787c478bd9Sstevel@tonic-gate char delim; /* delimiter char seen (for quoted strings ) */ 1797c478bd9Sstevel@tonic-gate char *tp; /* scratch pointer */ 1807c478bd9Sstevel@tonic-gate 18161961e0fSrobinson if (*p == '\0') 1827c478bd9Sstevel@tonic-gate return (-1); 1837c478bd9Sstevel@tonic-gate var = p; 1847c478bd9Sstevel@tonic-gate /* skip first token, but stop if we see a '=' */ 1857c478bd9Sstevel@tonic-gate while (*p && !isspace(*p) && (*p != '=')) 1867c478bd9Sstevel@tonic-gate p++; 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* if we found end of string, it's an error */ 18961961e0fSrobinson if (*p == '\0') 1907c478bd9Sstevel@tonic-gate return (-1); 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate /* if we found a space, look for the '=', otherwise it's an error */ 1937c478bd9Sstevel@tonic-gate if (isspace(*p)) { 1947c478bd9Sstevel@tonic-gate *p++ = '\0'; 1957c478bd9Sstevel@tonic-gate while (*p && isspace(*p)) 1967c478bd9Sstevel@tonic-gate p++; 19761961e0fSrobinson if (*p == '\0') 1987c478bd9Sstevel@tonic-gate return (-1); 1997c478bd9Sstevel@tonic-gate if (*p == '=') 2007c478bd9Sstevel@tonic-gate p++; 20161961e0fSrobinson else 2027c478bd9Sstevel@tonic-gate return (-1); 2037c478bd9Sstevel@tonic-gate } else { 2047c478bd9Sstevel@tonic-gate /* skip over '=' */ 2057c478bd9Sstevel@tonic-gate *p = '\0'; 2067c478bd9Sstevel@tonic-gate p++; 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate /* skip over any whitespace */ 2107c478bd9Sstevel@tonic-gate p = eatwhite(p); 2117c478bd9Sstevel@tonic-gate if (*p == '\'' || *p == '"') { 2127c478bd9Sstevel@tonic-gate /* handle quoted values */ 2137c478bd9Sstevel@tonic-gate delim = *p++; 2147c478bd9Sstevel@tonic-gate tp = val; 2157c478bd9Sstevel@tonic-gate for (;;) { 2167c478bd9Sstevel@tonic-gate if (*p == '\0') { 2177c478bd9Sstevel@tonic-gate return (-1); 2187c478bd9Sstevel@tonic-gate } else if (*p == delim) { 2197c478bd9Sstevel@tonic-gate if (*(p - 1) != '\\') 2207c478bd9Sstevel@tonic-gate break; 2217c478bd9Sstevel@tonic-gate else 2227c478bd9Sstevel@tonic-gate *(tp - 1) = *p++; 2237c478bd9Sstevel@tonic-gate } else 2247c478bd9Sstevel@tonic-gate *tp++ = *p++; 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate *tp = '\0'; 22761961e0fSrobinson /* 22861961e0fSrobinson * these assignments make the comment below true 22961961e0fSrobinson * (values of tp and p 23061961e0fSrobinson */ 2317c478bd9Sstevel@tonic-gate tp = ++p; 2327c478bd9Sstevel@tonic-gate p = val; 2337c478bd9Sstevel@tonic-gate } else { 2347c478bd9Sstevel@tonic-gate tp = p; 2357c478bd9Sstevel@tonic-gate /* look for end of token */ 2367c478bd9Sstevel@tonic-gate while (*tp && !isspace(*tp)) 2377c478bd9Sstevel@tonic-gate tp++; 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate /* 2417c478bd9Sstevel@tonic-gate * at this point, p points to the value, and tp points to the 2427c478bd9Sstevel@tonic-gate * end of the token. check to make sure there is no garbage on 2437c478bd9Sstevel@tonic-gate * the end of the line 2447c478bd9Sstevel@tonic-gate */ 2457c478bd9Sstevel@tonic-gate 24661961e0fSrobinson if (*tp) 2477c478bd9Sstevel@tonic-gate return (-1); 24861961e0fSrobinson (void) snprintf(scratch, sizeof (scratch), "%s=%s", var, p); 2497c478bd9Sstevel@tonic-gate /* note: need to malloc fresh space so putenv works */ 2507c478bd9Sstevel@tonic-gate tp = malloc(strlen(scratch) + 1); 25161961e0fSrobinson if (tp == NULL) 2527c478bd9Sstevel@tonic-gate return (-1); 25361961e0fSrobinson (void) strcpy(tp, scratch); 25461961e0fSrobinson if (putenv(tp)) 2557c478bd9Sstevel@tonic-gate return (-1); 2567c478bd9Sstevel@tonic-gate return (0); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate /* 2617c478bd9Sstevel@tonic-gate * dopush - handle a `push' command 2627c478bd9Sstevel@tonic-gate * 2637c478bd9Sstevel@tonic-gate * args: fd - file descriptor to push on 2647c478bd9Sstevel@tonic-gate * p - list of modules to push 2657c478bd9Sstevel@tonic-gate */ 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate static int 2697c478bd9Sstevel@tonic-gate dopush(int fd, char *p) 2707c478bd9Sstevel@tonic-gate { 2717c478bd9Sstevel@tonic-gate char *tp; /* scratch pointer */ 2727c478bd9Sstevel@tonic-gate int i; /* scratch variable */ 2737c478bd9Sstevel@tonic-gate int npush; /* count # of modules pushed */ 2747c478bd9Sstevel@tonic-gate 27561961e0fSrobinson if (*p == '\0') 2767c478bd9Sstevel@tonic-gate return (-1); 2777c478bd9Sstevel@tonic-gate npush = 0; 2787c478bd9Sstevel@tonic-gate for (;;) { 27961961e0fSrobinson if (*p == '\0') /* found end of line */ 2807c478bd9Sstevel@tonic-gate return (0); 2817c478bd9Sstevel@tonic-gate p = eatwhite(p); 28261961e0fSrobinson if (*p == '\0') 2837c478bd9Sstevel@tonic-gate return (-1); 2847c478bd9Sstevel@tonic-gate tp = p; 2857c478bd9Sstevel@tonic-gate while (*tp && !isspace(*tp) && (*tp != ',')) 2867c478bd9Sstevel@tonic-gate tp++; 2877c478bd9Sstevel@tonic-gate if (*tp) 2887c478bd9Sstevel@tonic-gate *tp++ = '\0'; 2897c478bd9Sstevel@tonic-gate if (ioctl(fd, I_PUSH, p) < 0) { 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate /* 2927c478bd9Sstevel@tonic-gate * try to pop all that we've done, if pop fails it doesn't matter because 2937c478bd9Sstevel@tonic-gate * nothing can be done anyhow 2947c478bd9Sstevel@tonic-gate */ 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate for (i = 0; i < npush; ++i) 29761961e0fSrobinson (void) ioctl(fd, I_POP, 0); 2987c478bd9Sstevel@tonic-gate return (-1); 29961961e0fSrobinson } 3007c478bd9Sstevel@tonic-gate /* count the number of modules we've pushed */ 3017c478bd9Sstevel@tonic-gate npush++; 3027c478bd9Sstevel@tonic-gate p = tp; 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate /* 3087c478bd9Sstevel@tonic-gate * dopop - handle a `pop' command 3097c478bd9Sstevel@tonic-gate * 3107c478bd9Sstevel@tonic-gate * args: fd - file descriptor to pop from 3117c478bd9Sstevel@tonic-gate * p - name of module to pop to or ALL (null means pop top only) 3127c478bd9Sstevel@tonic-gate */ 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate static int 3167c478bd9Sstevel@tonic-gate dopop(int fd, char *p) 3177c478bd9Sstevel@tonic-gate { 3187c478bd9Sstevel@tonic-gate char *modp; /* module name from argument to pop */ 3197c478bd9Sstevel@tonic-gate char buf[FMNAMESZ + 1]; /* scratch buffer */ 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate if (*p == '\0') { 3227c478bd9Sstevel@tonic-gate /* just a pop with no args */ 32361961e0fSrobinson if (ioctl(fd, I_POP, 0) < 0) 3247c478bd9Sstevel@tonic-gate return (-1); 3257c478bd9Sstevel@tonic-gate return (0); 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate /* skip any whitespace in between */ 3297c478bd9Sstevel@tonic-gate p = eatwhite(p); 3307c478bd9Sstevel@tonic-gate modp = p; 3317c478bd9Sstevel@tonic-gate /* find end of module name */ 3327c478bd9Sstevel@tonic-gate while (*p && !isspace(*p)) 3337c478bd9Sstevel@tonic-gate p++; 3347c478bd9Sstevel@tonic-gate 33561961e0fSrobinson if (*p) /* if not end of line, extra junk on line */ 3367c478bd9Sstevel@tonic-gate return (-1); 33761961e0fSrobinson if (strcmp(modp, "ALL") == 0) { 3387c478bd9Sstevel@tonic-gate /* it's the magic name, pop them all */ 3397c478bd9Sstevel@tonic-gate while (ioctl(fd, I_POP, 0) == 0) 3407c478bd9Sstevel@tonic-gate ; 3417c478bd9Sstevel@tonic-gate /* After all popped, we'll get an EINVAL, which is expected */ 34261961e0fSrobinson if (errno != EINVAL) 3437c478bd9Sstevel@tonic-gate return (-1); 3447c478bd9Sstevel@tonic-gate return (0); 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate /* check to see if the named module is on the stream */ 34761961e0fSrobinson if (ioctl(fd, I_FIND, modp) != 1) 3487c478bd9Sstevel@tonic-gate return (-1); 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate /* pop them until the right one is on top */ 3517c478bd9Sstevel@tonic-gate for (;;) { 35261961e0fSrobinson if (ioctl(fd, I_LOOK, buf) < 0) 3537c478bd9Sstevel@tonic-gate return (-1); 35461961e0fSrobinson if (strcmp(modp, buf) == 0) 3557c478bd9Sstevel@tonic-gate /* we're done */ 3567c478bd9Sstevel@tonic-gate return (0); 35761961e0fSrobinson if (ioctl(fd, I_POP, 0) < 0) 3587c478bd9Sstevel@tonic-gate return (-1); 3597c478bd9Sstevel@tonic-gate } 36061961e0fSrobinson /* NOTREACHED */ 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate /* 3657c478bd9Sstevel@tonic-gate * dorun - handle a `run' command 3667c478bd9Sstevel@tonic-gate * 3677c478bd9Sstevel@tonic-gate * args: p - command line to run 3687c478bd9Sstevel@tonic-gate * waitflag - flag indicating whether a wait should be done 3697c478bd9Sstevel@tonic-gate */ 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate static int 3737c478bd9Sstevel@tonic-gate dorun(char *p, int waitflg) 3747c478bd9Sstevel@tonic-gate { 3757c478bd9Sstevel@tonic-gate char *tp; /* scratch pointer */ 3767c478bd9Sstevel@tonic-gate char *ep; /* scratch pointer (end of token) */ 3777c478bd9Sstevel@tonic-gate char savech; /* hold area */ 3787c478bd9Sstevel@tonic-gate int status; /* return status from wait */ 3797c478bd9Sstevel@tonic-gate pid_t pid; /* pid of child proc */ 3807c478bd9Sstevel@tonic-gate pid_t rpid; /* returned pid from wait */ 3817c478bd9Sstevel@tonic-gate void (*func)(); /* return from signal */ 3827c478bd9Sstevel@tonic-gate 38361961e0fSrobinson if (*p == '\0') 3847c478bd9Sstevel@tonic-gate return (-1); 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate /* 3877c478bd9Sstevel@tonic-gate * get first token 3887c478bd9Sstevel@tonic-gate */ 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate for (tp = p; *tp && !isspace(*tp); ++tp) 3917c478bd9Sstevel@tonic-gate ; 3927c478bd9Sstevel@tonic-gate savech = '\0'; 3937c478bd9Sstevel@tonic-gate if (*tp) { 3947c478bd9Sstevel@tonic-gate savech = *tp; 3957c478bd9Sstevel@tonic-gate *tp = '\0'; 3967c478bd9Sstevel@tonic-gate } 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate /* 3997c478bd9Sstevel@tonic-gate * look for built-in's 4007c478bd9Sstevel@tonic-gate */ 4017c478bd9Sstevel@tonic-gate 40261961e0fSrobinson if (strcmp(p, "cd") == 0) { 4037c478bd9Sstevel@tonic-gate *tp = savech; 4047c478bd9Sstevel@tonic-gate tp = eatwhite(tp); 4057c478bd9Sstevel@tonic-gate if (*tp == '\0') 4067c478bd9Sstevel@tonic-gate /* if nothing there, try to cd to $HOME */ 4077c478bd9Sstevel@tonic-gate tp = getenv("HOME"); 40861961e0fSrobinson if (chdir(tp) < 0) 4097c478bd9Sstevel@tonic-gate return (-1); 41061961e0fSrobinson } else if (strcmp(p, "ulimit") == 0) { 4117c478bd9Sstevel@tonic-gate *tp = savech; 4127c478bd9Sstevel@tonic-gate tp = eatwhite(tp); 4137c478bd9Sstevel@tonic-gate /* must have an argument */ 41461961e0fSrobinson if (*tp == '\0') 4157c478bd9Sstevel@tonic-gate return (-1); 4167c478bd9Sstevel@tonic-gate /* make sure nothing appears on line after arg */ 4177c478bd9Sstevel@tonic-gate for (ep = tp; *ep && !isspace(*ep); ++ep) 4187c478bd9Sstevel@tonic-gate ; 4197c478bd9Sstevel@tonic-gate ep = eatwhite(ep); 42061961e0fSrobinson if (*ep) 4217c478bd9Sstevel@tonic-gate return (-1); 42261961e0fSrobinson if (!isdigit(*tp)) 4237c478bd9Sstevel@tonic-gate return (-1); 4247c478bd9Sstevel@tonic-gate 42561961e0fSrobinson if (ulimit(2, atoi(tp)) < 0) 4267c478bd9Sstevel@tonic-gate return (-1); 42761961e0fSrobinson } else if (strcmp(p, "umask") == 0) { 4287c478bd9Sstevel@tonic-gate *tp = savech; 4297c478bd9Sstevel@tonic-gate tp = eatwhite(tp); 4307c478bd9Sstevel@tonic-gate /* must have an argument */ 43161961e0fSrobinson if (*tp == '\0') 4327c478bd9Sstevel@tonic-gate return (-1); 4337c478bd9Sstevel@tonic-gate /* make sure nothing appears on line after arg */ 4347c478bd9Sstevel@tonic-gate for (ep = tp; *ep && !isspace(*ep); ++ep) 4357c478bd9Sstevel@tonic-gate ; 4367c478bd9Sstevel@tonic-gate ep = eatwhite(ep); 43761961e0fSrobinson if (*ep) 4387c478bd9Sstevel@tonic-gate return (-1); 43961961e0fSrobinson if (!isdigit(*tp)) 4407c478bd9Sstevel@tonic-gate return (-1); 4417c478bd9Sstevel@tonic-gate (void) umask(strtol(tp, NULL, 8)); 4427c478bd9Sstevel@tonic-gate } else { 4437c478bd9Sstevel@tonic-gate /* not a built-in */ 4447c478bd9Sstevel@tonic-gate *tp = savech; 4457c478bd9Sstevel@tonic-gate func = signal(SIGCLD, SIG_DFL); 4467c478bd9Sstevel@tonic-gate if ((pid = fork()) < 0) { 44761961e0fSrobinson (void) signal(SIGCLD, func); 4487c478bd9Sstevel@tonic-gate return (-1); 44961961e0fSrobinson } 45061961e0fSrobinson if (pid) { 4517c478bd9Sstevel@tonic-gate if (waitflg == WAIT) { 4527c478bd9Sstevel@tonic-gate status = 0; 4537c478bd9Sstevel@tonic-gate rpid = -1; 4547c478bd9Sstevel@tonic-gate while (rpid != pid) 4557c478bd9Sstevel@tonic-gate rpid = wait(&status); 4567c478bd9Sstevel@tonic-gate if (status) { 4577c478bd9Sstevel@tonic-gate /* child failed */ 45861961e0fSrobinson (void) signal(SIGCLD, func); 4597c478bd9Sstevel@tonic-gate return (-1); 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate } 46261961e0fSrobinson (void) signal(SIGCLD, func); 4637c478bd9Sstevel@tonic-gate } else { 4647c478bd9Sstevel@tonic-gate /* set IFS for security */ 4657c478bd9Sstevel@tonic-gate (void) putenv("IFS=\" \""); 4667c478bd9Sstevel@tonic-gate /* 4677c478bd9Sstevel@tonic-gate * need to close all files to prevent unauthorized 4687c478bd9Sstevel@tonic-gate * access in the children. Setup stdin, stdout, 4697c478bd9Sstevel@tonic-gate * and stderr to /dev/null. 4707c478bd9Sstevel@tonic-gate */ 4717c478bd9Sstevel@tonic-gate closefrom(0); 4727c478bd9Sstevel@tonic-gate /* stdin */ 47361961e0fSrobinson if (open("/dev/null", O_RDWR) != 0) 4747c478bd9Sstevel@tonic-gate return (-1); 4757c478bd9Sstevel@tonic-gate /* stdout */ 47661961e0fSrobinson if (dup(0) != 1) 4777c478bd9Sstevel@tonic-gate return (-1); 4787c478bd9Sstevel@tonic-gate /* stderr */ 47961961e0fSrobinson if (dup(0) != 2) 4807c478bd9Sstevel@tonic-gate return (-1); 481*7257d1b4Sraf (void) execl("/usr/bin/sh", "sh", "-c", p, NULL); 48261961e0fSrobinson /* 48361961e0fSrobinson * if we get here, there is a problem - remember that 48461961e0fSrobinson * this is the child 48561961e0fSrobinson */ 4867c478bd9Sstevel@tonic-gate exit(1); 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate return (0); 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate /* 4947c478bd9Sstevel@tonic-gate * eatwhite - swallow any leading whitespace, return pointer to first 4957c478bd9Sstevel@tonic-gate * non-white space character or to terminating null character 4967c478bd9Sstevel@tonic-gate * if nothing else is there 4977c478bd9Sstevel@tonic-gate * 4987c478bd9Sstevel@tonic-gate * args: p - string to parse 4997c478bd9Sstevel@tonic-gate */ 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate static char * 5027c478bd9Sstevel@tonic-gate eatwhite(char *p) 5037c478bd9Sstevel@tonic-gate { 5047c478bd9Sstevel@tonic-gate while (*p && isspace(*p)) 5057c478bd9Sstevel@tonic-gate p++; 5067c478bd9Sstevel@tonic-gate return (p); 5077c478bd9Sstevel@tonic-gate } 508