10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 52256Sna195498 * Common Development and Distribution License (the "License"). 62256Sna195498 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 21527Schin 22527Schin /* 23*9369SNobutomo.Nakano@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24527Schin * Use is subject to license terms. 25527Schin */ 26527Schin 270Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 280Sstevel@tonic-gate /* All Rights Reserved */ 290Sstevel@tonic-gate 300Sstevel@tonic-gate /* 310Sstevel@tonic-gate * 320Sstevel@tonic-gate * UNIX shell 330Sstevel@tonic-gate * 340Sstevel@tonic-gate */ 350Sstevel@tonic-gate 360Sstevel@tonic-gate 370Sstevel@tonic-gate #include "defs.h" 380Sstevel@tonic-gate #include <errno.h> 390Sstevel@tonic-gate #include "sym.h" 400Sstevel@tonic-gate #include "hash.h" 410Sstevel@tonic-gate #include <sys/types.h> 420Sstevel@tonic-gate #include <sys/times.h> 430Sstevel@tonic-gate 440Sstevel@tonic-gate pid_t parent; 450Sstevel@tonic-gate 46527Schin void execprint(unsigned char **); 47527Schin 480Sstevel@tonic-gate /* ======== command execution ======== */ 490Sstevel@tonic-gate 50527Schin /*VARARGS3*/ 51527Schin int 520Sstevel@tonic-gate execute(argt, xflags, errorflg, pf1, pf2) 53527Schin struct trenod *argt; 54527Schin int xflags, errorflg; 55527Schin int *pf1, *pf2; 560Sstevel@tonic-gate { 570Sstevel@tonic-gate /* 580Sstevel@tonic-gate * `stakbot' is preserved by this routine 590Sstevel@tonic-gate */ 60527Schin struct trenod *t; 610Sstevel@tonic-gate unsigned char *sav = savstak(); 620Sstevel@tonic-gate 630Sstevel@tonic-gate sigchk(); 640Sstevel@tonic-gate if (!errorflg) 650Sstevel@tonic-gate flags &= ~errflg; 660Sstevel@tonic-gate 670Sstevel@tonic-gate if ((t = argt) && execbrk == 0) { 68527Schin int treeflgs; 69527Schin unsigned char **com; 700Sstevel@tonic-gate int type; 710Sstevel@tonic-gate short pos; 720Sstevel@tonic-gate 730Sstevel@tonic-gate treeflgs = t->tretyp; 740Sstevel@tonic-gate type = treeflgs & COMMSK; 750Sstevel@tonic-gate 760Sstevel@tonic-gate switch (type) 770Sstevel@tonic-gate { 780Sstevel@tonic-gate case TFND: 790Sstevel@tonic-gate { 80*9369SNobutomo.Nakano@Sun.COM struct fndnod *f = fndptr(t); 810Sstevel@tonic-gate struct namnod *n = lookup(f->fndnam); 820Sstevel@tonic-gate 830Sstevel@tonic-gate exitval = 0; 840Sstevel@tonic-gate 850Sstevel@tonic-gate if (n->namflg & N_RDONLY) 860Sstevel@tonic-gate failed(n->namid, wtfailed); 870Sstevel@tonic-gate 880Sstevel@tonic-gate if (flags & rshflg && (n == &pathnod || 890Sstevel@tonic-gate eq(n->namid, "SHELL"))) 900Sstevel@tonic-gate failed(n->namid, restricted); 91*9369SNobutomo.Nakano@Sun.COM /* 92*9369SNobutomo.Nakano@Sun.COM * If function of same name is previously 93*9369SNobutomo.Nakano@Sun.COM * defined, it will no longer be used. 94*9369SNobutomo.Nakano@Sun.COM */ 95*9369SNobutomo.Nakano@Sun.COM if (n->namflg & N_FUNCTN) { 960Sstevel@tonic-gate freefunc(n); 97*9369SNobutomo.Nakano@Sun.COM } else { 980Sstevel@tonic-gate free(n->namval); 990Sstevel@tonic-gate free(n->namenv); 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate n->namval = 0; 1020Sstevel@tonic-gate n->namflg &= ~(N_EXPORT | N_ENVCHG); 1030Sstevel@tonic-gate } 104*9369SNobutomo.Nakano@Sun.COM /* 105*9369SNobutomo.Nakano@Sun.COM * If function is defined within function, 106*9369SNobutomo.Nakano@Sun.COM * we don't want to free it along with the 107*9369SNobutomo.Nakano@Sun.COM * free of the defining function. If we are 108*9369SNobutomo.Nakano@Sun.COM * in a loop, fndnod may be reused, so it 109*9369SNobutomo.Nakano@Sun.COM * should never be freed. 110*9369SNobutomo.Nakano@Sun.COM */ 111*9369SNobutomo.Nakano@Sun.COM if (funcnt != 0 || loopcnt != 0) 112*9369SNobutomo.Nakano@Sun.COM f->fndref++; 1130Sstevel@tonic-gate 114*9369SNobutomo.Nakano@Sun.COM /* 115*9369SNobutomo.Nakano@Sun.COM * We hang a fndnod on the namenv so that 116*9369SNobutomo.Nakano@Sun.COM * ref cnt(fndref) can be increased while 117*9369SNobutomo.Nakano@Sun.COM * running in the function. 118*9369SNobutomo.Nakano@Sun.COM */ 119*9369SNobutomo.Nakano@Sun.COM n->namenv = (unsigned char *)f; 1200Sstevel@tonic-gate attrib(n, N_FUNCTN); 1210Sstevel@tonic-gate hash_func(n->namid); 1220Sstevel@tonic-gate break; 1230Sstevel@tonic-gate } 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate case TCOM: 1260Sstevel@tonic-gate { 1270Sstevel@tonic-gate unsigned char *a1, *name; 1280Sstevel@tonic-gate int argn, internal; 1290Sstevel@tonic-gate struct argnod *schain = gchain; 1300Sstevel@tonic-gate struct ionod *io = t->treio; 1310Sstevel@tonic-gate short cmdhash; 1320Sstevel@tonic-gate short comtype; 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate exitval = 0; 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate gchain = 0; 1370Sstevel@tonic-gate argn = getarg(t); 1380Sstevel@tonic-gate com = scan(argn); 1390Sstevel@tonic-gate a1 = com[1]; 1400Sstevel@tonic-gate gchain = schain; 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate if (argn != 0) 1430Sstevel@tonic-gate cmdhash = pathlook(com[0], 1, comptr(t)->comset); 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate if (argn == 0 || (comtype = hashtype(cmdhash)) == BUILTIN) { 1460Sstevel@tonic-gate setlist(comptr(t)->comset, 0); 1470Sstevel@tonic-gate } 1480Sstevel@tonic-gate 1490Sstevel@tonic-gate if (argn && (flags&noexec) == 0) 1500Sstevel@tonic-gate { 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate /* print command if execpr */ 1530Sstevel@tonic-gate if (flags & execpr) 1540Sstevel@tonic-gate execprint(com); 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate if (comtype == NOTFOUND) 1570Sstevel@tonic-gate { 1580Sstevel@tonic-gate pos = hashdata(cmdhash); 1590Sstevel@tonic-gate if (pos == 1) 1600Sstevel@tonic-gate failure(*com, notfound); 1610Sstevel@tonic-gate else if (pos == 2) 1620Sstevel@tonic-gate failure(*com, badexec); 1630Sstevel@tonic-gate else 1640Sstevel@tonic-gate failure(*com, badperm); 1650Sstevel@tonic-gate break; 1660Sstevel@tonic-gate } 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate else if (comtype == PATH_COMMAND) 1690Sstevel@tonic-gate { 1700Sstevel@tonic-gate pos = -1; 1710Sstevel@tonic-gate } 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate else if (comtype & (COMMAND | REL_COMMAND)) 1740Sstevel@tonic-gate { 1750Sstevel@tonic-gate pos = hashdata(cmdhash); 1760Sstevel@tonic-gate } 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate else if (comtype == BUILTIN) { 1790Sstevel@tonic-gate builtin(hashdata(cmdhash),argn,com,t); 1800Sstevel@tonic-gate freejobs(); 1810Sstevel@tonic-gate break; 1820Sstevel@tonic-gate } 1830Sstevel@tonic-gate else if (comtype == FUNCTION) 1840Sstevel@tonic-gate { 1850Sstevel@tonic-gate struct dolnod *olddolh; 1860Sstevel@tonic-gate struct namnod *n, *opt; 187*9369SNobutomo.Nakano@Sun.COM struct fndnod *f; 1880Sstevel@tonic-gate short index; 1890Sstevel@tonic-gate unsigned char **olddolv = dolv; 1900Sstevel@tonic-gate int olddolc = dolc; 191*9369SNobutomo.Nakano@Sun.COM 1920Sstevel@tonic-gate n = findnam(com[0]); 193*9369SNobutomo.Nakano@Sun.COM f = fndptr(n->namenv); 194*9369SNobutomo.Nakano@Sun.COM /* just in case */ 195*9369SNobutomo.Nakano@Sun.COM if (f == NULL) 196*9369SNobutomo.Nakano@Sun.COM break; 1970Sstevel@tonic-gate /* save current positional parameters */ 1980Sstevel@tonic-gate olddolh = (struct dolnod *)savargs(funcnt); 199*9369SNobutomo.Nakano@Sun.COM f->fndref++; 2000Sstevel@tonic-gate funcnt++; 2010Sstevel@tonic-gate index = initio(io, 1); 2020Sstevel@tonic-gate setargs(com); 203*9369SNobutomo.Nakano@Sun.COM execute(f->fndval, xflags, 204*9369SNobutomo.Nakano@Sun.COM errorflg, pf1, pf2); 2050Sstevel@tonic-gate execbrk = 0; 2060Sstevel@tonic-gate restore(index); 2070Sstevel@tonic-gate (void) restorargs(olddolh, funcnt); 2080Sstevel@tonic-gate dolv = olddolv; 2090Sstevel@tonic-gate dolc = olddolc; 2100Sstevel@tonic-gate funcnt--; 211*9369SNobutomo.Nakano@Sun.COM /* 212*9369SNobutomo.Nakano@Sun.COM * n->namenv may have been 213*9369SNobutomo.Nakano@Sun.COM * pointing different func. 214*9369SNobutomo.Nakano@Sun.COM * Therefore, we can't use 215*9369SNobutomo.Nakano@Sun.COM * freefunc(n). 216*9369SNobutomo.Nakano@Sun.COM */ 217*9369SNobutomo.Nakano@Sun.COM freetree((struct trenod *)f); 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate break; 2200Sstevel@tonic-gate } 2210Sstevel@tonic-gate } 2220Sstevel@tonic-gate else if (t->treio == 0) 2230Sstevel@tonic-gate { 2240Sstevel@tonic-gate chktrap(); 2250Sstevel@tonic-gate break; 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate } 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate case TFORK: 2310Sstevel@tonic-gate { 2320Sstevel@tonic-gate int monitor = 0; 2330Sstevel@tonic-gate int linked = 0; 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate exitval = 0; 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate if (!(xflags & XEC_EXECED) || treeflgs&(FPOU|FAMP)) 2380Sstevel@tonic-gate { 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate int forkcnt = 1; 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate if (!(treeflgs&FPOU)) 2430Sstevel@tonic-gate { 2440Sstevel@tonic-gate monitor = (!(xflags & XEC_NOSTOP) 2450Sstevel@tonic-gate && (flags&(monitorflg|jcflg|jcoff)) 2460Sstevel@tonic-gate == (monitorflg|jcflg)); 2470Sstevel@tonic-gate if (monitor) { 2480Sstevel@tonic-gate int savefd; 2490Sstevel@tonic-gate unsigned char *savebot; 2500Sstevel@tonic-gate savefd = setb(-1); 2510Sstevel@tonic-gate savebot = stakbot; 2520Sstevel@tonic-gate prcmd(t); 2530Sstevel@tonic-gate (void)setb(savefd); 2540Sstevel@tonic-gate allocjob(savebot, cwdget(), monitor); 2550Sstevel@tonic-gate } else 2560Sstevel@tonic-gate allocjob("", "", 0); 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate } 2590Sstevel@tonic-gate 2600Sstevel@tonic-gate if (treeflgs & (FPOU|FAMP)) { 2610Sstevel@tonic-gate link_iodocs(iotemp); 2620Sstevel@tonic-gate linked = 1; 2630Sstevel@tonic-gate } 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate while ((parent = fork()) == -1) 2660Sstevel@tonic-gate { 2670Sstevel@tonic-gate /* 2680Sstevel@tonic-gate * FORKLIM is the max period between forks - 2690Sstevel@tonic-gate * power of 2 usually. Currently shell tries 2700Sstevel@tonic-gate * after 2,4,8,16, and 32 seconds and then quits 2710Sstevel@tonic-gate */ 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate if ((forkcnt = (forkcnt * 2)) > FORKLIM) 2740Sstevel@tonic-gate { 2750Sstevel@tonic-gate switch (errno) 2760Sstevel@tonic-gate { 2770Sstevel@tonic-gate case ENOMEM: 2780Sstevel@tonic-gate deallocjob(); 2790Sstevel@tonic-gate error(noswap); 2800Sstevel@tonic-gate break; 2810Sstevel@tonic-gate default: 2820Sstevel@tonic-gate deallocjob(); 2830Sstevel@tonic-gate error(nofork); 2840Sstevel@tonic-gate break; 2850Sstevel@tonic-gate } 2860Sstevel@tonic-gate } else if (errno == EPERM) { 2870Sstevel@tonic-gate deallocjob(); 2880Sstevel@tonic-gate error(eacces); 2890Sstevel@tonic-gate break; 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate sigchk(); 292527Schin sh_sleep(forkcnt); 2930Sstevel@tonic-gate } 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate if (parent) { 2960Sstevel@tonic-gate if (monitor) 2970Sstevel@tonic-gate setpgid(parent, 0); 2980Sstevel@tonic-gate if (treeflgs & FPIN) 2990Sstevel@tonic-gate closepipe(pf1); 3000Sstevel@tonic-gate if (!(treeflgs&FPOU)) { 3010Sstevel@tonic-gate postjob(parent,!(treeflgs&FAMP)); 3020Sstevel@tonic-gate freejobs(); 3030Sstevel@tonic-gate } 3040Sstevel@tonic-gate chktrap(); 3050Sstevel@tonic-gate break; 3060Sstevel@tonic-gate } 3070Sstevel@tonic-gate mypid = getpid(); 3080Sstevel@tonic-gate } 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate /* 3110Sstevel@tonic-gate * Forked process: assume it is not a subshell for 3120Sstevel@tonic-gate * now. If it is, the presence of a left parenthesis 3130Sstevel@tonic-gate * will trigger the jcoff flag to be turned off. 3140Sstevel@tonic-gate * When jcoff is turned on, monitoring is not going on 3150Sstevel@tonic-gate * and waitpid will not look for WUNTRACED. 3160Sstevel@tonic-gate */ 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate flags |= (forked|jcoff); 3190Sstevel@tonic-gate 3200Sstevel@tonic-gate fiotemp = 0; 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate if (linked == 1) { 3230Sstevel@tonic-gate swap_iodoc_nm(iotemp); 3240Sstevel@tonic-gate xflags |= XEC_LINKED; 3250Sstevel@tonic-gate } else if (!(xflags & XEC_LINKED)) 3260Sstevel@tonic-gate iotemp = 0; 3270Sstevel@tonic-gate #ifdef ACCT 3280Sstevel@tonic-gate suspacct(); 3290Sstevel@tonic-gate #endif 3300Sstevel@tonic-gate settmp(); 3310Sstevel@tonic-gate oldsigs(); 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate if (!(treeflgs & FPOU)) 3340Sstevel@tonic-gate makejob(monitor, !(treeflgs & FAMP)); 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate /* 3370Sstevel@tonic-gate * pipe in or out 3380Sstevel@tonic-gate */ 3390Sstevel@tonic-gate if (treeflgs & FPIN) 3400Sstevel@tonic-gate { 3410Sstevel@tonic-gate renamef(pf1[INPIPE], 0); 3420Sstevel@tonic-gate close(pf1[OTPIPE]); 3430Sstevel@tonic-gate } 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate if (treeflgs & FPOU) 3460Sstevel@tonic-gate { 3470Sstevel@tonic-gate close(pf2[INPIPE]); 3480Sstevel@tonic-gate renamef(pf2[OTPIPE], 1); 3490Sstevel@tonic-gate } 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate /* 3520Sstevel@tonic-gate * io redirection 3530Sstevel@tonic-gate */ 3540Sstevel@tonic-gate initio(t->treio, 0); 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate if (type == TFORK) 3570Sstevel@tonic-gate execute(forkptr(t)->forktre, xflags | XEC_EXECED, errorflg); 3580Sstevel@tonic-gate else if (com[0] != ENDARGS) 3590Sstevel@tonic-gate { 3600Sstevel@tonic-gate eflag = 0; 3610Sstevel@tonic-gate setlist(comptr(t)->comset, N_EXPORT); 3620Sstevel@tonic-gate rmtemp(0); 3630Sstevel@tonic-gate clearjobs(); 3640Sstevel@tonic-gate execa(com, pos); 3650Sstevel@tonic-gate } 3660Sstevel@tonic-gate done(0); 3670Sstevel@tonic-gate } 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate case TPAR: 3700Sstevel@tonic-gate /* Forked process is subshell: may want job control */ 3710Sstevel@tonic-gate flags &= ~jcoff; 3720Sstevel@tonic-gate clearjobs(); 3730Sstevel@tonic-gate execute(parptr(t)->partre, xflags, errorflg); 3740Sstevel@tonic-gate done(0); 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate case TFIL: 3770Sstevel@tonic-gate { 3780Sstevel@tonic-gate int pv[2]; 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate chkpipe(pv); 3810Sstevel@tonic-gate if (execute(lstptr(t)->lstlef, xflags & XEC_NOSTOP, errorflg, pf1, pv) == 0) 3820Sstevel@tonic-gate execute(lstptr(t)->lstrit, xflags, errorflg, pv, pf2); 3830Sstevel@tonic-gate else 3840Sstevel@tonic-gate closepipe(pv); 3850Sstevel@tonic-gate } 3860Sstevel@tonic-gate break; 3870Sstevel@tonic-gate 3880Sstevel@tonic-gate case TLST: 3890Sstevel@tonic-gate execute(lstptr(t)->lstlef, xflags&XEC_NOSTOP, errorflg); 3900Sstevel@tonic-gate /* Update errorflg if set -e is invoked in the sub-sh*/ 3910Sstevel@tonic-gate execute(lstptr(t)->lstrit, xflags, (errorflg | (eflag & errflg))); 3920Sstevel@tonic-gate break; 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate case TAND: 3950Sstevel@tonic-gate case TORF: 3960Sstevel@tonic-gate { 397527Schin int xval; 3980Sstevel@tonic-gate xval = execute(lstptr(t)->lstlef, XEC_NOSTOP, 0); 3990Sstevel@tonic-gate if ((xval == 0) == (type == TAND)) 4000Sstevel@tonic-gate execute(lstptr(t)->lstrit, xflags|XEC_NOSTOP, errorflg); 4010Sstevel@tonic-gate break; 4020Sstevel@tonic-gate } 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate case TFOR: 4050Sstevel@tonic-gate { 4060Sstevel@tonic-gate struct namnod *n = lookup(forptr(t)->fornam); 4070Sstevel@tonic-gate unsigned char **args; 4080Sstevel@tonic-gate struct dolnod *argsav = 0; 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate if (forptr(t)->forlst == 0) 4110Sstevel@tonic-gate { 4120Sstevel@tonic-gate args = dolv + 1; 4130Sstevel@tonic-gate argsav = useargs(); 4140Sstevel@tonic-gate } 4150Sstevel@tonic-gate else 4160Sstevel@tonic-gate { 4170Sstevel@tonic-gate struct argnod *schain = gchain; 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate gchain = 0; 4200Sstevel@tonic-gate args = scan(getarg(forptr(t)->forlst)); 4210Sstevel@tonic-gate gchain = schain; 4220Sstevel@tonic-gate } 4230Sstevel@tonic-gate loopcnt++; 4240Sstevel@tonic-gate while (*args != ENDARGS && execbrk == 0) 4250Sstevel@tonic-gate { 4260Sstevel@tonic-gate assign(n, *args++); 4270Sstevel@tonic-gate execute(forptr(t)->fortre, XEC_NOSTOP, errorflg); 4280Sstevel@tonic-gate if (breakcnt < 0) 4290Sstevel@tonic-gate execbrk = (++breakcnt != 0); 4300Sstevel@tonic-gate } 4310Sstevel@tonic-gate if (breakcnt > 0) 4320Sstevel@tonic-gate execbrk = (--breakcnt != 0); 4330Sstevel@tonic-gate 4340Sstevel@tonic-gate loopcnt--; 4350Sstevel@tonic-gate if(argsav) 4360Sstevel@tonic-gate argfor = (struct dolnod *)freeargs(argsav); 4370Sstevel@tonic-gate } 4380Sstevel@tonic-gate break; 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate case TWH: 4410Sstevel@tonic-gate case TUN: 4420Sstevel@tonic-gate { 4430Sstevel@tonic-gate int i = 0; 4440Sstevel@tonic-gate 4450Sstevel@tonic-gate loopcnt++; 4460Sstevel@tonic-gate while (execbrk == 0 && (execute(whptr(t)->whtre, 4470Sstevel@tonic-gate XEC_NOSTOP, 0) == 0) == (type == TWH) && 4480Sstevel@tonic-gate (flags&noexec) == 0) 4490Sstevel@tonic-gate { 4500Sstevel@tonic-gate i = execute(whptr(t)->dotre, XEC_NOSTOP, errorflg); 4510Sstevel@tonic-gate if (breakcnt < 0) 4520Sstevel@tonic-gate execbrk = (++breakcnt != 0); 4530Sstevel@tonic-gate } 4540Sstevel@tonic-gate if (breakcnt > 0) 4550Sstevel@tonic-gate execbrk = (--breakcnt != 0); 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate loopcnt--; 4580Sstevel@tonic-gate exitval = i; 4590Sstevel@tonic-gate } 4600Sstevel@tonic-gate break; 4610Sstevel@tonic-gate 4620Sstevel@tonic-gate case TIF: 4630Sstevel@tonic-gate if (execute(ifptr(t)->iftre, XEC_NOSTOP, 0) == 0) 4640Sstevel@tonic-gate execute(ifptr(t)->thtre, xflags|XEC_NOSTOP, errorflg); 4650Sstevel@tonic-gate else if (ifptr(t)->eltre) 4660Sstevel@tonic-gate execute(ifptr(t)->eltre, xflags|XEC_NOSTOP, errorflg); 4670Sstevel@tonic-gate else 4680Sstevel@tonic-gate exitval = 0; /* force zero exit for if-then-fi */ 4690Sstevel@tonic-gate break; 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate case TSW: 4720Sstevel@tonic-gate { 473527Schin unsigned char *r = mactrim(swptr(t)->swarg); 474527Schin struct regnod *regp; 4750Sstevel@tonic-gate 4760Sstevel@tonic-gate regp = swptr(t)->swlst; 4770Sstevel@tonic-gate while (regp) 4780Sstevel@tonic-gate { 4790Sstevel@tonic-gate struct argnod *rex = regp->regptr; 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate while (rex) 4820Sstevel@tonic-gate { 483527Schin unsigned char *s; 4840Sstevel@tonic-gate 4850Sstevel@tonic-gate if (gmatch(r, s = macro(rex->argval)) || (trim(s), eq(r, s))) 4860Sstevel@tonic-gate { 4870Sstevel@tonic-gate execute(regp->regcom, XEC_NOSTOP, errorflg); 4880Sstevel@tonic-gate regp = 0; 4890Sstevel@tonic-gate break; 4900Sstevel@tonic-gate } 4910Sstevel@tonic-gate else 4920Sstevel@tonic-gate rex = rex->argnxt; 4930Sstevel@tonic-gate } 4940Sstevel@tonic-gate if (regp) 4950Sstevel@tonic-gate regp = regp->regnxt; 4960Sstevel@tonic-gate } 4970Sstevel@tonic-gate } 4980Sstevel@tonic-gate break; 4990Sstevel@tonic-gate } 5000Sstevel@tonic-gate exitset(); 5010Sstevel@tonic-gate } 5020Sstevel@tonic-gate sigchk(); 5030Sstevel@tonic-gate tdystak(sav); 5040Sstevel@tonic-gate flags |= eflag; 5050Sstevel@tonic-gate return(exitval); 5060Sstevel@tonic-gate } 5070Sstevel@tonic-gate 508527Schin void 509527Schin execexp(unsigned char *s, int f) 5100Sstevel@tonic-gate { 5110Sstevel@tonic-gate struct fileblk fb; 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate push(&fb); 5140Sstevel@tonic-gate if (s) 5150Sstevel@tonic-gate { 5160Sstevel@tonic-gate estabf(s); 5170Sstevel@tonic-gate fb.feval = (unsigned char **)(f); 5180Sstevel@tonic-gate } 5190Sstevel@tonic-gate else if (f >= 0) 5200Sstevel@tonic-gate initf(f); 5210Sstevel@tonic-gate execute(cmd(NL, NLFLG | MTFLG), 0, (int)(flags & errflg)); 5220Sstevel@tonic-gate pop(); 5230Sstevel@tonic-gate } 5240Sstevel@tonic-gate 525527Schin void 526527Schin execprint(unsigned char **com) 5270Sstevel@tonic-gate { 528527Schin int argn = 0; 5290Sstevel@tonic-gate unsigned char *s; 5300Sstevel@tonic-gate 5312256Sna195498 prs(_gettext(execpmsg)); 5320Sstevel@tonic-gate while(com[argn] != ENDARGS) 5330Sstevel@tonic-gate { 5340Sstevel@tonic-gate s = com[argn++]; 5350Sstevel@tonic-gate write(output, s, length(s) - 1); 5360Sstevel@tonic-gate blank(); 5370Sstevel@tonic-gate } 5380Sstevel@tonic-gate 5390Sstevel@tonic-gate newline(); 5400Sstevel@tonic-gate } 541