xref: /onnv-gate/usr/src/cmd/sh/xec.c (revision 9369:4df685ccc8c1)
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