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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate /* 27*7c478bd9Sstevel@tonic-gate * Copyright 1996,2002-2003 Sun Microsystems, Inc. All rights reserved. 28*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate /* 33*7c478bd9Sstevel@tonic-gate * 34*7c478bd9Sstevel@tonic-gate * UNIX shell 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate */ 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #include "defs.h" 40*7c478bd9Sstevel@tonic-gate #include <errno.h> 41*7c478bd9Sstevel@tonic-gate #include "sym.h" 42*7c478bd9Sstevel@tonic-gate #include "hash.h" 43*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/times.h> 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate pid_t parent; 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate /* ======== command execution ======== */ 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate execute(argt, xflags, errorflg, pf1, pf2) 52*7c478bd9Sstevel@tonic-gate struct trenod *argt; 53*7c478bd9Sstevel@tonic-gate int *pf1, *pf2; 54*7c478bd9Sstevel@tonic-gate { 55*7c478bd9Sstevel@tonic-gate /* 56*7c478bd9Sstevel@tonic-gate * `stakbot' is preserved by this routine 57*7c478bd9Sstevel@tonic-gate */ 58*7c478bd9Sstevel@tonic-gate register struct trenod *t; 59*7c478bd9Sstevel@tonic-gate unsigned char *sav = savstak(); 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate sigchk(); 62*7c478bd9Sstevel@tonic-gate if (!errorflg) 63*7c478bd9Sstevel@tonic-gate flags &= ~errflg; 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate if ((t = argt) && execbrk == 0) { 66*7c478bd9Sstevel@tonic-gate register int treeflgs; 67*7c478bd9Sstevel@tonic-gate register unsigned char **com; 68*7c478bd9Sstevel@tonic-gate int type; 69*7c478bd9Sstevel@tonic-gate short pos; 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate treeflgs = t->tretyp; 72*7c478bd9Sstevel@tonic-gate type = treeflgs & COMMSK; 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate switch (type) 75*7c478bd9Sstevel@tonic-gate { 76*7c478bd9Sstevel@tonic-gate case TFND: 77*7c478bd9Sstevel@tonic-gate { 78*7c478bd9Sstevel@tonic-gate struct fndnod *f = (struct fndnod *)t; 79*7c478bd9Sstevel@tonic-gate struct namnod *n = lookup(f->fndnam); 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate exitval = 0; 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate if (n->namflg & N_RDONLY) 84*7c478bd9Sstevel@tonic-gate failed(n->namid, wtfailed); 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate if (flags & rshflg && (n == &pathnod || 87*7c478bd9Sstevel@tonic-gate eq(n->namid, "SHELL"))) 88*7c478bd9Sstevel@tonic-gate failed(n->namid, restricted); 89*7c478bd9Sstevel@tonic-gate if (n->namflg & N_FUNCTN) 90*7c478bd9Sstevel@tonic-gate freefunc(n); 91*7c478bd9Sstevel@tonic-gate else 92*7c478bd9Sstevel@tonic-gate { 93*7c478bd9Sstevel@tonic-gate free(n->namval); 94*7c478bd9Sstevel@tonic-gate free(n->namenv); 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate n->namval = 0; 97*7c478bd9Sstevel@tonic-gate n->namflg &= ~(N_EXPORT | N_ENVCHG); 98*7c478bd9Sstevel@tonic-gate } 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate if (funcnt) 101*7c478bd9Sstevel@tonic-gate f->fndval->tretyp++; 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate n->namenv = (unsigned char *)f->fndval; 104*7c478bd9Sstevel@tonic-gate attrib(n, N_FUNCTN); 105*7c478bd9Sstevel@tonic-gate hash_func(n->namid); 106*7c478bd9Sstevel@tonic-gate break; 107*7c478bd9Sstevel@tonic-gate } 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate case TCOM: 110*7c478bd9Sstevel@tonic-gate { 111*7c478bd9Sstevel@tonic-gate unsigned char *a1, *name; 112*7c478bd9Sstevel@tonic-gate int argn, internal; 113*7c478bd9Sstevel@tonic-gate struct argnod *schain = gchain; 114*7c478bd9Sstevel@tonic-gate struct ionod *io = t->treio; 115*7c478bd9Sstevel@tonic-gate short cmdhash; 116*7c478bd9Sstevel@tonic-gate short comtype; 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate exitval = 0; 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate gchain = 0; 121*7c478bd9Sstevel@tonic-gate argn = getarg(t); 122*7c478bd9Sstevel@tonic-gate com = scan(argn); 123*7c478bd9Sstevel@tonic-gate a1 = com[1]; 124*7c478bd9Sstevel@tonic-gate gchain = schain; 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate if (argn != 0) 127*7c478bd9Sstevel@tonic-gate cmdhash = pathlook(com[0], 1, comptr(t)->comset); 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate if (argn == 0 || (comtype = hashtype(cmdhash)) == BUILTIN) { 130*7c478bd9Sstevel@tonic-gate setlist(comptr(t)->comset, 0); 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate if (argn && (flags&noexec) == 0) 134*7c478bd9Sstevel@tonic-gate { 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate /* print command if execpr */ 137*7c478bd9Sstevel@tonic-gate if (flags & execpr) 138*7c478bd9Sstevel@tonic-gate execprint(com); 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate if (comtype == NOTFOUND) 141*7c478bd9Sstevel@tonic-gate { 142*7c478bd9Sstevel@tonic-gate pos = hashdata(cmdhash); 143*7c478bd9Sstevel@tonic-gate if (pos == 1) 144*7c478bd9Sstevel@tonic-gate failure(*com, notfound); 145*7c478bd9Sstevel@tonic-gate else if (pos == 2) 146*7c478bd9Sstevel@tonic-gate failure(*com, badexec); 147*7c478bd9Sstevel@tonic-gate else 148*7c478bd9Sstevel@tonic-gate failure(*com, badperm); 149*7c478bd9Sstevel@tonic-gate break; 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate else if (comtype == PATH_COMMAND) 153*7c478bd9Sstevel@tonic-gate { 154*7c478bd9Sstevel@tonic-gate pos = -1; 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate else if (comtype & (COMMAND | REL_COMMAND)) 158*7c478bd9Sstevel@tonic-gate { 159*7c478bd9Sstevel@tonic-gate pos = hashdata(cmdhash); 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate else if (comtype == BUILTIN) { 163*7c478bd9Sstevel@tonic-gate builtin(hashdata(cmdhash),argn,com,t); 164*7c478bd9Sstevel@tonic-gate freejobs(); 165*7c478bd9Sstevel@tonic-gate break; 166*7c478bd9Sstevel@tonic-gate } 167*7c478bd9Sstevel@tonic-gate else if (comtype == FUNCTION) 168*7c478bd9Sstevel@tonic-gate { 169*7c478bd9Sstevel@tonic-gate struct dolnod *olddolh; 170*7c478bd9Sstevel@tonic-gate struct namnod *n, *opt; 171*7c478bd9Sstevel@tonic-gate short index; 172*7c478bd9Sstevel@tonic-gate unsigned char **olddolv = dolv; 173*7c478bd9Sstevel@tonic-gate int olddolc = dolc; 174*7c478bd9Sstevel@tonic-gate n = findnam(com[0]); 175*7c478bd9Sstevel@tonic-gate /* save current positional parameters */ 176*7c478bd9Sstevel@tonic-gate olddolh = (struct dolnod *)savargs(funcnt); 177*7c478bd9Sstevel@tonic-gate funcnt++; 178*7c478bd9Sstevel@tonic-gate index = initio(io, 1); 179*7c478bd9Sstevel@tonic-gate setargs(com); 180*7c478bd9Sstevel@tonic-gate execute((struct trenod *)(n->namenv), xflags, errorflg, pf1, pf2); 181*7c478bd9Sstevel@tonic-gate execbrk = 0; 182*7c478bd9Sstevel@tonic-gate restore(index); 183*7c478bd9Sstevel@tonic-gate (void) restorargs(olddolh, funcnt); 184*7c478bd9Sstevel@tonic-gate dolv = olddolv; 185*7c478bd9Sstevel@tonic-gate dolc = olddolc; 186*7c478bd9Sstevel@tonic-gate funcnt--; 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate break; 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate } 191*7c478bd9Sstevel@tonic-gate else if (t->treio == 0) 192*7c478bd9Sstevel@tonic-gate { 193*7c478bd9Sstevel@tonic-gate chktrap(); 194*7c478bd9Sstevel@tonic-gate break; 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate case TFORK: 200*7c478bd9Sstevel@tonic-gate { 201*7c478bd9Sstevel@tonic-gate int monitor = 0; 202*7c478bd9Sstevel@tonic-gate int linked = 0; 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate exitval = 0; 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate if (!(xflags & XEC_EXECED) || treeflgs&(FPOU|FAMP)) 207*7c478bd9Sstevel@tonic-gate { 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate int forkcnt = 1; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate if (!(treeflgs&FPOU)) 212*7c478bd9Sstevel@tonic-gate { 213*7c478bd9Sstevel@tonic-gate monitor = (!(xflags & XEC_NOSTOP) 214*7c478bd9Sstevel@tonic-gate && (flags&(monitorflg|jcflg|jcoff)) 215*7c478bd9Sstevel@tonic-gate == (monitorflg|jcflg)); 216*7c478bd9Sstevel@tonic-gate if (monitor) { 217*7c478bd9Sstevel@tonic-gate int savefd; 218*7c478bd9Sstevel@tonic-gate unsigned char *savebot; 219*7c478bd9Sstevel@tonic-gate savefd = setb(-1); 220*7c478bd9Sstevel@tonic-gate savebot = stakbot; 221*7c478bd9Sstevel@tonic-gate prcmd(t); 222*7c478bd9Sstevel@tonic-gate (void)setb(savefd); 223*7c478bd9Sstevel@tonic-gate allocjob(savebot, cwdget(), monitor); 224*7c478bd9Sstevel@tonic-gate } else 225*7c478bd9Sstevel@tonic-gate allocjob("", "", 0); 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate if (treeflgs & (FPOU|FAMP)) { 230*7c478bd9Sstevel@tonic-gate link_iodocs(iotemp); 231*7c478bd9Sstevel@tonic-gate linked = 1; 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate while ((parent = fork()) == -1) 235*7c478bd9Sstevel@tonic-gate { 236*7c478bd9Sstevel@tonic-gate /* 237*7c478bd9Sstevel@tonic-gate * FORKLIM is the max period between forks - 238*7c478bd9Sstevel@tonic-gate * power of 2 usually. Currently shell tries 239*7c478bd9Sstevel@tonic-gate * after 2,4,8,16, and 32 seconds and then quits 240*7c478bd9Sstevel@tonic-gate */ 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate if ((forkcnt = (forkcnt * 2)) > FORKLIM) 243*7c478bd9Sstevel@tonic-gate { 244*7c478bd9Sstevel@tonic-gate switch (errno) 245*7c478bd9Sstevel@tonic-gate { 246*7c478bd9Sstevel@tonic-gate case ENOMEM: 247*7c478bd9Sstevel@tonic-gate deallocjob(); 248*7c478bd9Sstevel@tonic-gate error(noswap); 249*7c478bd9Sstevel@tonic-gate break; 250*7c478bd9Sstevel@tonic-gate default: 251*7c478bd9Sstevel@tonic-gate deallocjob(); 252*7c478bd9Sstevel@tonic-gate error(nofork); 253*7c478bd9Sstevel@tonic-gate break; 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate } else if (errno == EPERM) { 256*7c478bd9Sstevel@tonic-gate deallocjob(); 257*7c478bd9Sstevel@tonic-gate error(eacces); 258*7c478bd9Sstevel@tonic-gate break; 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate sigchk(); 261*7c478bd9Sstevel@tonic-gate sleep(forkcnt); 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate if (parent) { 265*7c478bd9Sstevel@tonic-gate if (monitor) 266*7c478bd9Sstevel@tonic-gate setpgid(parent, 0); 267*7c478bd9Sstevel@tonic-gate if (treeflgs & FPIN) 268*7c478bd9Sstevel@tonic-gate closepipe(pf1); 269*7c478bd9Sstevel@tonic-gate if (!(treeflgs&FPOU)) { 270*7c478bd9Sstevel@tonic-gate postjob(parent,!(treeflgs&FAMP)); 271*7c478bd9Sstevel@tonic-gate freejobs(); 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate chktrap(); 274*7c478bd9Sstevel@tonic-gate break; 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate mypid = getpid(); 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate /* 280*7c478bd9Sstevel@tonic-gate * Forked process: assume it is not a subshell for 281*7c478bd9Sstevel@tonic-gate * now. If it is, the presence of a left parenthesis 282*7c478bd9Sstevel@tonic-gate * will trigger the jcoff flag to be turned off. 283*7c478bd9Sstevel@tonic-gate * When jcoff is turned on, monitoring is not going on 284*7c478bd9Sstevel@tonic-gate * and waitpid will not look for WUNTRACED. 285*7c478bd9Sstevel@tonic-gate */ 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate flags |= (forked|jcoff); 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate fiotemp = 0; 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate if (linked == 1) { 292*7c478bd9Sstevel@tonic-gate swap_iodoc_nm(iotemp); 293*7c478bd9Sstevel@tonic-gate xflags |= XEC_LINKED; 294*7c478bd9Sstevel@tonic-gate } else if (!(xflags & XEC_LINKED)) 295*7c478bd9Sstevel@tonic-gate iotemp = 0; 296*7c478bd9Sstevel@tonic-gate #ifdef ACCT 297*7c478bd9Sstevel@tonic-gate suspacct(); 298*7c478bd9Sstevel@tonic-gate #endif 299*7c478bd9Sstevel@tonic-gate settmp(); 300*7c478bd9Sstevel@tonic-gate oldsigs(); 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate if (!(treeflgs & FPOU)) 303*7c478bd9Sstevel@tonic-gate makejob(monitor, !(treeflgs & FAMP)); 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate /* 306*7c478bd9Sstevel@tonic-gate * pipe in or out 307*7c478bd9Sstevel@tonic-gate */ 308*7c478bd9Sstevel@tonic-gate if (treeflgs & FPIN) 309*7c478bd9Sstevel@tonic-gate { 310*7c478bd9Sstevel@tonic-gate renamef(pf1[INPIPE], 0); 311*7c478bd9Sstevel@tonic-gate close(pf1[OTPIPE]); 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate if (treeflgs & FPOU) 315*7c478bd9Sstevel@tonic-gate { 316*7c478bd9Sstevel@tonic-gate close(pf2[INPIPE]); 317*7c478bd9Sstevel@tonic-gate renamef(pf2[OTPIPE], 1); 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate /* 321*7c478bd9Sstevel@tonic-gate * io redirection 322*7c478bd9Sstevel@tonic-gate */ 323*7c478bd9Sstevel@tonic-gate initio(t->treio, 0); 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate if (type == TFORK) 326*7c478bd9Sstevel@tonic-gate execute(forkptr(t)->forktre, xflags | XEC_EXECED, errorflg); 327*7c478bd9Sstevel@tonic-gate else if (com[0] != ENDARGS) 328*7c478bd9Sstevel@tonic-gate { 329*7c478bd9Sstevel@tonic-gate eflag = 0; 330*7c478bd9Sstevel@tonic-gate setlist(comptr(t)->comset, N_EXPORT); 331*7c478bd9Sstevel@tonic-gate rmtemp(0); 332*7c478bd9Sstevel@tonic-gate clearjobs(); 333*7c478bd9Sstevel@tonic-gate execa(com, pos); 334*7c478bd9Sstevel@tonic-gate } 335*7c478bd9Sstevel@tonic-gate done(0); 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate case TPAR: 339*7c478bd9Sstevel@tonic-gate /* Forked process is subshell: may want job control */ 340*7c478bd9Sstevel@tonic-gate flags &= ~jcoff; 341*7c478bd9Sstevel@tonic-gate clearjobs(); 342*7c478bd9Sstevel@tonic-gate execute(parptr(t)->partre, xflags, errorflg); 343*7c478bd9Sstevel@tonic-gate done(0); 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate case TFIL: 346*7c478bd9Sstevel@tonic-gate { 347*7c478bd9Sstevel@tonic-gate int pv[2]; 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate chkpipe(pv); 350*7c478bd9Sstevel@tonic-gate if (execute(lstptr(t)->lstlef, xflags & XEC_NOSTOP, errorflg, pf1, pv) == 0) 351*7c478bd9Sstevel@tonic-gate execute(lstptr(t)->lstrit, xflags, errorflg, pv, pf2); 352*7c478bd9Sstevel@tonic-gate else 353*7c478bd9Sstevel@tonic-gate closepipe(pv); 354*7c478bd9Sstevel@tonic-gate } 355*7c478bd9Sstevel@tonic-gate break; 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate case TLST: 358*7c478bd9Sstevel@tonic-gate execute(lstptr(t)->lstlef, xflags&XEC_NOSTOP, errorflg); 359*7c478bd9Sstevel@tonic-gate /* Update errorflg if set -e is invoked in the sub-sh*/ 360*7c478bd9Sstevel@tonic-gate execute(lstptr(t)->lstrit, xflags, (errorflg | (eflag & errflg))); 361*7c478bd9Sstevel@tonic-gate break; 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate case TAND: 364*7c478bd9Sstevel@tonic-gate case TORF: 365*7c478bd9Sstevel@tonic-gate { 366*7c478bd9Sstevel@tonic-gate register xval; 367*7c478bd9Sstevel@tonic-gate xval = execute(lstptr(t)->lstlef, XEC_NOSTOP, 0); 368*7c478bd9Sstevel@tonic-gate if ((xval == 0) == (type == TAND)) 369*7c478bd9Sstevel@tonic-gate execute(lstptr(t)->lstrit, xflags|XEC_NOSTOP, errorflg); 370*7c478bd9Sstevel@tonic-gate break; 371*7c478bd9Sstevel@tonic-gate } 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate case TFOR: 374*7c478bd9Sstevel@tonic-gate { 375*7c478bd9Sstevel@tonic-gate struct namnod *n = lookup(forptr(t)->fornam); 376*7c478bd9Sstevel@tonic-gate unsigned char **args; 377*7c478bd9Sstevel@tonic-gate struct dolnod *argsav = 0; 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate if (forptr(t)->forlst == 0) 380*7c478bd9Sstevel@tonic-gate { 381*7c478bd9Sstevel@tonic-gate args = dolv + 1; 382*7c478bd9Sstevel@tonic-gate argsav = useargs(); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate else 385*7c478bd9Sstevel@tonic-gate { 386*7c478bd9Sstevel@tonic-gate struct argnod *schain = gchain; 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate gchain = 0; 389*7c478bd9Sstevel@tonic-gate args = scan(getarg(forptr(t)->forlst)); 390*7c478bd9Sstevel@tonic-gate gchain = schain; 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate loopcnt++; 393*7c478bd9Sstevel@tonic-gate while (*args != ENDARGS && execbrk == 0) 394*7c478bd9Sstevel@tonic-gate { 395*7c478bd9Sstevel@tonic-gate assign(n, *args++); 396*7c478bd9Sstevel@tonic-gate execute(forptr(t)->fortre, XEC_NOSTOP, errorflg); 397*7c478bd9Sstevel@tonic-gate if (breakcnt < 0) 398*7c478bd9Sstevel@tonic-gate execbrk = (++breakcnt != 0); 399*7c478bd9Sstevel@tonic-gate } 400*7c478bd9Sstevel@tonic-gate if (breakcnt > 0) 401*7c478bd9Sstevel@tonic-gate execbrk = (--breakcnt != 0); 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate loopcnt--; 404*7c478bd9Sstevel@tonic-gate if(argsav) 405*7c478bd9Sstevel@tonic-gate argfor = (struct dolnod *)freeargs(argsav); 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate break; 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate case TWH: 410*7c478bd9Sstevel@tonic-gate case TUN: 411*7c478bd9Sstevel@tonic-gate { 412*7c478bd9Sstevel@tonic-gate int i = 0; 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate loopcnt++; 415*7c478bd9Sstevel@tonic-gate while (execbrk == 0 && (execute(whptr(t)->whtre, 416*7c478bd9Sstevel@tonic-gate XEC_NOSTOP, 0) == 0) == (type == TWH) && 417*7c478bd9Sstevel@tonic-gate (flags&noexec) == 0) 418*7c478bd9Sstevel@tonic-gate { 419*7c478bd9Sstevel@tonic-gate i = execute(whptr(t)->dotre, XEC_NOSTOP, errorflg); 420*7c478bd9Sstevel@tonic-gate if (breakcnt < 0) 421*7c478bd9Sstevel@tonic-gate execbrk = (++breakcnt != 0); 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate if (breakcnt > 0) 424*7c478bd9Sstevel@tonic-gate execbrk = (--breakcnt != 0); 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate loopcnt--; 427*7c478bd9Sstevel@tonic-gate exitval = i; 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate break; 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate case TIF: 432*7c478bd9Sstevel@tonic-gate if (execute(ifptr(t)->iftre, XEC_NOSTOP, 0) == 0) 433*7c478bd9Sstevel@tonic-gate execute(ifptr(t)->thtre, xflags|XEC_NOSTOP, errorflg); 434*7c478bd9Sstevel@tonic-gate else if (ifptr(t)->eltre) 435*7c478bd9Sstevel@tonic-gate execute(ifptr(t)->eltre, xflags|XEC_NOSTOP, errorflg); 436*7c478bd9Sstevel@tonic-gate else 437*7c478bd9Sstevel@tonic-gate exitval = 0; /* force zero exit for if-then-fi */ 438*7c478bd9Sstevel@tonic-gate break; 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate case TSW: 441*7c478bd9Sstevel@tonic-gate { 442*7c478bd9Sstevel@tonic-gate register unsigned char *r = mactrim(swptr(t)->swarg); 443*7c478bd9Sstevel@tonic-gate register struct regnod *regp; 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate regp = swptr(t)->swlst; 446*7c478bd9Sstevel@tonic-gate while (regp) 447*7c478bd9Sstevel@tonic-gate { 448*7c478bd9Sstevel@tonic-gate struct argnod *rex = regp->regptr; 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate while (rex) 451*7c478bd9Sstevel@tonic-gate { 452*7c478bd9Sstevel@tonic-gate register unsigned char *s; 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate if (gmatch(r, s = macro(rex->argval)) || (trim(s), eq(r, s))) 455*7c478bd9Sstevel@tonic-gate { 456*7c478bd9Sstevel@tonic-gate execute(regp->regcom, XEC_NOSTOP, errorflg); 457*7c478bd9Sstevel@tonic-gate regp = 0; 458*7c478bd9Sstevel@tonic-gate break; 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate else 461*7c478bd9Sstevel@tonic-gate rex = rex->argnxt; 462*7c478bd9Sstevel@tonic-gate } 463*7c478bd9Sstevel@tonic-gate if (regp) 464*7c478bd9Sstevel@tonic-gate regp = regp->regnxt; 465*7c478bd9Sstevel@tonic-gate } 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate break; 468*7c478bd9Sstevel@tonic-gate } 469*7c478bd9Sstevel@tonic-gate exitset(); 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate sigchk(); 472*7c478bd9Sstevel@tonic-gate tdystak(sav); 473*7c478bd9Sstevel@tonic-gate flags |= eflag; 474*7c478bd9Sstevel@tonic-gate return(exitval); 475*7c478bd9Sstevel@tonic-gate } 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate execexp(s, f) 478*7c478bd9Sstevel@tonic-gate unsigned char *s; 479*7c478bd9Sstevel@tonic-gate int f; 480*7c478bd9Sstevel@tonic-gate { 481*7c478bd9Sstevel@tonic-gate struct fileblk fb; 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate push(&fb); 484*7c478bd9Sstevel@tonic-gate if (s) 485*7c478bd9Sstevel@tonic-gate { 486*7c478bd9Sstevel@tonic-gate estabf(s); 487*7c478bd9Sstevel@tonic-gate fb.feval = (unsigned char **)(f); 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate else if (f >= 0) 490*7c478bd9Sstevel@tonic-gate initf(f); 491*7c478bd9Sstevel@tonic-gate execute(cmd(NL, NLFLG | MTFLG), 0, (int)(flags & errflg)); 492*7c478bd9Sstevel@tonic-gate pop(); 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate execprint(com) 496*7c478bd9Sstevel@tonic-gate unsigned char **com; 497*7c478bd9Sstevel@tonic-gate { 498*7c478bd9Sstevel@tonic-gate register int argn = 0; 499*7c478bd9Sstevel@tonic-gate unsigned char *s; 500*7c478bd9Sstevel@tonic-gate 501*7c478bd9Sstevel@tonic-gate prs(execpmsg); 502*7c478bd9Sstevel@tonic-gate while(com[argn] != ENDARGS) 503*7c478bd9Sstevel@tonic-gate { 504*7c478bd9Sstevel@tonic-gate s = com[argn++]; 505*7c478bd9Sstevel@tonic-gate write(output, s, length(s) - 1); 506*7c478bd9Sstevel@tonic-gate blank(); 507*7c478bd9Sstevel@tonic-gate } 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate newline(); 510*7c478bd9Sstevel@tonic-gate } 511