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