1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 30*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <stdio.h> 34*7c478bd9Sstevel@tonic-gate #include <string.h> 35*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 36*7c478bd9Sstevel@tonic-gate #include <unistd.h> 37*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 38*7c478bd9Sstevel@tonic-gate #include <ulimit.h> 39*7c478bd9Sstevel@tonic-gate #include <wait.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 41*7c478bd9Sstevel@tonic-gate #include <rpc/trace.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 43*7c478bd9Sstevel@tonic-gate #include <stropts.h> 44*7c478bd9Sstevel@tonic-gate #include <ctype.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 46*7c478bd9Sstevel@tonic-gate #include <errno.h> 47*7c478bd9Sstevel@tonic-gate #include <signal.h> 48*7c478bd9Sstevel@tonic-gate #include "sac.h" 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate #if defined(sparc) 51*7c478bd9Sstevel@tonic-gate #define _STAT _stat 52*7c478bd9Sstevel@tonic-gate #define _FSTAT _fstat 53*7c478bd9Sstevel@tonic-gate #else /* !sparc */ 54*7c478bd9Sstevel@tonic-gate #define _STAT stat 55*7c478bd9Sstevel@tonic-gate #define _FSTAT fstat 56*7c478bd9Sstevel@tonic-gate #endif /* sparc */ 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate extern int _stat(const char *, struct stat *); 59*7c478bd9Sstevel@tonic-gate extern int _fstat(int, struct stat *); 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate #define COMMENT '#' 62*7c478bd9Sstevel@tonic-gate #define NOWAIT 0 63*7c478bd9Sstevel@tonic-gate #define WAIT 1 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate extern char **_environ; 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate static char *eatwhite(); 68*7c478bd9Sstevel@tonic-gate static int doassign(); 69*7c478bd9Sstevel@tonic-gate static int dopush(); 70*7c478bd9Sstevel@tonic-gate static int dopop(); 71*7c478bd9Sstevel@tonic-gate static int dorun(); 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate /* 74*7c478bd9Sstevel@tonic-gate * doconfig - the configuration script interpreter, if all is ok, 75*7c478bd9Sstevel@tonic-gate * return 0. If there is a "system" error, return -1. 76*7c478bd9Sstevel@tonic-gate * If there is an error performing a command, or there 77*7c478bd9Sstevel@tonic-gate * is a syntax error, return the line number in error. 78*7c478bd9Sstevel@tonic-gate * 79*7c478bd9Sstevel@tonic-gate * args: fd - file descriptor to push and pop from 80*7c478bd9Sstevel@tonic-gate * script - name of the configuration script 81*7c478bd9Sstevel@tonic-gate * rflag - restriction flag to determine what "commands" 82*7c478bd9Sstevel@tonic-gate * can be run 83*7c478bd9Sstevel@tonic-gate */ 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate int 86*7c478bd9Sstevel@tonic-gate doconfig(int fd, char *script, long rflag) 87*7c478bd9Sstevel@tonic-gate { 88*7c478bd9Sstevel@tonic-gate int line; /* line counter */ 89*7c478bd9Sstevel@tonic-gate struct stat statbuf; /* place for stat */ 90*7c478bd9Sstevel@tonic-gate FILE *fp; /* file pointer for config script */ 91*7c478bd9Sstevel@tonic-gate char buf[BUFSIZ + 1]; /* scratch buffer */ 92*7c478bd9Sstevel@tonic-gate char *bp; /* scratch pointer */ 93*7c478bd9Sstevel@tonic-gate char *p; /* scratch pointer */ 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate /* if the script does not exist, then there is nothing to do */ 96*7c478bd9Sstevel@tonic-gate trace3(TR_doconfig, 0, fd, rflag); 97*7c478bd9Sstevel@tonic-gate if (_STAT(script, &statbuf) < 0) { 98*7c478bd9Sstevel@tonic-gate trace1(TR_doconfig, 1); 99*7c478bd9Sstevel@tonic-gate return (0); 100*7c478bd9Sstevel@tonic-gate } 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate fp = fopen(script, "r"); 103*7c478bd9Sstevel@tonic-gate if (fp == NULL) { 104*7c478bd9Sstevel@tonic-gate trace1(TR_doconfig, 1); 105*7c478bd9Sstevel@tonic-gate return (-1); 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate line = 0; 109*7c478bd9Sstevel@tonic-gate while (fgets(buf, BUFSIZ, fp)) { 110*7c478bd9Sstevel@tonic-gate line++; 111*7c478bd9Sstevel@tonic-gate p = strchr(buf, '\n'); 112*7c478bd9Sstevel@tonic-gate /* if no \n, then line is too long */ 113*7c478bd9Sstevel@tonic-gate if (p == NULL) { 114*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 115*7c478bd9Sstevel@tonic-gate trace1(TR_doconfig, 1); 116*7c478bd9Sstevel@tonic-gate return (line); 117*7c478bd9Sstevel@tonic-gate } 118*7c478bd9Sstevel@tonic-gate *p = '\0'; 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate /* remove comments */ 121*7c478bd9Sstevel@tonic-gate p = strchr(buf, COMMENT); 122*7c478bd9Sstevel@tonic-gate if (p) 123*7c478bd9Sstevel@tonic-gate *p = '\0'; 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate /* remove leading whitespace */ 126*7c478bd9Sstevel@tonic-gate bp = eatwhite(buf); 127*7c478bd9Sstevel@tonic-gate /* see if anything is left */ 128*7c478bd9Sstevel@tonic-gate if (*bp == '\0') 129*7c478bd9Sstevel@tonic-gate continue; 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate /* remove trailing whitespace */ 132*7c478bd9Sstevel@tonic-gate p = &buf[strlen(buf) - 1]; 133*7c478bd9Sstevel@tonic-gate while (*p && isspace(*p)) 134*7c478bd9Sstevel@tonic-gate *p-- = '\0'; 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate /* get the command */ 137*7c478bd9Sstevel@tonic-gate p = bp; 138*7c478bd9Sstevel@tonic-gate while (*p && !isspace(*p)) 139*7c478bd9Sstevel@tonic-gate p++; 140*7c478bd9Sstevel@tonic-gate if (*p) 141*7c478bd9Sstevel@tonic-gate *p++ = '\0'; 142*7c478bd9Sstevel@tonic-gate /* skip any whitespace here too (between command and args) */ 143*7c478bd9Sstevel@tonic-gate p = eatwhite(p); 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate if (!strcmp(bp, "assign")) { 146*7c478bd9Sstevel@tonic-gate if ((rflag & NOASSIGN) || doassign(p)) { 147*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 148*7c478bd9Sstevel@tonic-gate trace1(TR_doconfig, 1); 149*7c478bd9Sstevel@tonic-gate return (line); 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate } else if (!strcmp(bp, "push")) { 152*7c478bd9Sstevel@tonic-gate if (dopush(fd, p)) { 153*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 154*7c478bd9Sstevel@tonic-gate trace1(TR_doconfig, 1); 155*7c478bd9Sstevel@tonic-gate return (line); 156*7c478bd9Sstevel@tonic-gate } 157*7c478bd9Sstevel@tonic-gate } else if (!strcmp(bp, "pop")) { 158*7c478bd9Sstevel@tonic-gate if (dopop(fd, p)) { 159*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 160*7c478bd9Sstevel@tonic-gate trace1(TR_doconfig, 1); 161*7c478bd9Sstevel@tonic-gate return (line); 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate } else if (!strcmp(bp, "run")) { 164*7c478bd9Sstevel@tonic-gate if ((rflag & NORUN) || dorun(p, NOWAIT)) { 165*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 166*7c478bd9Sstevel@tonic-gate trace1(TR_doconfig, 1); 167*7c478bd9Sstevel@tonic-gate return (line); 168*7c478bd9Sstevel@tonic-gate } 169*7c478bd9Sstevel@tonic-gate } else if (!strcmp(bp, "runwait")) { 170*7c478bd9Sstevel@tonic-gate if ((rflag & NORUN) || dorun(p, WAIT)) { 171*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 172*7c478bd9Sstevel@tonic-gate trace1(TR_doconfig, 1); 173*7c478bd9Sstevel@tonic-gate return (line); 174*7c478bd9Sstevel@tonic-gate } 175*7c478bd9Sstevel@tonic-gate } else { 176*7c478bd9Sstevel@tonic-gate /* unknown command */ 177*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 178*7c478bd9Sstevel@tonic-gate trace1(TR_doconfig, 1); 179*7c478bd9Sstevel@tonic-gate return (line); 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate if (!feof(fp)) { 183*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 184*7c478bd9Sstevel@tonic-gate trace1(TR_doconfig, 1); 185*7c478bd9Sstevel@tonic-gate return (-1); 186*7c478bd9Sstevel@tonic-gate } else { 187*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 188*7c478bd9Sstevel@tonic-gate trace1(TR_doconfig, 1); 189*7c478bd9Sstevel@tonic-gate return (0); 190*7c478bd9Sstevel@tonic-gate } 191*7c478bd9Sstevel@tonic-gate } 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate /* 195*7c478bd9Sstevel@tonic-gate * doassign - handle an `assign' command 196*7c478bd9Sstevel@tonic-gate * 197*7c478bd9Sstevel@tonic-gate * args: p - assignment string 198*7c478bd9Sstevel@tonic-gate */ 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate static int 202*7c478bd9Sstevel@tonic-gate doassign(char *p) 203*7c478bd9Sstevel@tonic-gate { 204*7c478bd9Sstevel@tonic-gate char *var; /* environment variable to be assigned */ 205*7c478bd9Sstevel@tonic-gate char val[BUFSIZ]; /* and the value to be assigned to it */ 206*7c478bd9Sstevel@tonic-gate char scratch[BUFSIZ]; /* scratch buffer */ 207*7c478bd9Sstevel@tonic-gate char delim; /* delimiter char seen (for quoted strings ) */ 208*7c478bd9Sstevel@tonic-gate char *tp; /* scratch pointer */ 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate trace1(TR_doassign, 0); 211*7c478bd9Sstevel@tonic-gate if (*p == '\0') { 212*7c478bd9Sstevel@tonic-gate trace1(TR_doassign, 1); 213*7c478bd9Sstevel@tonic-gate return (-1); 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate var = p; 216*7c478bd9Sstevel@tonic-gate /* skip first token, but stop if we see a '=' */ 217*7c478bd9Sstevel@tonic-gate while (*p && !isspace(*p) && (*p != '=')) 218*7c478bd9Sstevel@tonic-gate p++; 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate /* if we found end of string, it's an error */ 221*7c478bd9Sstevel@tonic-gate if (*p == '\0') { 222*7c478bd9Sstevel@tonic-gate trace1(TR_doassign, 1); 223*7c478bd9Sstevel@tonic-gate return (-1); 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate /* if we found a space, look for the '=', otherwise it's an error */ 227*7c478bd9Sstevel@tonic-gate if (isspace(*p)) { 228*7c478bd9Sstevel@tonic-gate *p++ = '\0'; 229*7c478bd9Sstevel@tonic-gate while (*p && isspace(*p)) 230*7c478bd9Sstevel@tonic-gate p++; 231*7c478bd9Sstevel@tonic-gate if (*p == '\0') { 232*7c478bd9Sstevel@tonic-gate trace1(TR_doassign, 1); 233*7c478bd9Sstevel@tonic-gate return (-1); 234*7c478bd9Sstevel@tonic-gate } 235*7c478bd9Sstevel@tonic-gate if (*p == '=') 236*7c478bd9Sstevel@tonic-gate p++; 237*7c478bd9Sstevel@tonic-gate else { 238*7c478bd9Sstevel@tonic-gate trace1(TR_doassign, 1); 239*7c478bd9Sstevel@tonic-gate return (-1); 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate } else { 242*7c478bd9Sstevel@tonic-gate /* skip over '=' */ 243*7c478bd9Sstevel@tonic-gate *p = '\0'; 244*7c478bd9Sstevel@tonic-gate p++; 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate /* skip over any whitespace */ 248*7c478bd9Sstevel@tonic-gate p = eatwhite(p); 249*7c478bd9Sstevel@tonic-gate if (*p == '\'' || *p == '"') { 250*7c478bd9Sstevel@tonic-gate /* handle quoted values */ 251*7c478bd9Sstevel@tonic-gate delim = *p++; 252*7c478bd9Sstevel@tonic-gate tp = val; 253*7c478bd9Sstevel@tonic-gate for (;;) { 254*7c478bd9Sstevel@tonic-gate if (*p == '\0') { 255*7c478bd9Sstevel@tonic-gate trace1(TR_doassign, 1); 256*7c478bd9Sstevel@tonic-gate return (-1); 257*7c478bd9Sstevel@tonic-gate } else if (*p == delim) { 258*7c478bd9Sstevel@tonic-gate if (*(p - 1) != '\\') 259*7c478bd9Sstevel@tonic-gate break; 260*7c478bd9Sstevel@tonic-gate else 261*7c478bd9Sstevel@tonic-gate *(tp - 1) = *p++; 262*7c478bd9Sstevel@tonic-gate } else 263*7c478bd9Sstevel@tonic-gate *tp++ = *p++; 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate *tp = '\0'; 266*7c478bd9Sstevel@tonic-gate /* these assignments make the comment below true (values of tp and p */ 267*7c478bd9Sstevel@tonic-gate tp = ++p; 268*7c478bd9Sstevel@tonic-gate p = val; 269*7c478bd9Sstevel@tonic-gate } else { 270*7c478bd9Sstevel@tonic-gate tp = p; 271*7c478bd9Sstevel@tonic-gate /* look for end of token */ 272*7c478bd9Sstevel@tonic-gate while (*tp && !isspace(*tp)) 273*7c478bd9Sstevel@tonic-gate tp++; 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate /* 277*7c478bd9Sstevel@tonic-gate * at this point, p points to the value, and tp points to the 278*7c478bd9Sstevel@tonic-gate * end of the token. check to make sure there is no garbage on 279*7c478bd9Sstevel@tonic-gate * the end of the line 280*7c478bd9Sstevel@tonic-gate */ 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate if (*tp) { 283*7c478bd9Sstevel@tonic-gate trace1(TR_doassign, 1); 284*7c478bd9Sstevel@tonic-gate return (-1); 285*7c478bd9Sstevel@tonic-gate } 286*7c478bd9Sstevel@tonic-gate sprintf(scratch, "%s=%s", var, p); 287*7c478bd9Sstevel@tonic-gate /* note: need to malloc fresh space so putenv works */ 288*7c478bd9Sstevel@tonic-gate tp = malloc(strlen(scratch) + 1); 289*7c478bd9Sstevel@tonic-gate if (tp == NULL) { 290*7c478bd9Sstevel@tonic-gate trace1(TR_doassign, 1); 291*7c478bd9Sstevel@tonic-gate return (-1); 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate strcpy(tp, scratch); 294*7c478bd9Sstevel@tonic-gate if (putenv(tp)) { 295*7c478bd9Sstevel@tonic-gate trace1(TR_doassign, 1); 296*7c478bd9Sstevel@tonic-gate return (-1); 297*7c478bd9Sstevel@tonic-gate } else { 298*7c478bd9Sstevel@tonic-gate trace1(TR_doassign, 1); 299*7c478bd9Sstevel@tonic-gate return (0); 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate /* 305*7c478bd9Sstevel@tonic-gate * dopush - handle a `push' command 306*7c478bd9Sstevel@tonic-gate * 307*7c478bd9Sstevel@tonic-gate * args: fd - file descriptor to push on 308*7c478bd9Sstevel@tonic-gate * p - list of modules to push 309*7c478bd9Sstevel@tonic-gate */ 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate static int 313*7c478bd9Sstevel@tonic-gate dopush(int fd, char *p) 314*7c478bd9Sstevel@tonic-gate { 315*7c478bd9Sstevel@tonic-gate char *tp; /* scratch pointer */ 316*7c478bd9Sstevel@tonic-gate int i; /* scratch variable */ 317*7c478bd9Sstevel@tonic-gate int npush; /* count # of modules pushed */ 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate trace2(TR_dopush, 0, fd); 320*7c478bd9Sstevel@tonic-gate if (*p == '\0') { 321*7c478bd9Sstevel@tonic-gate trace1(TR_dopush, 1); 322*7c478bd9Sstevel@tonic-gate return (-1); 323*7c478bd9Sstevel@tonic-gate } 324*7c478bd9Sstevel@tonic-gate npush = 0; 325*7c478bd9Sstevel@tonic-gate for (;;) { 326*7c478bd9Sstevel@tonic-gate if (*p == '\0') { /* found end of line */ 327*7c478bd9Sstevel@tonic-gate trace1(TR_dopush, 1); 328*7c478bd9Sstevel@tonic-gate return (0); 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate p = eatwhite(p); 331*7c478bd9Sstevel@tonic-gate if (*p == '\0') { 332*7c478bd9Sstevel@tonic-gate trace1(TR_dopush, 1); 333*7c478bd9Sstevel@tonic-gate return (-1); 334*7c478bd9Sstevel@tonic-gate } 335*7c478bd9Sstevel@tonic-gate tp = p; 336*7c478bd9Sstevel@tonic-gate while (*tp && !isspace(*tp) && (*tp != ',')) 337*7c478bd9Sstevel@tonic-gate tp++; 338*7c478bd9Sstevel@tonic-gate if (*tp) 339*7c478bd9Sstevel@tonic-gate *tp++ = '\0'; 340*7c478bd9Sstevel@tonic-gate if (ioctl(fd, I_PUSH, p) < 0) { 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate /* 343*7c478bd9Sstevel@tonic-gate * try to pop all that we've done, if pop fails it doesn't matter because 344*7c478bd9Sstevel@tonic-gate * nothing can be done anyhow 345*7c478bd9Sstevel@tonic-gate */ 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate for (i = 0; i < npush; ++i) 348*7c478bd9Sstevel@tonic-gate ioctl(fd, I_POP, 0); 349*7c478bd9Sstevel@tonic-gate trace1(TR_dopush, 1); 350*7c478bd9Sstevel@tonic-gate return (-1); 351*7c478bd9Sstevel@tonic-gate } else { 352*7c478bd9Sstevel@tonic-gate /* count the number of modules we've pushed */ 353*7c478bd9Sstevel@tonic-gate npush++; 354*7c478bd9Sstevel@tonic-gate p = tp; 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate /* 361*7c478bd9Sstevel@tonic-gate * dopop - handle a `pop' command 362*7c478bd9Sstevel@tonic-gate * 363*7c478bd9Sstevel@tonic-gate * args: fd - file descriptor to pop from 364*7c478bd9Sstevel@tonic-gate * p - name of module to pop to or ALL (null means pop top only) 365*7c478bd9Sstevel@tonic-gate */ 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate static int 369*7c478bd9Sstevel@tonic-gate dopop(int fd, char *p) 370*7c478bd9Sstevel@tonic-gate { 371*7c478bd9Sstevel@tonic-gate char *modp; /* module name from argument to pop */ 372*7c478bd9Sstevel@tonic-gate char buf[FMNAMESZ + 1]; /* scratch buffer */ 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate trace2(TR_dopop, 0, fd); 375*7c478bd9Sstevel@tonic-gate if (*p == '\0') { 376*7c478bd9Sstevel@tonic-gate /* just a pop with no args */ 377*7c478bd9Sstevel@tonic-gate if (ioctl(fd, I_POP, 0) < 0) { 378*7c478bd9Sstevel@tonic-gate trace1(TR_dopop, 1); 379*7c478bd9Sstevel@tonic-gate return (-1); 380*7c478bd9Sstevel@tonic-gate } else { 381*7c478bd9Sstevel@tonic-gate trace1(TR_dopop, 1); 382*7c478bd9Sstevel@tonic-gate return (0); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate /* skip any whitespace in between */ 387*7c478bd9Sstevel@tonic-gate p = eatwhite(p); 388*7c478bd9Sstevel@tonic-gate modp = p; 389*7c478bd9Sstevel@tonic-gate /* find end of module name */ 390*7c478bd9Sstevel@tonic-gate while (*p && !isspace(*p)) 391*7c478bd9Sstevel@tonic-gate p++; 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate if (*p) { /* if not end of line, extra junk on line */ 394*7c478bd9Sstevel@tonic-gate trace1(TR_dopop, 1); 395*7c478bd9Sstevel@tonic-gate return (-1); 396*7c478bd9Sstevel@tonic-gate } 397*7c478bd9Sstevel@tonic-gate if (!strcmp(modp, "ALL")) { 398*7c478bd9Sstevel@tonic-gate /* it's the magic name, pop them all */ 399*7c478bd9Sstevel@tonic-gate while (ioctl(fd, I_POP, 0) == 0) 400*7c478bd9Sstevel@tonic-gate ; 401*7c478bd9Sstevel@tonic-gate /* After all popped, we'll get an EINVAL, which is expected */ 402*7c478bd9Sstevel@tonic-gate if (errno != EINVAL) { 403*7c478bd9Sstevel@tonic-gate trace1(TR_dopop, 1); 404*7c478bd9Sstevel@tonic-gate return (-1); 405*7c478bd9Sstevel@tonic-gate } else { 406*7c478bd9Sstevel@tonic-gate trace1(TR_dopop, 1); 407*7c478bd9Sstevel@tonic-gate return (0); 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate } else { 410*7c478bd9Sstevel@tonic-gate /* check to see if the named module is on the stream */ 411*7c478bd9Sstevel@tonic-gate if (ioctl(fd, I_FIND, modp) != 1) { 412*7c478bd9Sstevel@tonic-gate trace1(TR_dopop, 1); 413*7c478bd9Sstevel@tonic-gate return (-1); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate /* pop them until the right one is on top */ 417*7c478bd9Sstevel@tonic-gate for (;;) { 418*7c478bd9Sstevel@tonic-gate if (ioctl(fd, I_LOOK, buf) < 0) { 419*7c478bd9Sstevel@tonic-gate trace1(TR_dopop, 1); 420*7c478bd9Sstevel@tonic-gate return (-1); 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate if (!strcmp(modp, buf)) { 423*7c478bd9Sstevel@tonic-gate trace1(TR_dopop, 1); 424*7c478bd9Sstevel@tonic-gate /* we're done */ 425*7c478bd9Sstevel@tonic-gate return (0); 426*7c478bd9Sstevel@tonic-gate } 427*7c478bd9Sstevel@tonic-gate if (ioctl(fd, I_POP, 0) < 0) { 428*7c478bd9Sstevel@tonic-gate trace1(TR_dopop, 1); 429*7c478bd9Sstevel@tonic-gate return (-1); 430*7c478bd9Sstevel@tonic-gate } 431*7c478bd9Sstevel@tonic-gate } 432*7c478bd9Sstevel@tonic-gate } 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate /* 437*7c478bd9Sstevel@tonic-gate * dorun - handle a `run' command 438*7c478bd9Sstevel@tonic-gate * 439*7c478bd9Sstevel@tonic-gate * args: p - command line to run 440*7c478bd9Sstevel@tonic-gate * waitflag - flag indicating whether a wait should be done 441*7c478bd9Sstevel@tonic-gate */ 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate static int 445*7c478bd9Sstevel@tonic-gate dorun(char *p, int waitflg) 446*7c478bd9Sstevel@tonic-gate { 447*7c478bd9Sstevel@tonic-gate char *tp; /* scratch pointer */ 448*7c478bd9Sstevel@tonic-gate char *ep; /* scratch pointer (end of token) */ 449*7c478bd9Sstevel@tonic-gate int nfiles; /* # of possibly open files */ 450*7c478bd9Sstevel@tonic-gate int i; /* scratch variable */ 451*7c478bd9Sstevel@tonic-gate char savech; /* hold area */ 452*7c478bd9Sstevel@tonic-gate int status; /* return status from wait */ 453*7c478bd9Sstevel@tonic-gate pid_t pid; /* pid of child proc */ 454*7c478bd9Sstevel@tonic-gate pid_t rpid; /* returned pid from wait */ 455*7c478bd9Sstevel@tonic-gate void (*func)(); /* return from signal */ 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate trace2(TR_dorun, 0, waitflg); 458*7c478bd9Sstevel@tonic-gate if (*p == '\0') { 459*7c478bd9Sstevel@tonic-gate trace1(TR_dorun, 1); 460*7c478bd9Sstevel@tonic-gate return (-1); 461*7c478bd9Sstevel@tonic-gate } 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate /* 464*7c478bd9Sstevel@tonic-gate * get first token 465*7c478bd9Sstevel@tonic-gate */ 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate for (tp = p; *tp && !isspace(*tp); ++tp) 468*7c478bd9Sstevel@tonic-gate ; 469*7c478bd9Sstevel@tonic-gate savech = '\0'; 470*7c478bd9Sstevel@tonic-gate if (*tp) { 471*7c478bd9Sstevel@tonic-gate savech = *tp; 472*7c478bd9Sstevel@tonic-gate *tp = '\0'; 473*7c478bd9Sstevel@tonic-gate } 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate /* 476*7c478bd9Sstevel@tonic-gate * look for built-in's 477*7c478bd9Sstevel@tonic-gate */ 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate if (!strcmp(p, "cd")) { 480*7c478bd9Sstevel@tonic-gate *tp = savech; 481*7c478bd9Sstevel@tonic-gate tp = eatwhite(tp); 482*7c478bd9Sstevel@tonic-gate if (*tp == '\0') 483*7c478bd9Sstevel@tonic-gate /* if nothing there, try to cd to $HOME */ 484*7c478bd9Sstevel@tonic-gate tp = getenv("HOME"); 485*7c478bd9Sstevel@tonic-gate if (chdir(tp) < 0) { 486*7c478bd9Sstevel@tonic-gate trace1(TR_dorun, 1); 487*7c478bd9Sstevel@tonic-gate return (-1); 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate } else if (!strcmp(p, "ulimit")) { 490*7c478bd9Sstevel@tonic-gate *tp = savech; 491*7c478bd9Sstevel@tonic-gate tp = eatwhite(tp); 492*7c478bd9Sstevel@tonic-gate /* must have an argument */ 493*7c478bd9Sstevel@tonic-gate if (*tp == '\0') { 494*7c478bd9Sstevel@tonic-gate trace1(TR_dorun, 1); 495*7c478bd9Sstevel@tonic-gate return (-1); 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate /* make sure nothing appears on line after arg */ 498*7c478bd9Sstevel@tonic-gate for (ep = tp; *ep && !isspace(*ep); ++ep) 499*7c478bd9Sstevel@tonic-gate ; 500*7c478bd9Sstevel@tonic-gate ep = eatwhite(ep); 501*7c478bd9Sstevel@tonic-gate if (*ep) { 502*7c478bd9Sstevel@tonic-gate trace1(TR_dorun, 1); 503*7c478bd9Sstevel@tonic-gate return (-1); 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate if (!isdigit(*tp)) { 506*7c478bd9Sstevel@tonic-gate trace1(TR_dorun, 1); 507*7c478bd9Sstevel@tonic-gate return (-1); 508*7c478bd9Sstevel@tonic-gate } 509*7c478bd9Sstevel@tonic-gate 510*7c478bd9Sstevel@tonic-gate if (ulimit(2, atoi(tp)) < 0) { 511*7c478bd9Sstevel@tonic-gate trace1(TR_dorun, 1); 512*7c478bd9Sstevel@tonic-gate return (-1); 513*7c478bd9Sstevel@tonic-gate } 514*7c478bd9Sstevel@tonic-gate } else if (!strcmp(p, "umask")) { 515*7c478bd9Sstevel@tonic-gate *tp = savech; 516*7c478bd9Sstevel@tonic-gate tp = eatwhite(tp); 517*7c478bd9Sstevel@tonic-gate /* must have an argument */ 518*7c478bd9Sstevel@tonic-gate if (*tp == '\0') { 519*7c478bd9Sstevel@tonic-gate trace1(TR_dorun, 1); 520*7c478bd9Sstevel@tonic-gate return (-1); 521*7c478bd9Sstevel@tonic-gate } 522*7c478bd9Sstevel@tonic-gate /* make sure nothing appears on line after arg */ 523*7c478bd9Sstevel@tonic-gate for (ep = tp; *ep && !isspace(*ep); ++ep) 524*7c478bd9Sstevel@tonic-gate ; 525*7c478bd9Sstevel@tonic-gate ep = eatwhite(ep); 526*7c478bd9Sstevel@tonic-gate if (*ep) { 527*7c478bd9Sstevel@tonic-gate trace1(TR_dorun, 1); 528*7c478bd9Sstevel@tonic-gate return (-1); 529*7c478bd9Sstevel@tonic-gate } 530*7c478bd9Sstevel@tonic-gate if (!isdigit(*tp)) { 531*7c478bd9Sstevel@tonic-gate trace1(TR_dorun, 1); 532*7c478bd9Sstevel@tonic-gate return (-1); 533*7c478bd9Sstevel@tonic-gate } 534*7c478bd9Sstevel@tonic-gate (void) umask(strtol(tp, NULL, 8)); 535*7c478bd9Sstevel@tonic-gate } else { 536*7c478bd9Sstevel@tonic-gate /* not a built-in */ 537*7c478bd9Sstevel@tonic-gate *tp = savech; 538*7c478bd9Sstevel@tonic-gate func = signal(SIGCLD, SIG_DFL); 539*7c478bd9Sstevel@tonic-gate if ((pid = fork()) < 0) { 540*7c478bd9Sstevel@tonic-gate signal(SIGCLD, func); 541*7c478bd9Sstevel@tonic-gate trace1(TR_dorun, 1); 542*7c478bd9Sstevel@tonic-gate return (-1); 543*7c478bd9Sstevel@tonic-gate } else if (pid) { 544*7c478bd9Sstevel@tonic-gate if (waitflg == WAIT) { 545*7c478bd9Sstevel@tonic-gate status = 0; 546*7c478bd9Sstevel@tonic-gate rpid = -1; 547*7c478bd9Sstevel@tonic-gate while (rpid != pid) 548*7c478bd9Sstevel@tonic-gate rpid = wait(&status); 549*7c478bd9Sstevel@tonic-gate if (status) { 550*7c478bd9Sstevel@tonic-gate /* child failed */ 551*7c478bd9Sstevel@tonic-gate signal(SIGCLD, func); 552*7c478bd9Sstevel@tonic-gate trace1(TR_dorun, 1); 553*7c478bd9Sstevel@tonic-gate return (-1); 554*7c478bd9Sstevel@tonic-gate } 555*7c478bd9Sstevel@tonic-gate } 556*7c478bd9Sstevel@tonic-gate signal(SIGCLD, func); 557*7c478bd9Sstevel@tonic-gate } else { 558*7c478bd9Sstevel@tonic-gate /* set IFS for security */ 559*7c478bd9Sstevel@tonic-gate (void) putenv("IFS=\" \""); 560*7c478bd9Sstevel@tonic-gate /* 561*7c478bd9Sstevel@tonic-gate * need to close all files to prevent unauthorized 562*7c478bd9Sstevel@tonic-gate * access in the children. Setup stdin, stdout, 563*7c478bd9Sstevel@tonic-gate * and stderr to /dev/null. 564*7c478bd9Sstevel@tonic-gate */ 565*7c478bd9Sstevel@tonic-gate nfiles = ulimit(4, 0); 566*7c478bd9Sstevel@tonic-gate closefrom(0); 567*7c478bd9Sstevel@tonic-gate /* stdin */ 568*7c478bd9Sstevel@tonic-gate if (open("/dev/null", O_RDWR) != 0) { 569*7c478bd9Sstevel@tonic-gate trace1(TR_dorun, 1); 570*7c478bd9Sstevel@tonic-gate return (-1); 571*7c478bd9Sstevel@tonic-gate } 572*7c478bd9Sstevel@tonic-gate /* stdout */ 573*7c478bd9Sstevel@tonic-gate if (dup(0) != 1) { 574*7c478bd9Sstevel@tonic-gate trace1(TR_dorun, 1); 575*7c478bd9Sstevel@tonic-gate return (-1); 576*7c478bd9Sstevel@tonic-gate } 577*7c478bd9Sstevel@tonic-gate /* stderr */ 578*7c478bd9Sstevel@tonic-gate if (dup(0) != 2) { 579*7c478bd9Sstevel@tonic-gate trace1(TR_dorun, 1); 580*7c478bd9Sstevel@tonic-gate return (-1); 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate execle("/usr/bin/sh", "sh", "-c", p, 0, _environ); 583*7c478bd9Sstevel@tonic-gate /* if we get here, there is a problem - remember that 584*7c478bd9Sstevel@tonic-gate this is the child */ 585*7c478bd9Sstevel@tonic-gate trace1(TR_dorun, 1); 586*7c478bd9Sstevel@tonic-gate exit(1); 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate } 589*7c478bd9Sstevel@tonic-gate trace1(TR_dorun, 1); 590*7c478bd9Sstevel@tonic-gate return (0); 591*7c478bd9Sstevel@tonic-gate } 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate /* 595*7c478bd9Sstevel@tonic-gate * eatwhite - swallow any leading whitespace, return pointer to first 596*7c478bd9Sstevel@tonic-gate * non-white space character or to terminating null character 597*7c478bd9Sstevel@tonic-gate * if nothing else is there 598*7c478bd9Sstevel@tonic-gate * 599*7c478bd9Sstevel@tonic-gate * args: p - string to parse 600*7c478bd9Sstevel@tonic-gate */ 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate static char * 603*7c478bd9Sstevel@tonic-gate eatwhite(char *p) 604*7c478bd9Sstevel@tonic-gate { 605*7c478bd9Sstevel@tonic-gate trace1(TR_eatwhite, 0); 606*7c478bd9Sstevel@tonic-gate while (*p && isspace(*p)) 607*7c478bd9Sstevel@tonic-gate p++; 608*7c478bd9Sstevel@tonic-gate trace1(TR_eatwhite, 1); 609*7c478bd9Sstevel@tonic-gate return (p); 610*7c478bd9Sstevel@tonic-gate } 611