xref: /titanic_50/usr/src/cmd/sh/xec.c (revision 965005c81e0f731867d47892b9fb677030b102df)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate 
237c478bd9Sstevel@tonic-gate /*
24*965005c8Schin  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
257c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
28*965005c8Schin /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
29*965005c8Schin /*	  All Rights Reserved  	*/
30*965005c8Schin 
317c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
327c478bd9Sstevel@tonic-gate /*
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  * UNIX shell
357c478bd9Sstevel@tonic-gate  *
367c478bd9Sstevel@tonic-gate  */
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #include	"defs.h"
407c478bd9Sstevel@tonic-gate #include	<errno.h>
417c478bd9Sstevel@tonic-gate #include	"sym.h"
427c478bd9Sstevel@tonic-gate #include	"hash.h"
437c478bd9Sstevel@tonic-gate #include	<sys/types.h>
447c478bd9Sstevel@tonic-gate #include	<sys/times.h>
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate pid_t parent;
477c478bd9Sstevel@tonic-gate 
48*965005c8Schin void execprint(unsigned char **);
49*965005c8Schin 
507c478bd9Sstevel@tonic-gate /* ========	command execution	======== */
517c478bd9Sstevel@tonic-gate 
52*965005c8Schin /*VARARGS3*/
53*965005c8Schin int
547c478bd9Sstevel@tonic-gate execute(argt, xflags, errorflg, pf1, pf2)
557c478bd9Sstevel@tonic-gate struct trenod *argt;
56*965005c8Schin int xflags, errorflg;
577c478bd9Sstevel@tonic-gate int *pf1, *pf2;
587c478bd9Sstevel@tonic-gate {
597c478bd9Sstevel@tonic-gate 	/*
607c478bd9Sstevel@tonic-gate 	 * `stakbot' is preserved by this routine
617c478bd9Sstevel@tonic-gate 	 */
62*965005c8Schin 	struct trenod	*t;
637c478bd9Sstevel@tonic-gate 	unsigned char		*sav = savstak();
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate 	sigchk();
667c478bd9Sstevel@tonic-gate 	if (!errorflg)
677c478bd9Sstevel@tonic-gate 		flags &= ~errflg;
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate 	if ((t = argt) && execbrk == 0) {
70*965005c8Schin 		int treeflgs;
71*965005c8Schin 		unsigned char **com;
727c478bd9Sstevel@tonic-gate 		int type;
737c478bd9Sstevel@tonic-gate 		short pos;
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 		treeflgs = t->tretyp;
767c478bd9Sstevel@tonic-gate 		type = treeflgs & COMMSK;
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 		switch (type)
797c478bd9Sstevel@tonic-gate 		{
807c478bd9Sstevel@tonic-gate 		case TFND:
817c478bd9Sstevel@tonic-gate 			{
827c478bd9Sstevel@tonic-gate 				struct fndnod	*f = (struct fndnod *)t;
837c478bd9Sstevel@tonic-gate 				struct namnod	*n = lookup(f->fndnam);
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 				exitval = 0;
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 				if (n->namflg & N_RDONLY)
887c478bd9Sstevel@tonic-gate 					failed(n->namid, wtfailed);
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 				if (flags & rshflg && (n == &pathnod ||
917c478bd9Sstevel@tonic-gate 					eq(n->namid, "SHELL")))
927c478bd9Sstevel@tonic-gate 					failed(n->namid, restricted);
937c478bd9Sstevel@tonic-gate 				if (n->namflg & N_FUNCTN)
947c478bd9Sstevel@tonic-gate 					freefunc(n);
957c478bd9Sstevel@tonic-gate 				else
967c478bd9Sstevel@tonic-gate 				{
977c478bd9Sstevel@tonic-gate 					free(n->namval);
987c478bd9Sstevel@tonic-gate 					free(n->namenv);
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 					n->namval = 0;
1017c478bd9Sstevel@tonic-gate 					n->namflg &= ~(N_EXPORT | N_ENVCHG);
1027c478bd9Sstevel@tonic-gate 				}
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 				if (funcnt)
1057c478bd9Sstevel@tonic-gate 					f->fndval->tretyp++;
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 				n->namenv = (unsigned char *)f->fndval;
1087c478bd9Sstevel@tonic-gate 				attrib(n, N_FUNCTN);
1097c478bd9Sstevel@tonic-gate 				hash_func(n->namid);
1107c478bd9Sstevel@tonic-gate 				break;
1117c478bd9Sstevel@tonic-gate 			}
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 		case TCOM:
1147c478bd9Sstevel@tonic-gate 			{
1157c478bd9Sstevel@tonic-gate 				unsigned char	*a1, *name;
1167c478bd9Sstevel@tonic-gate 				int	argn, internal;
1177c478bd9Sstevel@tonic-gate 				struct argnod	*schain = gchain;
1187c478bd9Sstevel@tonic-gate 				struct ionod	*io = t->treio;
1197c478bd9Sstevel@tonic-gate 				short 	cmdhash;
1207c478bd9Sstevel@tonic-gate 				short	comtype;
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 				exitval = 0;
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 				gchain = 0;
1257c478bd9Sstevel@tonic-gate 				argn = getarg(t);
1267c478bd9Sstevel@tonic-gate 				com = scan(argn);
1277c478bd9Sstevel@tonic-gate 				a1 = com[1];
1287c478bd9Sstevel@tonic-gate 				gchain = schain;
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 				if (argn != 0)
1317c478bd9Sstevel@tonic-gate 					cmdhash = pathlook(com[0], 1, comptr(t)->comset);
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 				if (argn == 0 || (comtype = hashtype(cmdhash)) == BUILTIN) {
1347c478bd9Sstevel@tonic-gate 					setlist(comptr(t)->comset, 0);
1357c478bd9Sstevel@tonic-gate 				}
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 				if (argn && (flags&noexec) == 0)
1387c478bd9Sstevel@tonic-gate 				{
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 					/* print command if execpr */
1417c478bd9Sstevel@tonic-gate 					if (flags & execpr)
1427c478bd9Sstevel@tonic-gate 						execprint(com);
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 					if (comtype == NOTFOUND)
1457c478bd9Sstevel@tonic-gate 					{
1467c478bd9Sstevel@tonic-gate 						pos = hashdata(cmdhash);
1477c478bd9Sstevel@tonic-gate 						if (pos == 1)
1487c478bd9Sstevel@tonic-gate 							failure(*com, notfound);
1497c478bd9Sstevel@tonic-gate 						else if (pos == 2)
1507c478bd9Sstevel@tonic-gate 							failure(*com, badexec);
1517c478bd9Sstevel@tonic-gate 						else
1527c478bd9Sstevel@tonic-gate 							failure(*com, badperm);
1537c478bd9Sstevel@tonic-gate 						break;
1547c478bd9Sstevel@tonic-gate 					}
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 					else if (comtype == PATH_COMMAND)
1577c478bd9Sstevel@tonic-gate 					{
1587c478bd9Sstevel@tonic-gate 						pos = -1;
1597c478bd9Sstevel@tonic-gate 					}
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 					else if (comtype & (COMMAND | REL_COMMAND))
1627c478bd9Sstevel@tonic-gate 					{
1637c478bd9Sstevel@tonic-gate 						pos = hashdata(cmdhash);
1647c478bd9Sstevel@tonic-gate 					}
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 					else if (comtype == BUILTIN) {
1677c478bd9Sstevel@tonic-gate 						builtin(hashdata(cmdhash),argn,com,t);
1687c478bd9Sstevel@tonic-gate 						freejobs();
1697c478bd9Sstevel@tonic-gate 						break;
1707c478bd9Sstevel@tonic-gate 					}
1717c478bd9Sstevel@tonic-gate 					else if (comtype == FUNCTION)
1727c478bd9Sstevel@tonic-gate 					{
1737c478bd9Sstevel@tonic-gate 						struct dolnod *olddolh;
1747c478bd9Sstevel@tonic-gate 						struct namnod *n, *opt;
1757c478bd9Sstevel@tonic-gate 						short index;
1767c478bd9Sstevel@tonic-gate 						unsigned char **olddolv = dolv;
1777c478bd9Sstevel@tonic-gate 						int olddolc = dolc;
1787c478bd9Sstevel@tonic-gate 						n = findnam(com[0]);
1797c478bd9Sstevel@tonic-gate 					/* save current positional parameters */
1807c478bd9Sstevel@tonic-gate 						olddolh = (struct dolnod *)savargs(funcnt);
1817c478bd9Sstevel@tonic-gate 						funcnt++;
1827c478bd9Sstevel@tonic-gate 						index = initio(io, 1);
1837c478bd9Sstevel@tonic-gate 						setargs(com);
1847c478bd9Sstevel@tonic-gate 						execute((struct trenod *)(n->namenv), xflags, errorflg, pf1, pf2);
1857c478bd9Sstevel@tonic-gate 						execbrk = 0;
1867c478bd9Sstevel@tonic-gate 						restore(index);
1877c478bd9Sstevel@tonic-gate 						(void) restorargs(olddolh, funcnt);
1887c478bd9Sstevel@tonic-gate 						dolv = olddolv;
1897c478bd9Sstevel@tonic-gate 						dolc = olddolc;
1907c478bd9Sstevel@tonic-gate 						funcnt--;
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 						break;
1937c478bd9Sstevel@tonic-gate 					}
1947c478bd9Sstevel@tonic-gate 				}
1957c478bd9Sstevel@tonic-gate 				else if (t->treio == 0)
1967c478bd9Sstevel@tonic-gate 				{
1977c478bd9Sstevel@tonic-gate 					chktrap();
1987c478bd9Sstevel@tonic-gate 					break;
1997c478bd9Sstevel@tonic-gate 				}
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 			}
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 		case TFORK:
2047c478bd9Sstevel@tonic-gate 		{
2057c478bd9Sstevel@tonic-gate 			int monitor = 0;
2067c478bd9Sstevel@tonic-gate 			int linked = 0;
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 			exitval = 0;
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 			if (!(xflags & XEC_EXECED) || treeflgs&(FPOU|FAMP))
2117c478bd9Sstevel@tonic-gate 			{
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 				int forkcnt = 1;
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 				if (!(treeflgs&FPOU))
2167c478bd9Sstevel@tonic-gate 				{
2177c478bd9Sstevel@tonic-gate 					monitor = (!(xflags & XEC_NOSTOP)
2187c478bd9Sstevel@tonic-gate 					  && (flags&(monitorflg|jcflg|jcoff))
2197c478bd9Sstevel@tonic-gate 					  == (monitorflg|jcflg));
2207c478bd9Sstevel@tonic-gate 					if (monitor) {
2217c478bd9Sstevel@tonic-gate 						int savefd;
2227c478bd9Sstevel@tonic-gate 						unsigned char *savebot;
2237c478bd9Sstevel@tonic-gate 						savefd = setb(-1);
2247c478bd9Sstevel@tonic-gate 						savebot = stakbot;
2257c478bd9Sstevel@tonic-gate 						prcmd(t);
2267c478bd9Sstevel@tonic-gate 						(void)setb(savefd);
2277c478bd9Sstevel@tonic-gate 						allocjob(savebot, cwdget(), monitor);
2287c478bd9Sstevel@tonic-gate 					} else
2297c478bd9Sstevel@tonic-gate 						allocjob("", "", 0);
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 				}
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 				if (treeflgs & (FPOU|FAMP)) {
2347c478bd9Sstevel@tonic-gate 					link_iodocs(iotemp);
2357c478bd9Sstevel@tonic-gate 					linked = 1;
2367c478bd9Sstevel@tonic-gate 				}
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 				while ((parent = fork()) == -1)
2397c478bd9Sstevel@tonic-gate 				{
2407c478bd9Sstevel@tonic-gate 				/*
2417c478bd9Sstevel@tonic-gate 				 * FORKLIM is the max period between forks -
2427c478bd9Sstevel@tonic-gate 				 * power of 2 usually.	Currently shell tries
2437c478bd9Sstevel@tonic-gate 				 * after 2,4,8,16, and 32 seconds and then quits
2447c478bd9Sstevel@tonic-gate 				 */
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 				if ((forkcnt = (forkcnt * 2)) > FORKLIM)
2477c478bd9Sstevel@tonic-gate 				{
2487c478bd9Sstevel@tonic-gate 					switch (errno)
2497c478bd9Sstevel@tonic-gate 					{
2507c478bd9Sstevel@tonic-gate 					case ENOMEM:
2517c478bd9Sstevel@tonic-gate 						deallocjob();
2527c478bd9Sstevel@tonic-gate 						error(noswap);
2537c478bd9Sstevel@tonic-gate 						break;
2547c478bd9Sstevel@tonic-gate 					default:
2557c478bd9Sstevel@tonic-gate 						deallocjob();
2567c478bd9Sstevel@tonic-gate 						error(nofork);
2577c478bd9Sstevel@tonic-gate 						break;
2587c478bd9Sstevel@tonic-gate 					}
2597c478bd9Sstevel@tonic-gate 				} else if (errno == EPERM) {
2607c478bd9Sstevel@tonic-gate 					deallocjob();
2617c478bd9Sstevel@tonic-gate 					error(eacces);
2627c478bd9Sstevel@tonic-gate 					break;
2637c478bd9Sstevel@tonic-gate 				}
2647c478bd9Sstevel@tonic-gate 				sigchk();
265*965005c8Schin 				sh_sleep(forkcnt);
2667c478bd9Sstevel@tonic-gate 				}
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 				if (parent) {
2697c478bd9Sstevel@tonic-gate 					if (monitor)
2707c478bd9Sstevel@tonic-gate 						setpgid(parent, 0);
2717c478bd9Sstevel@tonic-gate 					if (treeflgs & FPIN)
2727c478bd9Sstevel@tonic-gate 						closepipe(pf1);
2737c478bd9Sstevel@tonic-gate 					if (!(treeflgs&FPOU)) {
2747c478bd9Sstevel@tonic-gate 						postjob(parent,!(treeflgs&FAMP));
2757c478bd9Sstevel@tonic-gate 						freejobs();
2767c478bd9Sstevel@tonic-gate 					}
2777c478bd9Sstevel@tonic-gate 					chktrap();
2787c478bd9Sstevel@tonic-gate 					break;
2797c478bd9Sstevel@tonic-gate 				}
2807c478bd9Sstevel@tonic-gate 				mypid = getpid();
2817c478bd9Sstevel@tonic-gate 			}
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 			/*
2847c478bd9Sstevel@tonic-gate 			 * Forked process:  assume it is not a subshell for
2857c478bd9Sstevel@tonic-gate 			 * now.  If it is, the presence of a left parenthesis
2867c478bd9Sstevel@tonic-gate 			 * will trigger the jcoff flag to be turned off.
2877c478bd9Sstevel@tonic-gate 			 * When jcoff is turned on, monitoring is not going on
2887c478bd9Sstevel@tonic-gate 			 * and waitpid will not look for WUNTRACED.
2897c478bd9Sstevel@tonic-gate 			 */
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 			flags |= (forked|jcoff);
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 			fiotemp  = 0;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 			if (linked == 1) {
2967c478bd9Sstevel@tonic-gate 				swap_iodoc_nm(iotemp);
2977c478bd9Sstevel@tonic-gate 				xflags |= XEC_LINKED;
2987c478bd9Sstevel@tonic-gate 			} else if (!(xflags & XEC_LINKED))
2997c478bd9Sstevel@tonic-gate 				iotemp = 0;
3007c478bd9Sstevel@tonic-gate #ifdef ACCT
3017c478bd9Sstevel@tonic-gate 			suspacct();
3027c478bd9Sstevel@tonic-gate #endif
3037c478bd9Sstevel@tonic-gate 			settmp();
3047c478bd9Sstevel@tonic-gate 			oldsigs();
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 			if (!(treeflgs & FPOU))
3077c478bd9Sstevel@tonic-gate 				makejob(monitor, !(treeflgs & FAMP));
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 			/*
3107c478bd9Sstevel@tonic-gate 			 * pipe in or out
3117c478bd9Sstevel@tonic-gate 			 */
3127c478bd9Sstevel@tonic-gate 			if (treeflgs & FPIN)
3137c478bd9Sstevel@tonic-gate 			{
3147c478bd9Sstevel@tonic-gate 				renamef(pf1[INPIPE], 0);
3157c478bd9Sstevel@tonic-gate 				close(pf1[OTPIPE]);
3167c478bd9Sstevel@tonic-gate 			}
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 			if (treeflgs & FPOU)
3197c478bd9Sstevel@tonic-gate 			{
3207c478bd9Sstevel@tonic-gate 				close(pf2[INPIPE]);
3217c478bd9Sstevel@tonic-gate 				renamef(pf2[OTPIPE], 1);
3227c478bd9Sstevel@tonic-gate 			}
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 			/*
3257c478bd9Sstevel@tonic-gate 			 * io redirection
3267c478bd9Sstevel@tonic-gate 			 */
3277c478bd9Sstevel@tonic-gate 			initio(t->treio, 0);
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 			if (type == TFORK)
3307c478bd9Sstevel@tonic-gate 				execute(forkptr(t)->forktre, xflags | XEC_EXECED, errorflg);
3317c478bd9Sstevel@tonic-gate 			else if (com[0] != ENDARGS)
3327c478bd9Sstevel@tonic-gate 			{
3337c478bd9Sstevel@tonic-gate 				eflag = 0;
3347c478bd9Sstevel@tonic-gate 				setlist(comptr(t)->comset, N_EXPORT);
3357c478bd9Sstevel@tonic-gate 				rmtemp(0);
3367c478bd9Sstevel@tonic-gate 				clearjobs();
3377c478bd9Sstevel@tonic-gate 				execa(com, pos);
3387c478bd9Sstevel@tonic-gate 			}
3397c478bd9Sstevel@tonic-gate 			done(0);
3407c478bd9Sstevel@tonic-gate 		}
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 		case TPAR:
3437c478bd9Sstevel@tonic-gate 			/* Forked process is subshell:  may want job control */
3447c478bd9Sstevel@tonic-gate 			flags &= ~jcoff;
3457c478bd9Sstevel@tonic-gate 			clearjobs();
3467c478bd9Sstevel@tonic-gate 			execute(parptr(t)->partre, xflags, errorflg);
3477c478bd9Sstevel@tonic-gate 			done(0);
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 		case TFIL:
3507c478bd9Sstevel@tonic-gate 			{
3517c478bd9Sstevel@tonic-gate 				int pv[2];
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 				chkpipe(pv);
3547c478bd9Sstevel@tonic-gate 				if (execute(lstptr(t)->lstlef, xflags & XEC_NOSTOP, errorflg, pf1, pv) == 0)
3557c478bd9Sstevel@tonic-gate 					execute(lstptr(t)->lstrit, xflags, errorflg, pv, pf2);
3567c478bd9Sstevel@tonic-gate 				else
3577c478bd9Sstevel@tonic-gate 					closepipe(pv);
3587c478bd9Sstevel@tonic-gate 			}
3597c478bd9Sstevel@tonic-gate 			break;
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 		case TLST:
3627c478bd9Sstevel@tonic-gate 			execute(lstptr(t)->lstlef, xflags&XEC_NOSTOP, errorflg);
3637c478bd9Sstevel@tonic-gate 			/* Update errorflg if set -e is invoked in the sub-sh*/
3647c478bd9Sstevel@tonic-gate 			execute(lstptr(t)->lstrit, xflags, (errorflg | (eflag & errflg)));
3657c478bd9Sstevel@tonic-gate 			break;
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 		case TAND:
3687c478bd9Sstevel@tonic-gate 		case TORF:
3697c478bd9Sstevel@tonic-gate 		{
370*965005c8Schin 			int xval;
3717c478bd9Sstevel@tonic-gate 			xval = execute(lstptr(t)->lstlef, XEC_NOSTOP, 0);
3727c478bd9Sstevel@tonic-gate 			if ((xval == 0) == (type == TAND))
3737c478bd9Sstevel@tonic-gate 				execute(lstptr(t)->lstrit, xflags|XEC_NOSTOP, errorflg);
3747c478bd9Sstevel@tonic-gate 			break;
3757c478bd9Sstevel@tonic-gate 		}
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 		case TFOR:
3787c478bd9Sstevel@tonic-gate 			{
3797c478bd9Sstevel@tonic-gate 				struct namnod *n = lookup(forptr(t)->fornam);
3807c478bd9Sstevel@tonic-gate 				unsigned char	**args;
3817c478bd9Sstevel@tonic-gate 				struct dolnod *argsav = 0;
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 				if (forptr(t)->forlst == 0)
3847c478bd9Sstevel@tonic-gate 				{
3857c478bd9Sstevel@tonic-gate 					args = dolv + 1;
3867c478bd9Sstevel@tonic-gate 					argsav = useargs();
3877c478bd9Sstevel@tonic-gate 				}
3887c478bd9Sstevel@tonic-gate 				else
3897c478bd9Sstevel@tonic-gate 				{
3907c478bd9Sstevel@tonic-gate 					struct argnod *schain = gchain;
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 					gchain = 0;
3937c478bd9Sstevel@tonic-gate 					args = scan(getarg(forptr(t)->forlst));
3947c478bd9Sstevel@tonic-gate 					gchain = schain;
3957c478bd9Sstevel@tonic-gate 				}
3967c478bd9Sstevel@tonic-gate 				loopcnt++;
3977c478bd9Sstevel@tonic-gate 				while (*args != ENDARGS && execbrk == 0)
3987c478bd9Sstevel@tonic-gate 				{
3997c478bd9Sstevel@tonic-gate 					assign(n, *args++);
4007c478bd9Sstevel@tonic-gate 					execute(forptr(t)->fortre, XEC_NOSTOP, errorflg);
4017c478bd9Sstevel@tonic-gate 					if (breakcnt < 0)
4027c478bd9Sstevel@tonic-gate 						execbrk = (++breakcnt != 0);
4037c478bd9Sstevel@tonic-gate 				}
4047c478bd9Sstevel@tonic-gate 				if (breakcnt > 0)
4057c478bd9Sstevel@tonic-gate 						execbrk = (--breakcnt != 0);
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 				loopcnt--;
4087c478bd9Sstevel@tonic-gate 				if(argsav)
4097c478bd9Sstevel@tonic-gate 					argfor = (struct dolnod *)freeargs(argsav);
4107c478bd9Sstevel@tonic-gate 			}
4117c478bd9Sstevel@tonic-gate 			break;
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 		case TWH:
4147c478bd9Sstevel@tonic-gate 		case TUN:
4157c478bd9Sstevel@tonic-gate 			{
4167c478bd9Sstevel@tonic-gate 				int	i = 0;
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 				loopcnt++;
4197c478bd9Sstevel@tonic-gate 				while (execbrk == 0 && (execute(whptr(t)->whtre,
4207c478bd9Sstevel@tonic-gate 				    XEC_NOSTOP, 0) == 0) == (type == TWH) &&
4217c478bd9Sstevel@tonic-gate 				    (flags&noexec) == 0)
4227c478bd9Sstevel@tonic-gate {
4237c478bd9Sstevel@tonic-gate 					i = execute(whptr(t)->dotre, XEC_NOSTOP, errorflg);
4247c478bd9Sstevel@tonic-gate 					if (breakcnt < 0)
4257c478bd9Sstevel@tonic-gate 						execbrk = (++breakcnt != 0);
4267c478bd9Sstevel@tonic-gate 				}
4277c478bd9Sstevel@tonic-gate 				if (breakcnt > 0)
4287c478bd9Sstevel@tonic-gate 						execbrk = (--breakcnt != 0);
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 				loopcnt--;
4317c478bd9Sstevel@tonic-gate 				exitval = i;
4327c478bd9Sstevel@tonic-gate 			}
4337c478bd9Sstevel@tonic-gate 			break;
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 		case TIF:
4367c478bd9Sstevel@tonic-gate 			if (execute(ifptr(t)->iftre, XEC_NOSTOP, 0) == 0)
4377c478bd9Sstevel@tonic-gate 				execute(ifptr(t)->thtre, xflags|XEC_NOSTOP, errorflg);
4387c478bd9Sstevel@tonic-gate 			else if (ifptr(t)->eltre)
4397c478bd9Sstevel@tonic-gate 				execute(ifptr(t)->eltre, xflags|XEC_NOSTOP, errorflg);
4407c478bd9Sstevel@tonic-gate 			else
4417c478bd9Sstevel@tonic-gate 				exitval = 0;	/* force zero exit for if-then-fi */
4427c478bd9Sstevel@tonic-gate 			break;
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 		case TSW:
4457c478bd9Sstevel@tonic-gate 			{
446*965005c8Schin 				unsigned char	*r = mactrim(swptr(t)->swarg);
447*965005c8Schin 				struct regnod *regp;
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 				regp = swptr(t)->swlst;
4507c478bd9Sstevel@tonic-gate 				while (regp)
4517c478bd9Sstevel@tonic-gate 				{
4527c478bd9Sstevel@tonic-gate 					struct argnod *rex = regp->regptr;
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 					while (rex)
4557c478bd9Sstevel@tonic-gate 					{
456*965005c8Schin 						unsigned char	*s;
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 						if (gmatch(r, s = macro(rex->argval)) || (trim(s), eq(r, s)))
4597c478bd9Sstevel@tonic-gate 						{
4607c478bd9Sstevel@tonic-gate 							execute(regp->regcom, XEC_NOSTOP, errorflg);
4617c478bd9Sstevel@tonic-gate 							regp = 0;
4627c478bd9Sstevel@tonic-gate 							break;
4637c478bd9Sstevel@tonic-gate 						}
4647c478bd9Sstevel@tonic-gate 						else
4657c478bd9Sstevel@tonic-gate 							rex = rex->argnxt;
4667c478bd9Sstevel@tonic-gate 					}
4677c478bd9Sstevel@tonic-gate 					if (regp)
4687c478bd9Sstevel@tonic-gate 						regp = regp->regnxt;
4697c478bd9Sstevel@tonic-gate 				}
4707c478bd9Sstevel@tonic-gate 			}
4717c478bd9Sstevel@tonic-gate 			break;
4727c478bd9Sstevel@tonic-gate 		}
4737c478bd9Sstevel@tonic-gate 		exitset();
4747c478bd9Sstevel@tonic-gate 	}
4757c478bd9Sstevel@tonic-gate 	sigchk();
4767c478bd9Sstevel@tonic-gate 	tdystak(sav);
4777c478bd9Sstevel@tonic-gate 	flags |= eflag;
4787c478bd9Sstevel@tonic-gate 	return(exitval);
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate 
481*965005c8Schin void
482*965005c8Schin execexp(unsigned char *s, int f)
4837c478bd9Sstevel@tonic-gate {
4847c478bd9Sstevel@tonic-gate 	struct fileblk	fb;
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	push(&fb);
4877c478bd9Sstevel@tonic-gate 	if (s)
4887c478bd9Sstevel@tonic-gate 	{
4897c478bd9Sstevel@tonic-gate 		estabf(s);
4907c478bd9Sstevel@tonic-gate 		fb.feval = (unsigned char **)(f);
4917c478bd9Sstevel@tonic-gate 	}
4927c478bd9Sstevel@tonic-gate 	else if (f >= 0)
4937c478bd9Sstevel@tonic-gate 		initf(f);
4947c478bd9Sstevel@tonic-gate 	execute(cmd(NL, NLFLG | MTFLG), 0, (int)(flags & errflg));
4957c478bd9Sstevel@tonic-gate 	pop();
4967c478bd9Sstevel@tonic-gate }
4977c478bd9Sstevel@tonic-gate 
498*965005c8Schin void
499*965005c8Schin execprint(unsigned char **com)
5007c478bd9Sstevel@tonic-gate {
501*965005c8Schin 	int 	argn = 0;
5027c478bd9Sstevel@tonic-gate 	unsigned char	*s;
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	prs(execpmsg);
5057c478bd9Sstevel@tonic-gate 	while(com[argn] != ENDARGS)
5067c478bd9Sstevel@tonic-gate 	{
5077c478bd9Sstevel@tonic-gate 		s = com[argn++];
5087c478bd9Sstevel@tonic-gate 		write(output, s, length(s) - 1);
5097c478bd9Sstevel@tonic-gate 		blank();
5107c478bd9Sstevel@tonic-gate 	}
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	newline();
5137c478bd9Sstevel@tonic-gate }
514