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
execute(argt,xflags,errorflg,pf1,pf2)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
execexp(unsigned char * s,int f)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
execprint(unsigned char ** com)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