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