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 */ 22*61961e0fSrobinson 237c478bd9Sstevel@tonic-gate /* 24*61961e0fSrobinson * Copyright 2005 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 337c478bd9Sstevel@tonic-gate 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 #if defined(sparc) 517c478bd9Sstevel@tonic-gate #define _STAT _stat 527c478bd9Sstevel@tonic-gate #define _FSTAT _fstat 537c478bd9Sstevel@tonic-gate #else /* !sparc */ 547c478bd9Sstevel@tonic-gate #define _STAT stat 557c478bd9Sstevel@tonic-gate #define _FSTAT fstat 567c478bd9Sstevel@tonic-gate #endif /* sparc */ 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate extern int _stat(const char *, struct stat *); 597c478bd9Sstevel@tonic-gate extern int _fstat(int, struct stat *); 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate #define COMMENT '#' 627c478bd9Sstevel@tonic-gate #define NOWAIT 0 637c478bd9Sstevel@tonic-gate #define WAIT 1 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate extern char **_environ; 667c478bd9Sstevel@tonic-gate 67*61961e0fSrobinson static char *eatwhite(char *); 68*61961e0fSrobinson static int doassign(char *); 69*61961e0fSrobinson static int dopush(int, char *); 70*61961e0fSrobinson static int dopop(int, char *); 71*61961e0fSrobinson static int dorun(char *, int); 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate /* 747c478bd9Sstevel@tonic-gate * doconfig - the configuration script interpreter, if all is ok, 757c478bd9Sstevel@tonic-gate * return 0. If there is a "system" error, return -1. 767c478bd9Sstevel@tonic-gate * If there is an error performing a command, or there 777c478bd9Sstevel@tonic-gate * is a syntax error, return the line number in error. 787c478bd9Sstevel@tonic-gate * 797c478bd9Sstevel@tonic-gate * args: fd - file descriptor to push and pop from 807c478bd9Sstevel@tonic-gate * script - name of the configuration script 817c478bd9Sstevel@tonic-gate * rflag - restriction flag to determine what "commands" 827c478bd9Sstevel@tonic-gate * can be run 837c478bd9Sstevel@tonic-gate */ 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate int 867c478bd9Sstevel@tonic-gate doconfig(int fd, char *script, long rflag) 877c478bd9Sstevel@tonic-gate { 887c478bd9Sstevel@tonic-gate int line; /* line counter */ 897c478bd9Sstevel@tonic-gate struct stat statbuf; /* place for stat */ 907c478bd9Sstevel@tonic-gate FILE *fp; /* file pointer for config script */ 917c478bd9Sstevel@tonic-gate char buf[BUFSIZ + 1]; /* scratch buffer */ 927c478bd9Sstevel@tonic-gate char *bp; /* scratch pointer */ 937c478bd9Sstevel@tonic-gate char *p; /* scratch pointer */ 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate /* if the script does not exist, then there is nothing to do */ 96*61961e0fSrobinson if (_STAT(script, &statbuf) < 0) 977c478bd9Sstevel@tonic-gate return (0); 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate fp = fopen(script, "r"); 100*61961e0fSrobinson if (fp == NULL) 1017c478bd9Sstevel@tonic-gate return (-1); 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate line = 0; 1047c478bd9Sstevel@tonic-gate while (fgets(buf, BUFSIZ, fp)) { 1057c478bd9Sstevel@tonic-gate line++; 1067c478bd9Sstevel@tonic-gate p = strchr(buf, '\n'); 1077c478bd9Sstevel@tonic-gate /* if no \n, then line is too long */ 1087c478bd9Sstevel@tonic-gate if (p == NULL) { 1097c478bd9Sstevel@tonic-gate (void) fclose(fp); 1107c478bd9Sstevel@tonic-gate return (line); 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate *p = '\0'; 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate /* remove comments */ 1157c478bd9Sstevel@tonic-gate p = strchr(buf, COMMENT); 1167c478bd9Sstevel@tonic-gate if (p) 1177c478bd9Sstevel@tonic-gate *p = '\0'; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate /* remove leading whitespace */ 1207c478bd9Sstevel@tonic-gate bp = eatwhite(buf); 1217c478bd9Sstevel@tonic-gate /* see if anything is left */ 1227c478bd9Sstevel@tonic-gate if (*bp == '\0') 1237c478bd9Sstevel@tonic-gate continue; 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate /* remove trailing whitespace */ 1267c478bd9Sstevel@tonic-gate p = &buf[strlen(buf) - 1]; 1277c478bd9Sstevel@tonic-gate while (*p && isspace(*p)) 1287c478bd9Sstevel@tonic-gate *p-- = '\0'; 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate /* get the command */ 1317c478bd9Sstevel@tonic-gate p = bp; 1327c478bd9Sstevel@tonic-gate while (*p && !isspace(*p)) 1337c478bd9Sstevel@tonic-gate p++; 1347c478bd9Sstevel@tonic-gate if (*p) 1357c478bd9Sstevel@tonic-gate *p++ = '\0'; 1367c478bd9Sstevel@tonic-gate /* skip any whitespace here too (between command and args) */ 1377c478bd9Sstevel@tonic-gate p = eatwhite(p); 1387c478bd9Sstevel@tonic-gate 139*61961e0fSrobinson if (strcmp(bp, "assign") == 0) { 1407c478bd9Sstevel@tonic-gate if ((rflag & NOASSIGN) || doassign(p)) { 1417c478bd9Sstevel@tonic-gate (void) fclose(fp); 1427c478bd9Sstevel@tonic-gate return (line); 1437c478bd9Sstevel@tonic-gate } 144*61961e0fSrobinson } else if (strcmp(bp, "push") == 0) { 1457c478bd9Sstevel@tonic-gate if (dopush(fd, p)) { 1467c478bd9Sstevel@tonic-gate (void) fclose(fp); 1477c478bd9Sstevel@tonic-gate return (line); 1487c478bd9Sstevel@tonic-gate } 149*61961e0fSrobinson } else if (strcmp(bp, "pop") == 0) { 1507c478bd9Sstevel@tonic-gate if (dopop(fd, p)) { 1517c478bd9Sstevel@tonic-gate (void) fclose(fp); 1527c478bd9Sstevel@tonic-gate return (line); 1537c478bd9Sstevel@tonic-gate } 154*61961e0fSrobinson } else if (strcmp(bp, "run") == 0) { 1557c478bd9Sstevel@tonic-gate if ((rflag & NORUN) || dorun(p, NOWAIT)) { 1567c478bd9Sstevel@tonic-gate (void) fclose(fp); 1577c478bd9Sstevel@tonic-gate return (line); 1587c478bd9Sstevel@tonic-gate } 159*61961e0fSrobinson } else if (strcmp(bp, "runwait") == 0) { 1607c478bd9Sstevel@tonic-gate if ((rflag & NORUN) || dorun(p, WAIT)) { 1617c478bd9Sstevel@tonic-gate (void) fclose(fp); 1627c478bd9Sstevel@tonic-gate return (line); 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate } else { 1657c478bd9Sstevel@tonic-gate /* unknown command */ 1667c478bd9Sstevel@tonic-gate (void) fclose(fp); 1677c478bd9Sstevel@tonic-gate return (line); 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate if (!feof(fp)) { 1717c478bd9Sstevel@tonic-gate (void) fclose(fp); 1727c478bd9Sstevel@tonic-gate return (-1); 1737c478bd9Sstevel@tonic-gate } 174*61961e0fSrobinson (void) fclose(fp); 175*61961e0fSrobinson return (0); 1767c478bd9Sstevel@tonic-gate } 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate /* 1807c478bd9Sstevel@tonic-gate * doassign - handle an `assign' command 1817c478bd9Sstevel@tonic-gate * 1827c478bd9Sstevel@tonic-gate * args: p - assignment string 1837c478bd9Sstevel@tonic-gate */ 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate static int 1877c478bd9Sstevel@tonic-gate doassign(char *p) 1887c478bd9Sstevel@tonic-gate { 1897c478bd9Sstevel@tonic-gate char *var; /* environment variable to be assigned */ 1907c478bd9Sstevel@tonic-gate char val[BUFSIZ]; /* and the value to be assigned to it */ 1917c478bd9Sstevel@tonic-gate char scratch[BUFSIZ]; /* scratch buffer */ 1927c478bd9Sstevel@tonic-gate char delim; /* delimiter char seen (for quoted strings ) */ 1937c478bd9Sstevel@tonic-gate char *tp; /* scratch pointer */ 1947c478bd9Sstevel@tonic-gate 195*61961e0fSrobinson if (*p == '\0') 1967c478bd9Sstevel@tonic-gate return (-1); 1977c478bd9Sstevel@tonic-gate var = p; 1987c478bd9Sstevel@tonic-gate /* skip first token, but stop if we see a '=' */ 1997c478bd9Sstevel@tonic-gate while (*p && !isspace(*p) && (*p != '=')) 2007c478bd9Sstevel@tonic-gate p++; 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate /* if we found end of string, it's an error */ 203*61961e0fSrobinson if (*p == '\0') 2047c478bd9Sstevel@tonic-gate return (-1); 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate /* if we found a space, look for the '=', otherwise it's an error */ 2077c478bd9Sstevel@tonic-gate if (isspace(*p)) { 2087c478bd9Sstevel@tonic-gate *p++ = '\0'; 2097c478bd9Sstevel@tonic-gate while (*p && isspace(*p)) 2107c478bd9Sstevel@tonic-gate p++; 211*61961e0fSrobinson if (*p == '\0') 2127c478bd9Sstevel@tonic-gate return (-1); 2137c478bd9Sstevel@tonic-gate if (*p == '=') 2147c478bd9Sstevel@tonic-gate p++; 215*61961e0fSrobinson else 2167c478bd9Sstevel@tonic-gate return (-1); 2177c478bd9Sstevel@tonic-gate } else { 2187c478bd9Sstevel@tonic-gate /* skip over '=' */ 2197c478bd9Sstevel@tonic-gate *p = '\0'; 2207c478bd9Sstevel@tonic-gate p++; 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate /* skip over any whitespace */ 2247c478bd9Sstevel@tonic-gate p = eatwhite(p); 2257c478bd9Sstevel@tonic-gate if (*p == '\'' || *p == '"') { 2267c478bd9Sstevel@tonic-gate /* handle quoted values */ 2277c478bd9Sstevel@tonic-gate delim = *p++; 2287c478bd9Sstevel@tonic-gate tp = val; 2297c478bd9Sstevel@tonic-gate for (;;) { 2307c478bd9Sstevel@tonic-gate if (*p == '\0') { 2317c478bd9Sstevel@tonic-gate return (-1); 2327c478bd9Sstevel@tonic-gate } else if (*p == delim) { 2337c478bd9Sstevel@tonic-gate if (*(p - 1) != '\\') 2347c478bd9Sstevel@tonic-gate break; 2357c478bd9Sstevel@tonic-gate else 2367c478bd9Sstevel@tonic-gate *(tp - 1) = *p++; 2377c478bd9Sstevel@tonic-gate } else 2387c478bd9Sstevel@tonic-gate *tp++ = *p++; 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate *tp = '\0'; 241*61961e0fSrobinson /* 242*61961e0fSrobinson * these assignments make the comment below true 243*61961e0fSrobinson * (values of tp and p 244*61961e0fSrobinson */ 2457c478bd9Sstevel@tonic-gate tp = ++p; 2467c478bd9Sstevel@tonic-gate p = val; 2477c478bd9Sstevel@tonic-gate } else { 2487c478bd9Sstevel@tonic-gate tp = p; 2497c478bd9Sstevel@tonic-gate /* look for end of token */ 2507c478bd9Sstevel@tonic-gate while (*tp && !isspace(*tp)) 2517c478bd9Sstevel@tonic-gate tp++; 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate /* 2557c478bd9Sstevel@tonic-gate * at this point, p points to the value, and tp points to the 2567c478bd9Sstevel@tonic-gate * end of the token. check to make sure there is no garbage on 2577c478bd9Sstevel@tonic-gate * the end of the line 2587c478bd9Sstevel@tonic-gate */ 2597c478bd9Sstevel@tonic-gate 260*61961e0fSrobinson if (*tp) 2617c478bd9Sstevel@tonic-gate return (-1); 262*61961e0fSrobinson (void) snprintf(scratch, sizeof (scratch), "%s=%s", var, p); 2637c478bd9Sstevel@tonic-gate /* note: need to malloc fresh space so putenv works */ 2647c478bd9Sstevel@tonic-gate tp = malloc(strlen(scratch) + 1); 265*61961e0fSrobinson if (tp == NULL) 2667c478bd9Sstevel@tonic-gate return (-1); 267*61961e0fSrobinson (void) strcpy(tp, scratch); 268*61961e0fSrobinson if (putenv(tp)) 2697c478bd9Sstevel@tonic-gate return (-1); 2707c478bd9Sstevel@tonic-gate return (0); 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate /* 2757c478bd9Sstevel@tonic-gate * dopush - handle a `push' command 2767c478bd9Sstevel@tonic-gate * 2777c478bd9Sstevel@tonic-gate * args: fd - file descriptor to push on 2787c478bd9Sstevel@tonic-gate * p - list of modules to push 2797c478bd9Sstevel@tonic-gate */ 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate static int 2837c478bd9Sstevel@tonic-gate dopush(int fd, char *p) 2847c478bd9Sstevel@tonic-gate { 2857c478bd9Sstevel@tonic-gate char *tp; /* scratch pointer */ 2867c478bd9Sstevel@tonic-gate int i; /* scratch variable */ 2877c478bd9Sstevel@tonic-gate int npush; /* count # of modules pushed */ 2887c478bd9Sstevel@tonic-gate 289*61961e0fSrobinson if (*p == '\0') 2907c478bd9Sstevel@tonic-gate return (-1); 2917c478bd9Sstevel@tonic-gate npush = 0; 2927c478bd9Sstevel@tonic-gate for (;;) { 293*61961e0fSrobinson if (*p == '\0') /* found end of line */ 2947c478bd9Sstevel@tonic-gate return (0); 2957c478bd9Sstevel@tonic-gate p = eatwhite(p); 296*61961e0fSrobinson if (*p == '\0') 2977c478bd9Sstevel@tonic-gate return (-1); 2987c478bd9Sstevel@tonic-gate tp = p; 2997c478bd9Sstevel@tonic-gate while (*tp && !isspace(*tp) && (*tp != ',')) 3007c478bd9Sstevel@tonic-gate tp++; 3017c478bd9Sstevel@tonic-gate if (*tp) 3027c478bd9Sstevel@tonic-gate *tp++ = '\0'; 3037c478bd9Sstevel@tonic-gate if (ioctl(fd, I_PUSH, p) < 0) { 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate /* 3067c478bd9Sstevel@tonic-gate * try to pop all that we've done, if pop fails it doesn't matter because 3077c478bd9Sstevel@tonic-gate * nothing can be done anyhow 3087c478bd9Sstevel@tonic-gate */ 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate for (i = 0; i < npush; ++i) 311*61961e0fSrobinson (void) ioctl(fd, I_POP, 0); 3127c478bd9Sstevel@tonic-gate return (-1); 313*61961e0fSrobinson } 3147c478bd9Sstevel@tonic-gate /* count the number of modules we've pushed */ 3157c478bd9Sstevel@tonic-gate npush++; 3167c478bd9Sstevel@tonic-gate p = tp; 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate /* 3227c478bd9Sstevel@tonic-gate * dopop - handle a `pop' command 3237c478bd9Sstevel@tonic-gate * 3247c478bd9Sstevel@tonic-gate * args: fd - file descriptor to pop from 3257c478bd9Sstevel@tonic-gate * p - name of module to pop to or ALL (null means pop top only) 3267c478bd9Sstevel@tonic-gate */ 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate static int 3307c478bd9Sstevel@tonic-gate dopop(int fd, char *p) 3317c478bd9Sstevel@tonic-gate { 3327c478bd9Sstevel@tonic-gate char *modp; /* module name from argument to pop */ 3337c478bd9Sstevel@tonic-gate char buf[FMNAMESZ + 1]; /* scratch buffer */ 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate if (*p == '\0') { 3367c478bd9Sstevel@tonic-gate /* just a pop with no args */ 337*61961e0fSrobinson if (ioctl(fd, I_POP, 0) < 0) 3387c478bd9Sstevel@tonic-gate return (-1); 3397c478bd9Sstevel@tonic-gate return (0); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate /* skip any whitespace in between */ 3437c478bd9Sstevel@tonic-gate p = eatwhite(p); 3447c478bd9Sstevel@tonic-gate modp = p; 3457c478bd9Sstevel@tonic-gate /* find end of module name */ 3467c478bd9Sstevel@tonic-gate while (*p && !isspace(*p)) 3477c478bd9Sstevel@tonic-gate p++; 3487c478bd9Sstevel@tonic-gate 349*61961e0fSrobinson if (*p) /* if not end of line, extra junk on line */ 3507c478bd9Sstevel@tonic-gate return (-1); 351*61961e0fSrobinson if (strcmp(modp, "ALL") == 0) { 3527c478bd9Sstevel@tonic-gate /* it's the magic name, pop them all */ 3537c478bd9Sstevel@tonic-gate while (ioctl(fd, I_POP, 0) == 0) 3547c478bd9Sstevel@tonic-gate ; 3557c478bd9Sstevel@tonic-gate /* After all popped, we'll get an EINVAL, which is expected */ 356*61961e0fSrobinson if (errno != EINVAL) 3577c478bd9Sstevel@tonic-gate return (-1); 3587c478bd9Sstevel@tonic-gate return (0); 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate /* check to see if the named module is on the stream */ 361*61961e0fSrobinson if (ioctl(fd, I_FIND, modp) != 1) 3627c478bd9Sstevel@tonic-gate return (-1); 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate /* pop them until the right one is on top */ 3657c478bd9Sstevel@tonic-gate for (;;) { 366*61961e0fSrobinson if (ioctl(fd, I_LOOK, buf) < 0) 3677c478bd9Sstevel@tonic-gate return (-1); 368*61961e0fSrobinson if (strcmp(modp, buf) == 0) 3697c478bd9Sstevel@tonic-gate /* we're done */ 3707c478bd9Sstevel@tonic-gate return (0); 371*61961e0fSrobinson if (ioctl(fd, I_POP, 0) < 0) 3727c478bd9Sstevel@tonic-gate return (-1); 3737c478bd9Sstevel@tonic-gate } 374*61961e0fSrobinson /* NOTREACHED */ 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate /* 3797c478bd9Sstevel@tonic-gate * dorun - handle a `run' command 3807c478bd9Sstevel@tonic-gate * 3817c478bd9Sstevel@tonic-gate * args: p - command line to run 3827c478bd9Sstevel@tonic-gate * waitflag - flag indicating whether a wait should be done 3837c478bd9Sstevel@tonic-gate */ 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate static int 3877c478bd9Sstevel@tonic-gate dorun(char *p, int waitflg) 3887c478bd9Sstevel@tonic-gate { 3897c478bd9Sstevel@tonic-gate char *tp; /* scratch pointer */ 3907c478bd9Sstevel@tonic-gate char *ep; /* scratch pointer (end of token) */ 3917c478bd9Sstevel@tonic-gate char savech; /* hold area */ 3927c478bd9Sstevel@tonic-gate int status; /* return status from wait */ 3937c478bd9Sstevel@tonic-gate pid_t pid; /* pid of child proc */ 3947c478bd9Sstevel@tonic-gate pid_t rpid; /* returned pid from wait */ 3957c478bd9Sstevel@tonic-gate void (*func)(); /* return from signal */ 3967c478bd9Sstevel@tonic-gate 397*61961e0fSrobinson if (*p == '\0') 3987c478bd9Sstevel@tonic-gate return (-1); 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate /* 4017c478bd9Sstevel@tonic-gate * get first token 4027c478bd9Sstevel@tonic-gate */ 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate for (tp = p; *tp && !isspace(*tp); ++tp) 4057c478bd9Sstevel@tonic-gate ; 4067c478bd9Sstevel@tonic-gate savech = '\0'; 4077c478bd9Sstevel@tonic-gate if (*tp) { 4087c478bd9Sstevel@tonic-gate savech = *tp; 4097c478bd9Sstevel@tonic-gate *tp = '\0'; 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate /* 4137c478bd9Sstevel@tonic-gate * look for built-in's 4147c478bd9Sstevel@tonic-gate */ 4157c478bd9Sstevel@tonic-gate 416*61961e0fSrobinson if (strcmp(p, "cd") == 0) { 4177c478bd9Sstevel@tonic-gate *tp = savech; 4187c478bd9Sstevel@tonic-gate tp = eatwhite(tp); 4197c478bd9Sstevel@tonic-gate if (*tp == '\0') 4207c478bd9Sstevel@tonic-gate /* if nothing there, try to cd to $HOME */ 4217c478bd9Sstevel@tonic-gate tp = getenv("HOME"); 422*61961e0fSrobinson if (chdir(tp) < 0) 4237c478bd9Sstevel@tonic-gate return (-1); 424*61961e0fSrobinson } else if (strcmp(p, "ulimit") == 0) { 4257c478bd9Sstevel@tonic-gate *tp = savech; 4267c478bd9Sstevel@tonic-gate tp = eatwhite(tp); 4277c478bd9Sstevel@tonic-gate /* must have an argument */ 428*61961e0fSrobinson if (*tp == '\0') 4297c478bd9Sstevel@tonic-gate return (-1); 4307c478bd9Sstevel@tonic-gate /* make sure nothing appears on line after arg */ 4317c478bd9Sstevel@tonic-gate for (ep = tp; *ep && !isspace(*ep); ++ep) 4327c478bd9Sstevel@tonic-gate ; 4337c478bd9Sstevel@tonic-gate ep = eatwhite(ep); 434*61961e0fSrobinson if (*ep) 4357c478bd9Sstevel@tonic-gate return (-1); 436*61961e0fSrobinson if (!isdigit(*tp)) 4377c478bd9Sstevel@tonic-gate return (-1); 4387c478bd9Sstevel@tonic-gate 439*61961e0fSrobinson if (ulimit(2, atoi(tp)) < 0) 4407c478bd9Sstevel@tonic-gate return (-1); 441*61961e0fSrobinson } else if (strcmp(p, "umask") == 0) { 4427c478bd9Sstevel@tonic-gate *tp = savech; 4437c478bd9Sstevel@tonic-gate tp = eatwhite(tp); 4447c478bd9Sstevel@tonic-gate /* must have an argument */ 445*61961e0fSrobinson if (*tp == '\0') 4467c478bd9Sstevel@tonic-gate return (-1); 4477c478bd9Sstevel@tonic-gate /* make sure nothing appears on line after arg */ 4487c478bd9Sstevel@tonic-gate for (ep = tp; *ep && !isspace(*ep); ++ep) 4497c478bd9Sstevel@tonic-gate ; 4507c478bd9Sstevel@tonic-gate ep = eatwhite(ep); 451*61961e0fSrobinson if (*ep) 4527c478bd9Sstevel@tonic-gate return (-1); 453*61961e0fSrobinson if (!isdigit(*tp)) 4547c478bd9Sstevel@tonic-gate return (-1); 4557c478bd9Sstevel@tonic-gate (void) umask(strtol(tp, NULL, 8)); 4567c478bd9Sstevel@tonic-gate } else { 4577c478bd9Sstevel@tonic-gate /* not a built-in */ 4587c478bd9Sstevel@tonic-gate *tp = savech; 4597c478bd9Sstevel@tonic-gate func = signal(SIGCLD, SIG_DFL); 4607c478bd9Sstevel@tonic-gate if ((pid = fork()) < 0) { 461*61961e0fSrobinson (void) signal(SIGCLD, func); 4627c478bd9Sstevel@tonic-gate return (-1); 463*61961e0fSrobinson } 464*61961e0fSrobinson if (pid) { 4657c478bd9Sstevel@tonic-gate if (waitflg == WAIT) { 4667c478bd9Sstevel@tonic-gate status = 0; 4677c478bd9Sstevel@tonic-gate rpid = -1; 4687c478bd9Sstevel@tonic-gate while (rpid != pid) 4697c478bd9Sstevel@tonic-gate rpid = wait(&status); 4707c478bd9Sstevel@tonic-gate if (status) { 4717c478bd9Sstevel@tonic-gate /* child failed */ 472*61961e0fSrobinson (void) signal(SIGCLD, func); 4737c478bd9Sstevel@tonic-gate return (-1); 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate } 476*61961e0fSrobinson (void) signal(SIGCLD, func); 4777c478bd9Sstevel@tonic-gate } else { 4787c478bd9Sstevel@tonic-gate /* set IFS for security */ 4797c478bd9Sstevel@tonic-gate (void) putenv("IFS=\" \""); 4807c478bd9Sstevel@tonic-gate /* 4817c478bd9Sstevel@tonic-gate * need to close all files to prevent unauthorized 4827c478bd9Sstevel@tonic-gate * access in the children. Setup stdin, stdout, 4837c478bd9Sstevel@tonic-gate * and stderr to /dev/null. 4847c478bd9Sstevel@tonic-gate */ 4857c478bd9Sstevel@tonic-gate closefrom(0); 4867c478bd9Sstevel@tonic-gate /* stdin */ 487*61961e0fSrobinson if (open("/dev/null", O_RDWR) != 0) 4887c478bd9Sstevel@tonic-gate return (-1); 4897c478bd9Sstevel@tonic-gate /* stdout */ 490*61961e0fSrobinson if (dup(0) != 1) 4917c478bd9Sstevel@tonic-gate return (-1); 4927c478bd9Sstevel@tonic-gate /* stderr */ 493*61961e0fSrobinson if (dup(0) != 2) 4947c478bd9Sstevel@tonic-gate return (-1); 495*61961e0fSrobinson (void) execle("/usr/bin/sh", "sh", "-c", 496*61961e0fSrobinson p, 0, _environ); 497*61961e0fSrobinson /* 498*61961e0fSrobinson * if we get here, there is a problem - remember that 499*61961e0fSrobinson * this is the child 500*61961e0fSrobinson */ 5017c478bd9Sstevel@tonic-gate exit(1); 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate return (0); 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate /* 5097c478bd9Sstevel@tonic-gate * eatwhite - swallow any leading whitespace, return pointer to first 5107c478bd9Sstevel@tonic-gate * non-white space character or to terminating null character 5117c478bd9Sstevel@tonic-gate * if nothing else is there 5127c478bd9Sstevel@tonic-gate * 5137c478bd9Sstevel@tonic-gate * args: p - string to parse 5147c478bd9Sstevel@tonic-gate */ 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate static char * 5177c478bd9Sstevel@tonic-gate eatwhite(char *p) 5187c478bd9Sstevel@tonic-gate { 5197c478bd9Sstevel@tonic-gate while (*p && isspace(*p)) 5207c478bd9Sstevel@tonic-gate p++; 5217c478bd9Sstevel@tonic-gate return (p); 5227c478bd9Sstevel@tonic-gate } 523