xref: /titanic_50/usr/src/cmd/sh/xec.c (revision d6b882a974afe4a3ab38793d5de10bae2e078d39)
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
539e7390aSna195498  * Common Development and Distribution License (the "License").
639e7390aSna195498  * 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*d6b882a9SNobutomo Nakano  * Copyright 2009 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 /*
317c478bd9Sstevel@tonic-gate  *
327c478bd9Sstevel@tonic-gate  * UNIX shell
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include	"defs.h"
387c478bd9Sstevel@tonic-gate #include	<errno.h>
397c478bd9Sstevel@tonic-gate #include	"sym.h"
407c478bd9Sstevel@tonic-gate #include	"hash.h"
417c478bd9Sstevel@tonic-gate #include	<sys/types.h>
427c478bd9Sstevel@tonic-gate #include	<sys/times.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate pid_t parent;
457c478bd9Sstevel@tonic-gate 
46965005c8Schin void execprint(unsigned char **);
47965005c8Schin 
487c478bd9Sstevel@tonic-gate /* ========	command execution	======== */
497c478bd9Sstevel@tonic-gate 
50965005c8Schin /*VARARGS3*/
51965005c8Schin int
execute(argt,xflags,errorflg,pf1,pf2)527c478bd9Sstevel@tonic-gate execute(argt, xflags, errorflg, pf1, pf2)
537c478bd9Sstevel@tonic-gate struct trenod *argt;
54965005c8Schin int xflags, errorflg;
557c478bd9Sstevel@tonic-gate int *pf1, *pf2;
567c478bd9Sstevel@tonic-gate {
577c478bd9Sstevel@tonic-gate 	/*
587c478bd9Sstevel@tonic-gate 	 * `stakbot' is preserved by this routine
597c478bd9Sstevel@tonic-gate 	 */
60965005c8Schin 	struct trenod	*t;
617c478bd9Sstevel@tonic-gate 	unsigned char		*sav = savstak();
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate 	sigchk();
647c478bd9Sstevel@tonic-gate 	if (!errorflg)
657c478bd9Sstevel@tonic-gate 		flags &= ~errflg;
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate 	if ((t = argt) && execbrk == 0) {
68965005c8Schin 		int treeflgs;
69965005c8Schin 		unsigned char **com;
707c478bd9Sstevel@tonic-gate 		int type;
717c478bd9Sstevel@tonic-gate 		short pos;
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate 		treeflgs = t->tretyp;
747c478bd9Sstevel@tonic-gate 		type = treeflgs & COMMSK;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 		switch (type)
777c478bd9Sstevel@tonic-gate 		{
787c478bd9Sstevel@tonic-gate 		case TFND:
797c478bd9Sstevel@tonic-gate 			{
80*d6b882a9SNobutomo Nakano 				struct fndnod	*f = fndptr(t);
817c478bd9Sstevel@tonic-gate 				struct namnod	*n = lookup(f->fndnam);
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 				exitval = 0;
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 				if (n->namflg & N_RDONLY)
867c478bd9Sstevel@tonic-gate 					failed(n->namid, wtfailed);
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 				if (flags & rshflg && (n == &pathnod ||
897c478bd9Sstevel@tonic-gate 					eq(n->namid, "SHELL")))
907c478bd9Sstevel@tonic-gate 					failed(n->namid, restricted);
91*d6b882a9SNobutomo Nakano 				/*
92*d6b882a9SNobutomo Nakano 				 * If function of same name is previously
93*d6b882a9SNobutomo Nakano 				 * defined, it will no longer be used.
94*d6b882a9SNobutomo Nakano 				 */
95*d6b882a9SNobutomo Nakano 				if (n->namflg & N_FUNCTN) {
967c478bd9Sstevel@tonic-gate 					freefunc(n);
97*d6b882a9SNobutomo Nakano 				} else {
987c478bd9Sstevel@tonic-gate 					free(n->namval);
997c478bd9Sstevel@tonic-gate 					free(n->namenv);
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 					n->namval = 0;
1027c478bd9Sstevel@tonic-gate 					n->namflg &= ~(N_EXPORT | N_ENVCHG);
1037c478bd9Sstevel@tonic-gate 				}
104*d6b882a9SNobutomo Nakano 				/*
105*d6b882a9SNobutomo Nakano 				 * If function is defined within function,
106*d6b882a9SNobutomo Nakano 				 * we don't want to free it along with the
107*d6b882a9SNobutomo Nakano 				 * free of the defining function. If we are
108*d6b882a9SNobutomo Nakano 				 * in a loop, fndnod may be reused, so it
109*d6b882a9SNobutomo Nakano 				 * should never be freed.
110*d6b882a9SNobutomo Nakano 				 */
111*d6b882a9SNobutomo Nakano 				if (funcnt != 0 || loopcnt != 0)
112*d6b882a9SNobutomo Nakano 					f->fndref++;
1137c478bd9Sstevel@tonic-gate 
114*d6b882a9SNobutomo Nakano 				/*
115*d6b882a9SNobutomo Nakano 				 * We hang a fndnod on the namenv so that
116*d6b882a9SNobutomo Nakano 				 * ref cnt(fndref) can be increased while
117*d6b882a9SNobutomo Nakano 				 * running in the function.
118*d6b882a9SNobutomo Nakano 				 */
119*d6b882a9SNobutomo Nakano 				n->namenv = (unsigned char *)f;
1207c478bd9Sstevel@tonic-gate 				attrib(n, N_FUNCTN);
1217c478bd9Sstevel@tonic-gate 				hash_func(n->namid);
1227c478bd9Sstevel@tonic-gate 				break;
1237c478bd9Sstevel@tonic-gate 			}
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 		case TCOM:
1267c478bd9Sstevel@tonic-gate 			{
1277c478bd9Sstevel@tonic-gate 				unsigned char	*a1, *name;
1287c478bd9Sstevel@tonic-gate 				int	argn, internal;
1297c478bd9Sstevel@tonic-gate 				struct argnod	*schain = gchain;
1307c478bd9Sstevel@tonic-gate 				struct ionod	*io = t->treio;
1317c478bd9Sstevel@tonic-gate 				short 	cmdhash;
1327c478bd9Sstevel@tonic-gate 				short	comtype;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 				exitval = 0;
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 				gchain = 0;
1377c478bd9Sstevel@tonic-gate 				argn = getarg(t);
1387c478bd9Sstevel@tonic-gate 				com = scan(argn);
1397c478bd9Sstevel@tonic-gate 				a1 = com[1];
1407c478bd9Sstevel@tonic-gate 				gchain = schain;
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 				if (argn != 0)
1437c478bd9Sstevel@tonic-gate 					cmdhash = pathlook(com[0], 1, comptr(t)->comset);
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 				if (argn == 0 || (comtype = hashtype(cmdhash)) == BUILTIN) {
1467c478bd9Sstevel@tonic-gate 					setlist(comptr(t)->comset, 0);
1477c478bd9Sstevel@tonic-gate 				}
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 				if (argn && (flags&noexec) == 0)
1507c478bd9Sstevel@tonic-gate 				{
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 					/* print command if execpr */
1537c478bd9Sstevel@tonic-gate 					if (flags & execpr)
1547c478bd9Sstevel@tonic-gate 						execprint(com);
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 					if (comtype == NOTFOUND)
1577c478bd9Sstevel@tonic-gate 					{
1587c478bd9Sstevel@tonic-gate 						pos = hashdata(cmdhash);
1597c478bd9Sstevel@tonic-gate 						if (pos == 1)
1607c478bd9Sstevel@tonic-gate 							failure(*com, notfound);
1617c478bd9Sstevel@tonic-gate 						else if (pos == 2)
1627c478bd9Sstevel@tonic-gate 							failure(*com, badexec);
1637c478bd9Sstevel@tonic-gate 						else
1647c478bd9Sstevel@tonic-gate 							failure(*com, badperm);
1657c478bd9Sstevel@tonic-gate 						break;
1667c478bd9Sstevel@tonic-gate 					}
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 					else if (comtype == PATH_COMMAND)
1697c478bd9Sstevel@tonic-gate 					{
1707c478bd9Sstevel@tonic-gate 						pos = -1;
1717c478bd9Sstevel@tonic-gate 					}
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 					else if (comtype & (COMMAND | REL_COMMAND))
1747c478bd9Sstevel@tonic-gate 					{
1757c478bd9Sstevel@tonic-gate 						pos = hashdata(cmdhash);
1767c478bd9Sstevel@tonic-gate 					}
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 					else if (comtype == BUILTIN) {
1797c478bd9Sstevel@tonic-gate 						builtin(hashdata(cmdhash),argn,com,t);
1807c478bd9Sstevel@tonic-gate 						freejobs();
1817c478bd9Sstevel@tonic-gate 						break;
1827c478bd9Sstevel@tonic-gate 					}
1837c478bd9Sstevel@tonic-gate 					else if (comtype == FUNCTION)
1847c478bd9Sstevel@tonic-gate 					{
1857c478bd9Sstevel@tonic-gate 						struct dolnod *olddolh;
1867c478bd9Sstevel@tonic-gate 						struct namnod *n, *opt;
187*d6b882a9SNobutomo Nakano 						struct fndnod *f;
1887c478bd9Sstevel@tonic-gate 						short index;
1897c478bd9Sstevel@tonic-gate 						unsigned char **olddolv = dolv;
1907c478bd9Sstevel@tonic-gate 						int olddolc = dolc;
191*d6b882a9SNobutomo Nakano 
1927c478bd9Sstevel@tonic-gate 						n = findnam(com[0]);
193*d6b882a9SNobutomo Nakano 						f = fndptr(n->namenv);
194*d6b882a9SNobutomo Nakano 						/* just in case */
195*d6b882a9SNobutomo Nakano 						if (f == NULL)
196*d6b882a9SNobutomo Nakano 							break;
1977c478bd9Sstevel@tonic-gate 					/* save current positional parameters */
1987c478bd9Sstevel@tonic-gate 						olddolh = (struct dolnod *)savargs(funcnt);
199*d6b882a9SNobutomo Nakano 						f->fndref++;
2007c478bd9Sstevel@tonic-gate 						funcnt++;
2017c478bd9Sstevel@tonic-gate 						index = initio(io, 1);
2027c478bd9Sstevel@tonic-gate 						setargs(com);
203*d6b882a9SNobutomo Nakano 						execute(f->fndval, xflags,
204*d6b882a9SNobutomo Nakano 						    errorflg, pf1, pf2);
2057c478bd9Sstevel@tonic-gate 						execbrk = 0;
2067c478bd9Sstevel@tonic-gate 						restore(index);
2077c478bd9Sstevel@tonic-gate 						(void) restorargs(olddolh, funcnt);
2087c478bd9Sstevel@tonic-gate 						dolv = olddolv;
2097c478bd9Sstevel@tonic-gate 						dolc = olddolc;
2107c478bd9Sstevel@tonic-gate 						funcnt--;
211*d6b882a9SNobutomo Nakano 						/*
212*d6b882a9SNobutomo Nakano 						 * n->namenv may have been
213*d6b882a9SNobutomo Nakano 						 * pointing different func.
214*d6b882a9SNobutomo Nakano 						 * Therefore, we can't use
215*d6b882a9SNobutomo Nakano 						 * freefunc(n).
216*d6b882a9SNobutomo Nakano 						 */
217*d6b882a9SNobutomo Nakano 						freetree((struct trenod *)f);
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 						break;
2207c478bd9Sstevel@tonic-gate 					}
2217c478bd9Sstevel@tonic-gate 				}
2227c478bd9Sstevel@tonic-gate 				else if (t->treio == 0)
2237c478bd9Sstevel@tonic-gate 				{
2247c478bd9Sstevel@tonic-gate 					chktrap();
2257c478bd9Sstevel@tonic-gate 					break;
2267c478bd9Sstevel@tonic-gate 				}
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 			}
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 		case TFORK:
2317c478bd9Sstevel@tonic-gate 		{
2327c478bd9Sstevel@tonic-gate 			int monitor = 0;
2337c478bd9Sstevel@tonic-gate 			int linked = 0;
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 			exitval = 0;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 			if (!(xflags & XEC_EXECED) || treeflgs&(FPOU|FAMP))
2387c478bd9Sstevel@tonic-gate 			{
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 				int forkcnt = 1;
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 				if (!(treeflgs&FPOU))
2437c478bd9Sstevel@tonic-gate 				{
2447c478bd9Sstevel@tonic-gate 					monitor = (!(xflags & XEC_NOSTOP)
2457c478bd9Sstevel@tonic-gate 					  && (flags&(monitorflg|jcflg|jcoff))
2467c478bd9Sstevel@tonic-gate 					  == (monitorflg|jcflg));
2477c478bd9Sstevel@tonic-gate 					if (monitor) {
2487c478bd9Sstevel@tonic-gate 						int savefd;
2497c478bd9Sstevel@tonic-gate 						unsigned char *savebot;
2507c478bd9Sstevel@tonic-gate 						savefd = setb(-1);
2517c478bd9Sstevel@tonic-gate 						savebot = stakbot;
2527c478bd9Sstevel@tonic-gate 						prcmd(t);
2537c478bd9Sstevel@tonic-gate 						(void)setb(savefd);
2547c478bd9Sstevel@tonic-gate 						allocjob(savebot, cwdget(), monitor);
2557c478bd9Sstevel@tonic-gate 					} else
2567c478bd9Sstevel@tonic-gate 						allocjob("", "", 0);
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 				}
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 				if (treeflgs & (FPOU|FAMP)) {
2617c478bd9Sstevel@tonic-gate 					link_iodocs(iotemp);
2627c478bd9Sstevel@tonic-gate 					linked = 1;
2637c478bd9Sstevel@tonic-gate 				}
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 				while ((parent = fork()) == -1)
2667c478bd9Sstevel@tonic-gate 				{
2677c478bd9Sstevel@tonic-gate 				/*
2687c478bd9Sstevel@tonic-gate 				 * FORKLIM is the max period between forks -
2697c478bd9Sstevel@tonic-gate 				 * power of 2 usually.	Currently shell tries
2707c478bd9Sstevel@tonic-gate 				 * after 2,4,8,16, and 32 seconds and then quits
2717c478bd9Sstevel@tonic-gate 				 */
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 				if ((forkcnt = (forkcnt * 2)) > FORKLIM)
2747c478bd9Sstevel@tonic-gate 				{
2757c478bd9Sstevel@tonic-gate 					switch (errno)
2767c478bd9Sstevel@tonic-gate 					{
2777c478bd9Sstevel@tonic-gate 					case ENOMEM:
2787c478bd9Sstevel@tonic-gate 						deallocjob();
2797c478bd9Sstevel@tonic-gate 						error(noswap);
2807c478bd9Sstevel@tonic-gate 						break;
2817c478bd9Sstevel@tonic-gate 					default:
2827c478bd9Sstevel@tonic-gate 						deallocjob();
2837c478bd9Sstevel@tonic-gate 						error(nofork);
2847c478bd9Sstevel@tonic-gate 						break;
2857c478bd9Sstevel@tonic-gate 					}
2867c478bd9Sstevel@tonic-gate 				} else if (errno == EPERM) {
2877c478bd9Sstevel@tonic-gate 					deallocjob();
2887c478bd9Sstevel@tonic-gate 					error(eacces);
2897c478bd9Sstevel@tonic-gate 					break;
2907c478bd9Sstevel@tonic-gate 				}
2917c478bd9Sstevel@tonic-gate 				sigchk();
292965005c8Schin 				sh_sleep(forkcnt);
2937c478bd9Sstevel@tonic-gate 				}
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 				if (parent) {
2967c478bd9Sstevel@tonic-gate 					if (monitor)
2977c478bd9Sstevel@tonic-gate 						setpgid(parent, 0);
2987c478bd9Sstevel@tonic-gate 					if (treeflgs & FPIN)
2997c478bd9Sstevel@tonic-gate 						closepipe(pf1);
3007c478bd9Sstevel@tonic-gate 					if (!(treeflgs&FPOU)) {
3017c478bd9Sstevel@tonic-gate 						postjob(parent,!(treeflgs&FAMP));
3027c478bd9Sstevel@tonic-gate 						freejobs();
3037c478bd9Sstevel@tonic-gate 					}
3047c478bd9Sstevel@tonic-gate 					chktrap();
3057c478bd9Sstevel@tonic-gate 					break;
3067c478bd9Sstevel@tonic-gate 				}
3077c478bd9Sstevel@tonic-gate 				mypid = getpid();
3087c478bd9Sstevel@tonic-gate 			}
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 			/*
3117c478bd9Sstevel@tonic-gate 			 * Forked process:  assume it is not a subshell for
3127c478bd9Sstevel@tonic-gate 			 * now.  If it is, the presence of a left parenthesis
3137c478bd9Sstevel@tonic-gate 			 * will trigger the jcoff flag to be turned off.
3147c478bd9Sstevel@tonic-gate 			 * When jcoff is turned on, monitoring is not going on
3157c478bd9Sstevel@tonic-gate 			 * and waitpid will not look for WUNTRACED.
3167c478bd9Sstevel@tonic-gate 			 */
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 			flags |= (forked|jcoff);
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 			fiotemp  = 0;
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 			if (linked == 1) {
3237c478bd9Sstevel@tonic-gate 				swap_iodoc_nm(iotemp);
3247c478bd9Sstevel@tonic-gate 				xflags |= XEC_LINKED;
3257c478bd9Sstevel@tonic-gate 			} else if (!(xflags & XEC_LINKED))
3267c478bd9Sstevel@tonic-gate 				iotemp = 0;
3277c478bd9Sstevel@tonic-gate #ifdef ACCT
3287c478bd9Sstevel@tonic-gate 			suspacct();
3297c478bd9Sstevel@tonic-gate #endif
3307c478bd9Sstevel@tonic-gate 			settmp();
3317c478bd9Sstevel@tonic-gate 			oldsigs();
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 			if (!(treeflgs & FPOU))
3347c478bd9Sstevel@tonic-gate 				makejob(monitor, !(treeflgs & FAMP));
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 			/*
3377c478bd9Sstevel@tonic-gate 			 * pipe in or out
3387c478bd9Sstevel@tonic-gate 			 */
3397c478bd9Sstevel@tonic-gate 			if (treeflgs & FPIN)
3407c478bd9Sstevel@tonic-gate 			{
3417c478bd9Sstevel@tonic-gate 				renamef(pf1[INPIPE], 0);
3427c478bd9Sstevel@tonic-gate 				close(pf1[OTPIPE]);
3437c478bd9Sstevel@tonic-gate 			}
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 			if (treeflgs & FPOU)
3467c478bd9Sstevel@tonic-gate 			{
3477c478bd9Sstevel@tonic-gate 				close(pf2[INPIPE]);
3487c478bd9Sstevel@tonic-gate 				renamef(pf2[OTPIPE], 1);
3497c478bd9Sstevel@tonic-gate 			}
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 			/*
3527c478bd9Sstevel@tonic-gate 			 * io redirection
3537c478bd9Sstevel@tonic-gate 			 */
3547c478bd9Sstevel@tonic-gate 			initio(t->treio, 0);
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 			if (type == TFORK)
3577c478bd9Sstevel@tonic-gate 				execute(forkptr(t)->forktre, xflags | XEC_EXECED, errorflg);
3587c478bd9Sstevel@tonic-gate 			else if (com[0] != ENDARGS)
3597c478bd9Sstevel@tonic-gate 			{
3607c478bd9Sstevel@tonic-gate 				eflag = 0;
3617c478bd9Sstevel@tonic-gate 				setlist(comptr(t)->comset, N_EXPORT);
3627c478bd9Sstevel@tonic-gate 				rmtemp(0);
3637c478bd9Sstevel@tonic-gate 				clearjobs();
3647c478bd9Sstevel@tonic-gate 				execa(com, pos);
3657c478bd9Sstevel@tonic-gate 			}
3667c478bd9Sstevel@tonic-gate 			done(0);
3677c478bd9Sstevel@tonic-gate 		}
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 		case TPAR:
3707c478bd9Sstevel@tonic-gate 			/* Forked process is subshell:  may want job control */
3717c478bd9Sstevel@tonic-gate 			flags &= ~jcoff;
3727c478bd9Sstevel@tonic-gate 			clearjobs();
3737c478bd9Sstevel@tonic-gate 			execute(parptr(t)->partre, xflags, errorflg);
3747c478bd9Sstevel@tonic-gate 			done(0);
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 		case TFIL:
3777c478bd9Sstevel@tonic-gate 			{
3787c478bd9Sstevel@tonic-gate 				int pv[2];
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 				chkpipe(pv);
3817c478bd9Sstevel@tonic-gate 				if (execute(lstptr(t)->lstlef, xflags & XEC_NOSTOP, errorflg, pf1, pv) == 0)
3827c478bd9Sstevel@tonic-gate 					execute(lstptr(t)->lstrit, xflags, errorflg, pv, pf2);
3837c478bd9Sstevel@tonic-gate 				else
3847c478bd9Sstevel@tonic-gate 					closepipe(pv);
3857c478bd9Sstevel@tonic-gate 			}
3867c478bd9Sstevel@tonic-gate 			break;
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 		case TLST:
3897c478bd9Sstevel@tonic-gate 			execute(lstptr(t)->lstlef, xflags&XEC_NOSTOP, errorflg);
3907c478bd9Sstevel@tonic-gate 			/* Update errorflg if set -e is invoked in the sub-sh*/
3917c478bd9Sstevel@tonic-gate 			execute(lstptr(t)->lstrit, xflags, (errorflg | (eflag & errflg)));
3927c478bd9Sstevel@tonic-gate 			break;
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 		case TAND:
3957c478bd9Sstevel@tonic-gate 		case TORF:
3967c478bd9Sstevel@tonic-gate 		{
397965005c8Schin 			int xval;
3987c478bd9Sstevel@tonic-gate 			xval = execute(lstptr(t)->lstlef, XEC_NOSTOP, 0);
3997c478bd9Sstevel@tonic-gate 			if ((xval == 0) == (type == TAND))
4007c478bd9Sstevel@tonic-gate 				execute(lstptr(t)->lstrit, xflags|XEC_NOSTOP, errorflg);
4017c478bd9Sstevel@tonic-gate 			break;
4027c478bd9Sstevel@tonic-gate 		}
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 		case TFOR:
4057c478bd9Sstevel@tonic-gate 			{
4067c478bd9Sstevel@tonic-gate 				struct namnod *n = lookup(forptr(t)->fornam);
4077c478bd9Sstevel@tonic-gate 				unsigned char	**args;
4087c478bd9Sstevel@tonic-gate 				struct dolnod *argsav = 0;
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 				if (forptr(t)->forlst == 0)
4117c478bd9Sstevel@tonic-gate 				{
4127c478bd9Sstevel@tonic-gate 					args = dolv + 1;
4137c478bd9Sstevel@tonic-gate 					argsav = useargs();
4147c478bd9Sstevel@tonic-gate 				}
4157c478bd9Sstevel@tonic-gate 				else
4167c478bd9Sstevel@tonic-gate 				{
4177c478bd9Sstevel@tonic-gate 					struct argnod *schain = gchain;
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 					gchain = 0;
4207c478bd9Sstevel@tonic-gate 					args = scan(getarg(forptr(t)->forlst));
4217c478bd9Sstevel@tonic-gate 					gchain = schain;
4227c478bd9Sstevel@tonic-gate 				}
4237c478bd9Sstevel@tonic-gate 				loopcnt++;
4247c478bd9Sstevel@tonic-gate 				while (*args != ENDARGS && execbrk == 0)
4257c478bd9Sstevel@tonic-gate 				{
4267c478bd9Sstevel@tonic-gate 					assign(n, *args++);
4277c478bd9Sstevel@tonic-gate 					execute(forptr(t)->fortre, XEC_NOSTOP, errorflg);
4287c478bd9Sstevel@tonic-gate 					if (breakcnt < 0)
4297c478bd9Sstevel@tonic-gate 						execbrk = (++breakcnt != 0);
4307c478bd9Sstevel@tonic-gate 				}
4317c478bd9Sstevel@tonic-gate 				if (breakcnt > 0)
4327c478bd9Sstevel@tonic-gate 						execbrk = (--breakcnt != 0);
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 				loopcnt--;
4357c478bd9Sstevel@tonic-gate 				if(argsav)
4367c478bd9Sstevel@tonic-gate 					argfor = (struct dolnod *)freeargs(argsav);
4377c478bd9Sstevel@tonic-gate 			}
4387c478bd9Sstevel@tonic-gate 			break;
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 		case TWH:
4417c478bd9Sstevel@tonic-gate 		case TUN:
4427c478bd9Sstevel@tonic-gate 			{
4437c478bd9Sstevel@tonic-gate 				int	i = 0;
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 				loopcnt++;
4467c478bd9Sstevel@tonic-gate 				while (execbrk == 0 && (execute(whptr(t)->whtre,
4477c478bd9Sstevel@tonic-gate 				    XEC_NOSTOP, 0) == 0) == (type == TWH) &&
4487c478bd9Sstevel@tonic-gate 				    (flags&noexec) == 0)
4497c478bd9Sstevel@tonic-gate {
4507c478bd9Sstevel@tonic-gate 					i = execute(whptr(t)->dotre, XEC_NOSTOP, errorflg);
4517c478bd9Sstevel@tonic-gate 					if (breakcnt < 0)
4527c478bd9Sstevel@tonic-gate 						execbrk = (++breakcnt != 0);
4537c478bd9Sstevel@tonic-gate 				}
4547c478bd9Sstevel@tonic-gate 				if (breakcnt > 0)
4557c478bd9Sstevel@tonic-gate 						execbrk = (--breakcnt != 0);
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 				loopcnt--;
4587c478bd9Sstevel@tonic-gate 				exitval = i;
4597c478bd9Sstevel@tonic-gate 			}
4607c478bd9Sstevel@tonic-gate 			break;
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 		case TIF:
4637c478bd9Sstevel@tonic-gate 			if (execute(ifptr(t)->iftre, XEC_NOSTOP, 0) == 0)
4647c478bd9Sstevel@tonic-gate 				execute(ifptr(t)->thtre, xflags|XEC_NOSTOP, errorflg);
4657c478bd9Sstevel@tonic-gate 			else if (ifptr(t)->eltre)
4667c478bd9Sstevel@tonic-gate 				execute(ifptr(t)->eltre, xflags|XEC_NOSTOP, errorflg);
4677c478bd9Sstevel@tonic-gate 			else
4687c478bd9Sstevel@tonic-gate 				exitval = 0;	/* force zero exit for if-then-fi */
4697c478bd9Sstevel@tonic-gate 			break;
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 		case TSW:
4727c478bd9Sstevel@tonic-gate 			{
473965005c8Schin 				unsigned char	*r = mactrim(swptr(t)->swarg);
474965005c8Schin 				struct regnod *regp;
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 				regp = swptr(t)->swlst;
4777c478bd9Sstevel@tonic-gate 				while (regp)
4787c478bd9Sstevel@tonic-gate 				{
4797c478bd9Sstevel@tonic-gate 					struct argnod *rex = regp->regptr;
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 					while (rex)
4827c478bd9Sstevel@tonic-gate 					{
483965005c8Schin 						unsigned char	*s;
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 						if (gmatch(r, s = macro(rex->argval)) || (trim(s), eq(r, s)))
4867c478bd9Sstevel@tonic-gate 						{
4877c478bd9Sstevel@tonic-gate 							execute(regp->regcom, XEC_NOSTOP, errorflg);
4887c478bd9Sstevel@tonic-gate 							regp = 0;
4897c478bd9Sstevel@tonic-gate 							break;
4907c478bd9Sstevel@tonic-gate 						}
4917c478bd9Sstevel@tonic-gate 						else
4927c478bd9Sstevel@tonic-gate 							rex = rex->argnxt;
4937c478bd9Sstevel@tonic-gate 					}
4947c478bd9Sstevel@tonic-gate 					if (regp)
4957c478bd9Sstevel@tonic-gate 						regp = regp->regnxt;
4967c478bd9Sstevel@tonic-gate 				}
4977c478bd9Sstevel@tonic-gate 			}
4987c478bd9Sstevel@tonic-gate 			break;
4997c478bd9Sstevel@tonic-gate 		}
5007c478bd9Sstevel@tonic-gate 		exitset();
5017c478bd9Sstevel@tonic-gate 	}
5027c478bd9Sstevel@tonic-gate 	sigchk();
5037c478bd9Sstevel@tonic-gate 	tdystak(sav);
5047c478bd9Sstevel@tonic-gate 	flags |= eflag;
5057c478bd9Sstevel@tonic-gate 	return(exitval);
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate 
508965005c8Schin void
execexp(unsigned char * s,int f)509965005c8Schin execexp(unsigned char *s, int f)
5107c478bd9Sstevel@tonic-gate {
5117c478bd9Sstevel@tonic-gate 	struct fileblk	fb;
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 	push(&fb);
5147c478bd9Sstevel@tonic-gate 	if (s)
5157c478bd9Sstevel@tonic-gate 	{
5167c478bd9Sstevel@tonic-gate 		estabf(s);
5177c478bd9Sstevel@tonic-gate 		fb.feval = (unsigned char **)(f);
5187c478bd9Sstevel@tonic-gate 	}
5197c478bd9Sstevel@tonic-gate 	else if (f >= 0)
5207c478bd9Sstevel@tonic-gate 		initf(f);
5217c478bd9Sstevel@tonic-gate 	execute(cmd(NL, NLFLG | MTFLG), 0, (int)(flags & errflg));
5227c478bd9Sstevel@tonic-gate 	pop();
5237c478bd9Sstevel@tonic-gate }
5247c478bd9Sstevel@tonic-gate 
525965005c8Schin void
execprint(unsigned char ** com)526965005c8Schin execprint(unsigned char **com)
5277c478bd9Sstevel@tonic-gate {
528965005c8Schin 	int 	argn = 0;
5297c478bd9Sstevel@tonic-gate 	unsigned char	*s;
5307c478bd9Sstevel@tonic-gate 
53139e7390aSna195498 	prs(_gettext(execpmsg));
5327c478bd9Sstevel@tonic-gate 	while(com[argn] != ENDARGS)
5337c478bd9Sstevel@tonic-gate 	{
5347c478bd9Sstevel@tonic-gate 		s = com[argn++];
5357c478bd9Sstevel@tonic-gate 		write(output, s, length(s) - 1);
5367c478bd9Sstevel@tonic-gate 		blank();
5377c478bd9Sstevel@tonic-gate 	}
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 	newline();
5407c478bd9Sstevel@tonic-gate }
541