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 5*004388ebScasper * Common Development and Distribution License (the "License"). 6*004388ebScasper * 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 /* 23e8031f0aSraf * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 307c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 317c478bd9Sstevel@tonic-gate 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 537c478bd9Sstevel@tonic-gate extern char **_environ; 547c478bd9Sstevel@tonic-gate 5561961e0fSrobinson static char *eatwhite(char *); 5661961e0fSrobinson static int doassign(char *); 5761961e0fSrobinson static int dopush(int, char *); 5861961e0fSrobinson static int dopop(int, char *); 5961961e0fSrobinson static int dorun(char *, int); 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate /* 627c478bd9Sstevel@tonic-gate * doconfig - the configuration script interpreter, if all is ok, 637c478bd9Sstevel@tonic-gate * return 0. If there is a "system" error, return -1. 647c478bd9Sstevel@tonic-gate * If there is an error performing a command, or there 657c478bd9Sstevel@tonic-gate * is a syntax error, return the line number in error. 667c478bd9Sstevel@tonic-gate * 677c478bd9Sstevel@tonic-gate * args: fd - file descriptor to push and pop from 687c478bd9Sstevel@tonic-gate * script - name of the configuration script 697c478bd9Sstevel@tonic-gate * rflag - restriction flag to determine what "commands" 707c478bd9Sstevel@tonic-gate * can be run 717c478bd9Sstevel@tonic-gate */ 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate int 747c478bd9Sstevel@tonic-gate doconfig(int fd, char *script, long rflag) 757c478bd9Sstevel@tonic-gate { 767c478bd9Sstevel@tonic-gate int line; /* line counter */ 777c478bd9Sstevel@tonic-gate struct stat statbuf; /* place for stat */ 787c478bd9Sstevel@tonic-gate FILE *fp; /* file pointer for config script */ 797c478bd9Sstevel@tonic-gate char buf[BUFSIZ + 1]; /* scratch buffer */ 807c478bd9Sstevel@tonic-gate char *bp; /* scratch pointer */ 817c478bd9Sstevel@tonic-gate char *p; /* scratch pointer */ 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate /* if the script does not exist, then there is nothing to do */ 84e8031f0aSraf if (stat(script, &statbuf) < 0) 857c478bd9Sstevel@tonic-gate return (0); 867c478bd9Sstevel@tonic-gate 87*004388ebScasper fp = fopen(script, "rF"); 8861961e0fSrobinson if (fp == NULL) 897c478bd9Sstevel@tonic-gate return (-1); 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate line = 0; 927c478bd9Sstevel@tonic-gate while (fgets(buf, BUFSIZ, fp)) { 937c478bd9Sstevel@tonic-gate line++; 947c478bd9Sstevel@tonic-gate p = strchr(buf, '\n'); 957c478bd9Sstevel@tonic-gate /* if no \n, then line is too long */ 967c478bd9Sstevel@tonic-gate if (p == NULL) { 977c478bd9Sstevel@tonic-gate (void) fclose(fp); 987c478bd9Sstevel@tonic-gate return (line); 997c478bd9Sstevel@tonic-gate } 1007c478bd9Sstevel@tonic-gate *p = '\0'; 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate /* remove comments */ 1037c478bd9Sstevel@tonic-gate p = strchr(buf, COMMENT); 1047c478bd9Sstevel@tonic-gate if (p) 1057c478bd9Sstevel@tonic-gate *p = '\0'; 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate /* remove leading whitespace */ 1087c478bd9Sstevel@tonic-gate bp = eatwhite(buf); 1097c478bd9Sstevel@tonic-gate /* see if anything is left */ 1107c478bd9Sstevel@tonic-gate if (*bp == '\0') 1117c478bd9Sstevel@tonic-gate continue; 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate /* remove trailing whitespace */ 1147c478bd9Sstevel@tonic-gate p = &buf[strlen(buf) - 1]; 1157c478bd9Sstevel@tonic-gate while (*p && isspace(*p)) 1167c478bd9Sstevel@tonic-gate *p-- = '\0'; 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate /* get the command */ 1197c478bd9Sstevel@tonic-gate p = bp; 1207c478bd9Sstevel@tonic-gate while (*p && !isspace(*p)) 1217c478bd9Sstevel@tonic-gate p++; 1227c478bd9Sstevel@tonic-gate if (*p) 1237c478bd9Sstevel@tonic-gate *p++ = '\0'; 1247c478bd9Sstevel@tonic-gate /* skip any whitespace here too (between command and args) */ 1257c478bd9Sstevel@tonic-gate p = eatwhite(p); 1267c478bd9Sstevel@tonic-gate 12761961e0fSrobinson if (strcmp(bp, "assign") == 0) { 1287c478bd9Sstevel@tonic-gate if ((rflag & NOASSIGN) || doassign(p)) { 1297c478bd9Sstevel@tonic-gate (void) fclose(fp); 1307c478bd9Sstevel@tonic-gate return (line); 1317c478bd9Sstevel@tonic-gate } 13261961e0fSrobinson } else if (strcmp(bp, "push") == 0) { 1337c478bd9Sstevel@tonic-gate if (dopush(fd, p)) { 1347c478bd9Sstevel@tonic-gate (void) fclose(fp); 1357c478bd9Sstevel@tonic-gate return (line); 1367c478bd9Sstevel@tonic-gate } 13761961e0fSrobinson } else if (strcmp(bp, "pop") == 0) { 1387c478bd9Sstevel@tonic-gate if (dopop(fd, p)) { 1397c478bd9Sstevel@tonic-gate (void) fclose(fp); 1407c478bd9Sstevel@tonic-gate return (line); 1417c478bd9Sstevel@tonic-gate } 14261961e0fSrobinson } else if (strcmp(bp, "run") == 0) { 1437c478bd9Sstevel@tonic-gate if ((rflag & NORUN) || dorun(p, NOWAIT)) { 1447c478bd9Sstevel@tonic-gate (void) fclose(fp); 1457c478bd9Sstevel@tonic-gate return (line); 1467c478bd9Sstevel@tonic-gate } 14761961e0fSrobinson } else if (strcmp(bp, "runwait") == 0) { 1487c478bd9Sstevel@tonic-gate if ((rflag & NORUN) || dorun(p, WAIT)) { 1497c478bd9Sstevel@tonic-gate (void) fclose(fp); 1507c478bd9Sstevel@tonic-gate return (line); 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate } else { 1537c478bd9Sstevel@tonic-gate /* unknown command */ 1547c478bd9Sstevel@tonic-gate (void) fclose(fp); 1557c478bd9Sstevel@tonic-gate return (line); 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate if (!feof(fp)) { 1597c478bd9Sstevel@tonic-gate (void) fclose(fp); 1607c478bd9Sstevel@tonic-gate return (-1); 1617c478bd9Sstevel@tonic-gate } 16261961e0fSrobinson (void) fclose(fp); 16361961e0fSrobinson return (0); 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate /* 1687c478bd9Sstevel@tonic-gate * doassign - handle an `assign' command 1697c478bd9Sstevel@tonic-gate * 1707c478bd9Sstevel@tonic-gate * args: p - assignment string 1717c478bd9Sstevel@tonic-gate */ 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate static int 1757c478bd9Sstevel@tonic-gate doassign(char *p) 1767c478bd9Sstevel@tonic-gate { 1777c478bd9Sstevel@tonic-gate char *var; /* environment variable to be assigned */ 1787c478bd9Sstevel@tonic-gate char val[BUFSIZ]; /* and the value to be assigned to it */ 1797c478bd9Sstevel@tonic-gate char scratch[BUFSIZ]; /* scratch buffer */ 1807c478bd9Sstevel@tonic-gate char delim; /* delimiter char seen (for quoted strings ) */ 1817c478bd9Sstevel@tonic-gate char *tp; /* scratch pointer */ 1827c478bd9Sstevel@tonic-gate 18361961e0fSrobinson if (*p == '\0') 1847c478bd9Sstevel@tonic-gate return (-1); 1857c478bd9Sstevel@tonic-gate var = p; 1867c478bd9Sstevel@tonic-gate /* skip first token, but stop if we see a '=' */ 1877c478bd9Sstevel@tonic-gate while (*p && !isspace(*p) && (*p != '=')) 1887c478bd9Sstevel@tonic-gate p++; 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate /* if we found end of string, it's an error */ 19161961e0fSrobinson if (*p == '\0') 1927c478bd9Sstevel@tonic-gate return (-1); 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* if we found a space, look for the '=', otherwise it's an error */ 1957c478bd9Sstevel@tonic-gate if (isspace(*p)) { 1967c478bd9Sstevel@tonic-gate *p++ = '\0'; 1977c478bd9Sstevel@tonic-gate while (*p && isspace(*p)) 1987c478bd9Sstevel@tonic-gate p++; 19961961e0fSrobinson if (*p == '\0') 2007c478bd9Sstevel@tonic-gate return (-1); 2017c478bd9Sstevel@tonic-gate if (*p == '=') 2027c478bd9Sstevel@tonic-gate p++; 20361961e0fSrobinson else 2047c478bd9Sstevel@tonic-gate return (-1); 2057c478bd9Sstevel@tonic-gate } else { 2067c478bd9Sstevel@tonic-gate /* skip over '=' */ 2077c478bd9Sstevel@tonic-gate *p = '\0'; 2087c478bd9Sstevel@tonic-gate p++; 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate /* skip over any whitespace */ 2127c478bd9Sstevel@tonic-gate p = eatwhite(p); 2137c478bd9Sstevel@tonic-gate if (*p == '\'' || *p == '"') { 2147c478bd9Sstevel@tonic-gate /* handle quoted values */ 2157c478bd9Sstevel@tonic-gate delim = *p++; 2167c478bd9Sstevel@tonic-gate tp = val; 2177c478bd9Sstevel@tonic-gate for (;;) { 2187c478bd9Sstevel@tonic-gate if (*p == '\0') { 2197c478bd9Sstevel@tonic-gate return (-1); 2207c478bd9Sstevel@tonic-gate } else if (*p == delim) { 2217c478bd9Sstevel@tonic-gate if (*(p - 1) != '\\') 2227c478bd9Sstevel@tonic-gate break; 2237c478bd9Sstevel@tonic-gate else 2247c478bd9Sstevel@tonic-gate *(tp - 1) = *p++; 2257c478bd9Sstevel@tonic-gate } else 2267c478bd9Sstevel@tonic-gate *tp++ = *p++; 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate *tp = '\0'; 22961961e0fSrobinson /* 23061961e0fSrobinson * these assignments make the comment below true 23161961e0fSrobinson * (values of tp and p 23261961e0fSrobinson */ 2337c478bd9Sstevel@tonic-gate tp = ++p; 2347c478bd9Sstevel@tonic-gate p = val; 2357c478bd9Sstevel@tonic-gate } else { 2367c478bd9Sstevel@tonic-gate tp = p; 2377c478bd9Sstevel@tonic-gate /* look for end of token */ 2387c478bd9Sstevel@tonic-gate while (*tp && !isspace(*tp)) 2397c478bd9Sstevel@tonic-gate tp++; 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* 2437c478bd9Sstevel@tonic-gate * at this point, p points to the value, and tp points to the 2447c478bd9Sstevel@tonic-gate * end of the token. check to make sure there is no garbage on 2457c478bd9Sstevel@tonic-gate * the end of the line 2467c478bd9Sstevel@tonic-gate */ 2477c478bd9Sstevel@tonic-gate 24861961e0fSrobinson if (*tp) 2497c478bd9Sstevel@tonic-gate return (-1); 25061961e0fSrobinson (void) snprintf(scratch, sizeof (scratch), "%s=%s", var, p); 2517c478bd9Sstevel@tonic-gate /* note: need to malloc fresh space so putenv works */ 2527c478bd9Sstevel@tonic-gate tp = malloc(strlen(scratch) + 1); 25361961e0fSrobinson if (tp == NULL) 2547c478bd9Sstevel@tonic-gate return (-1); 25561961e0fSrobinson (void) strcpy(tp, scratch); 25661961e0fSrobinson if (putenv(tp)) 2577c478bd9Sstevel@tonic-gate return (-1); 2587c478bd9Sstevel@tonic-gate return (0); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate /* 2637c478bd9Sstevel@tonic-gate * dopush - handle a `push' command 2647c478bd9Sstevel@tonic-gate * 2657c478bd9Sstevel@tonic-gate * args: fd - file descriptor to push on 2667c478bd9Sstevel@tonic-gate * p - list of modules to push 2677c478bd9Sstevel@tonic-gate */ 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate static int 2717c478bd9Sstevel@tonic-gate dopush(int fd, char *p) 2727c478bd9Sstevel@tonic-gate { 2737c478bd9Sstevel@tonic-gate char *tp; /* scratch pointer */ 2747c478bd9Sstevel@tonic-gate int i; /* scratch variable */ 2757c478bd9Sstevel@tonic-gate int npush; /* count # of modules pushed */ 2767c478bd9Sstevel@tonic-gate 27761961e0fSrobinson if (*p == '\0') 2787c478bd9Sstevel@tonic-gate return (-1); 2797c478bd9Sstevel@tonic-gate npush = 0; 2807c478bd9Sstevel@tonic-gate for (;;) { 28161961e0fSrobinson if (*p == '\0') /* found end of line */ 2827c478bd9Sstevel@tonic-gate return (0); 2837c478bd9Sstevel@tonic-gate p = eatwhite(p); 28461961e0fSrobinson if (*p == '\0') 2857c478bd9Sstevel@tonic-gate return (-1); 2867c478bd9Sstevel@tonic-gate tp = p; 2877c478bd9Sstevel@tonic-gate while (*tp && !isspace(*tp) && (*tp != ',')) 2887c478bd9Sstevel@tonic-gate tp++; 2897c478bd9Sstevel@tonic-gate if (*tp) 2907c478bd9Sstevel@tonic-gate *tp++ = '\0'; 2917c478bd9Sstevel@tonic-gate if (ioctl(fd, I_PUSH, p) < 0) { 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate /* 2947c478bd9Sstevel@tonic-gate * try to pop all that we've done, if pop fails it doesn't matter because 2957c478bd9Sstevel@tonic-gate * nothing can be done anyhow 2967c478bd9Sstevel@tonic-gate */ 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate for (i = 0; i < npush; ++i) 29961961e0fSrobinson (void) ioctl(fd, I_POP, 0); 3007c478bd9Sstevel@tonic-gate return (-1); 30161961e0fSrobinson } 3027c478bd9Sstevel@tonic-gate /* count the number of modules we've pushed */ 3037c478bd9Sstevel@tonic-gate npush++; 3047c478bd9Sstevel@tonic-gate p = tp; 3057c478bd9Sstevel@tonic-gate } 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate /* 3107c478bd9Sstevel@tonic-gate * dopop - handle a `pop' command 3117c478bd9Sstevel@tonic-gate * 3127c478bd9Sstevel@tonic-gate * args: fd - file descriptor to pop from 3137c478bd9Sstevel@tonic-gate * p - name of module to pop to or ALL (null means pop top only) 3147c478bd9Sstevel@tonic-gate */ 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate static int 3187c478bd9Sstevel@tonic-gate dopop(int fd, char *p) 3197c478bd9Sstevel@tonic-gate { 3207c478bd9Sstevel@tonic-gate char *modp; /* module name from argument to pop */ 3217c478bd9Sstevel@tonic-gate char buf[FMNAMESZ + 1]; /* scratch buffer */ 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate if (*p == '\0') { 3247c478bd9Sstevel@tonic-gate /* just a pop with no args */ 32561961e0fSrobinson if (ioctl(fd, I_POP, 0) < 0) 3267c478bd9Sstevel@tonic-gate return (-1); 3277c478bd9Sstevel@tonic-gate return (0); 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate /* skip any whitespace in between */ 3317c478bd9Sstevel@tonic-gate p = eatwhite(p); 3327c478bd9Sstevel@tonic-gate modp = p; 3337c478bd9Sstevel@tonic-gate /* find end of module name */ 3347c478bd9Sstevel@tonic-gate while (*p && !isspace(*p)) 3357c478bd9Sstevel@tonic-gate p++; 3367c478bd9Sstevel@tonic-gate 33761961e0fSrobinson if (*p) /* if not end of line, extra junk on line */ 3387c478bd9Sstevel@tonic-gate return (-1); 33961961e0fSrobinson if (strcmp(modp, "ALL") == 0) { 3407c478bd9Sstevel@tonic-gate /* it's the magic name, pop them all */ 3417c478bd9Sstevel@tonic-gate while (ioctl(fd, I_POP, 0) == 0) 3427c478bd9Sstevel@tonic-gate ; 3437c478bd9Sstevel@tonic-gate /* After all popped, we'll get an EINVAL, which is expected */ 34461961e0fSrobinson if (errno != EINVAL) 3457c478bd9Sstevel@tonic-gate return (-1); 3467c478bd9Sstevel@tonic-gate return (0); 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate /* check to see if the named module is on the stream */ 34961961e0fSrobinson if (ioctl(fd, I_FIND, modp) != 1) 3507c478bd9Sstevel@tonic-gate return (-1); 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate /* pop them until the right one is on top */ 3537c478bd9Sstevel@tonic-gate for (;;) { 35461961e0fSrobinson if (ioctl(fd, I_LOOK, buf) < 0) 3557c478bd9Sstevel@tonic-gate return (-1); 35661961e0fSrobinson if (strcmp(modp, buf) == 0) 3577c478bd9Sstevel@tonic-gate /* we're done */ 3587c478bd9Sstevel@tonic-gate return (0); 35961961e0fSrobinson if (ioctl(fd, I_POP, 0) < 0) 3607c478bd9Sstevel@tonic-gate return (-1); 3617c478bd9Sstevel@tonic-gate } 36261961e0fSrobinson /* NOTREACHED */ 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate /* 3677c478bd9Sstevel@tonic-gate * dorun - handle a `run' command 3687c478bd9Sstevel@tonic-gate * 3697c478bd9Sstevel@tonic-gate * args: p - command line to run 3707c478bd9Sstevel@tonic-gate * waitflag - flag indicating whether a wait should be done 3717c478bd9Sstevel@tonic-gate */ 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate static int 3757c478bd9Sstevel@tonic-gate dorun(char *p, int waitflg) 3767c478bd9Sstevel@tonic-gate { 3777c478bd9Sstevel@tonic-gate char *tp; /* scratch pointer */ 3787c478bd9Sstevel@tonic-gate char *ep; /* scratch pointer (end of token) */ 3797c478bd9Sstevel@tonic-gate char savech; /* hold area */ 3807c478bd9Sstevel@tonic-gate int status; /* return status from wait */ 3817c478bd9Sstevel@tonic-gate pid_t pid; /* pid of child proc */ 3827c478bd9Sstevel@tonic-gate pid_t rpid; /* returned pid from wait */ 3837c478bd9Sstevel@tonic-gate void (*func)(); /* return from signal */ 3847c478bd9Sstevel@tonic-gate 38561961e0fSrobinson if (*p == '\0') 3867c478bd9Sstevel@tonic-gate return (-1); 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate /* 3897c478bd9Sstevel@tonic-gate * get first token 3907c478bd9Sstevel@tonic-gate */ 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate for (tp = p; *tp && !isspace(*tp); ++tp) 3937c478bd9Sstevel@tonic-gate ; 3947c478bd9Sstevel@tonic-gate savech = '\0'; 3957c478bd9Sstevel@tonic-gate if (*tp) { 3967c478bd9Sstevel@tonic-gate savech = *tp; 3977c478bd9Sstevel@tonic-gate *tp = '\0'; 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate /* 4017c478bd9Sstevel@tonic-gate * look for built-in's 4027c478bd9Sstevel@tonic-gate */ 4037c478bd9Sstevel@tonic-gate 40461961e0fSrobinson if (strcmp(p, "cd") == 0) { 4057c478bd9Sstevel@tonic-gate *tp = savech; 4067c478bd9Sstevel@tonic-gate tp = eatwhite(tp); 4077c478bd9Sstevel@tonic-gate if (*tp == '\0') 4087c478bd9Sstevel@tonic-gate /* if nothing there, try to cd to $HOME */ 4097c478bd9Sstevel@tonic-gate tp = getenv("HOME"); 41061961e0fSrobinson if (chdir(tp) < 0) 4117c478bd9Sstevel@tonic-gate return (-1); 41261961e0fSrobinson } else if (strcmp(p, "ulimit") == 0) { 4137c478bd9Sstevel@tonic-gate *tp = savech; 4147c478bd9Sstevel@tonic-gate tp = eatwhite(tp); 4157c478bd9Sstevel@tonic-gate /* must have an argument */ 41661961e0fSrobinson if (*tp == '\0') 4177c478bd9Sstevel@tonic-gate return (-1); 4187c478bd9Sstevel@tonic-gate /* make sure nothing appears on line after arg */ 4197c478bd9Sstevel@tonic-gate for (ep = tp; *ep && !isspace(*ep); ++ep) 4207c478bd9Sstevel@tonic-gate ; 4217c478bd9Sstevel@tonic-gate ep = eatwhite(ep); 42261961e0fSrobinson if (*ep) 4237c478bd9Sstevel@tonic-gate return (-1); 42461961e0fSrobinson if (!isdigit(*tp)) 4257c478bd9Sstevel@tonic-gate return (-1); 4267c478bd9Sstevel@tonic-gate 42761961e0fSrobinson if (ulimit(2, atoi(tp)) < 0) 4287c478bd9Sstevel@tonic-gate return (-1); 42961961e0fSrobinson } else if (strcmp(p, "umask") == 0) { 4307c478bd9Sstevel@tonic-gate *tp = savech; 4317c478bd9Sstevel@tonic-gate tp = eatwhite(tp); 4327c478bd9Sstevel@tonic-gate /* must have an argument */ 43361961e0fSrobinson if (*tp == '\0') 4347c478bd9Sstevel@tonic-gate return (-1); 4357c478bd9Sstevel@tonic-gate /* make sure nothing appears on line after arg */ 4367c478bd9Sstevel@tonic-gate for (ep = tp; *ep && !isspace(*ep); ++ep) 4377c478bd9Sstevel@tonic-gate ; 4387c478bd9Sstevel@tonic-gate ep = eatwhite(ep); 43961961e0fSrobinson if (*ep) 4407c478bd9Sstevel@tonic-gate return (-1); 44161961e0fSrobinson if (!isdigit(*tp)) 4427c478bd9Sstevel@tonic-gate return (-1); 4437c478bd9Sstevel@tonic-gate (void) umask(strtol(tp, NULL, 8)); 4447c478bd9Sstevel@tonic-gate } else { 4457c478bd9Sstevel@tonic-gate /* not a built-in */ 4467c478bd9Sstevel@tonic-gate *tp = savech; 4477c478bd9Sstevel@tonic-gate func = signal(SIGCLD, SIG_DFL); 4487c478bd9Sstevel@tonic-gate if ((pid = fork()) < 0) { 44961961e0fSrobinson (void) signal(SIGCLD, func); 4507c478bd9Sstevel@tonic-gate return (-1); 45161961e0fSrobinson } 45261961e0fSrobinson if (pid) { 4537c478bd9Sstevel@tonic-gate if (waitflg == WAIT) { 4547c478bd9Sstevel@tonic-gate status = 0; 4557c478bd9Sstevel@tonic-gate rpid = -1; 4567c478bd9Sstevel@tonic-gate while (rpid != pid) 4577c478bd9Sstevel@tonic-gate rpid = wait(&status); 4587c478bd9Sstevel@tonic-gate if (status) { 4597c478bd9Sstevel@tonic-gate /* child failed */ 46061961e0fSrobinson (void) signal(SIGCLD, func); 4617c478bd9Sstevel@tonic-gate return (-1); 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate } 46461961e0fSrobinson (void) signal(SIGCLD, func); 4657c478bd9Sstevel@tonic-gate } else { 4667c478bd9Sstevel@tonic-gate /* set IFS for security */ 4677c478bd9Sstevel@tonic-gate (void) putenv("IFS=\" \""); 4687c478bd9Sstevel@tonic-gate /* 4697c478bd9Sstevel@tonic-gate * need to close all files to prevent unauthorized 4707c478bd9Sstevel@tonic-gate * access in the children. Setup stdin, stdout, 4717c478bd9Sstevel@tonic-gate * and stderr to /dev/null. 4727c478bd9Sstevel@tonic-gate */ 4737c478bd9Sstevel@tonic-gate closefrom(0); 4747c478bd9Sstevel@tonic-gate /* stdin */ 47561961e0fSrobinson if (open("/dev/null", O_RDWR) != 0) 4767c478bd9Sstevel@tonic-gate return (-1); 4777c478bd9Sstevel@tonic-gate /* stdout */ 47861961e0fSrobinson if (dup(0) != 1) 4797c478bd9Sstevel@tonic-gate return (-1); 4807c478bd9Sstevel@tonic-gate /* stderr */ 48161961e0fSrobinson if (dup(0) != 2) 4827c478bd9Sstevel@tonic-gate return (-1); 48361961e0fSrobinson (void) execle("/usr/bin/sh", "sh", "-c", 48461961e0fSrobinson p, 0, _environ); 48561961e0fSrobinson /* 48661961e0fSrobinson * if we get here, there is a problem - remember that 48761961e0fSrobinson * this is the child 48861961e0fSrobinson */ 4897c478bd9Sstevel@tonic-gate exit(1); 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate return (0); 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate /* 4977c478bd9Sstevel@tonic-gate * eatwhite - swallow any leading whitespace, return pointer to first 4987c478bd9Sstevel@tonic-gate * non-white space character or to terminating null character 4997c478bd9Sstevel@tonic-gate * if nothing else is there 5007c478bd9Sstevel@tonic-gate * 5017c478bd9Sstevel@tonic-gate * args: p - string to parse 5027c478bd9Sstevel@tonic-gate */ 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate static char * 5057c478bd9Sstevel@tonic-gate eatwhite(char *p) 5067c478bd9Sstevel@tonic-gate { 5077c478bd9Sstevel@tonic-gate while (*p && isspace(*p)) 5087c478bd9Sstevel@tonic-gate p++; 5097c478bd9Sstevel@tonic-gate return (p); 5107c478bd9Sstevel@tonic-gate } 511