xref: /titanic_50/usr/src/cmd/sh/xec.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*7c478bd9Sstevel@tonic-gate 
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate /*
27*7c478bd9Sstevel@tonic-gate  * Copyright 1996,2002-2003 Sun Microsystems, Inc.  All rights reserved.
28*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
29*7c478bd9Sstevel@tonic-gate  */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
32*7c478bd9Sstevel@tonic-gate /*
33*7c478bd9Sstevel@tonic-gate  *
34*7c478bd9Sstevel@tonic-gate  * UNIX shell
35*7c478bd9Sstevel@tonic-gate  *
36*7c478bd9Sstevel@tonic-gate  */
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate #include	"defs.h"
40*7c478bd9Sstevel@tonic-gate #include	<errno.h>
41*7c478bd9Sstevel@tonic-gate #include	"sym.h"
42*7c478bd9Sstevel@tonic-gate #include	"hash.h"
43*7c478bd9Sstevel@tonic-gate #include	<sys/types.h>
44*7c478bd9Sstevel@tonic-gate #include	<sys/times.h>
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate pid_t parent;
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate /* ========	command execution	======== */
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate execute(argt, xflags, errorflg, pf1, pf2)
52*7c478bd9Sstevel@tonic-gate struct trenod	*argt;
53*7c478bd9Sstevel@tonic-gate int	*pf1, *pf2;
54*7c478bd9Sstevel@tonic-gate {
55*7c478bd9Sstevel@tonic-gate 	/*
56*7c478bd9Sstevel@tonic-gate 	 * `stakbot' is preserved by this routine
57*7c478bd9Sstevel@tonic-gate 	 */
58*7c478bd9Sstevel@tonic-gate 	register struct trenod	*t;
59*7c478bd9Sstevel@tonic-gate 	unsigned char		*sav = savstak();
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate 	sigchk();
62*7c478bd9Sstevel@tonic-gate 	if (!errorflg)
63*7c478bd9Sstevel@tonic-gate 		flags &= ~errflg;
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate 	if ((t = argt) && execbrk == 0) {
66*7c478bd9Sstevel@tonic-gate 		register int treeflgs;
67*7c478bd9Sstevel@tonic-gate 		register unsigned char **com;
68*7c478bd9Sstevel@tonic-gate 		int type;
69*7c478bd9Sstevel@tonic-gate 		short pos;
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate 		treeflgs = t->tretyp;
72*7c478bd9Sstevel@tonic-gate 		type = treeflgs & COMMSK;
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate 		switch (type)
75*7c478bd9Sstevel@tonic-gate 		{
76*7c478bd9Sstevel@tonic-gate 		case TFND:
77*7c478bd9Sstevel@tonic-gate 			{
78*7c478bd9Sstevel@tonic-gate 				struct fndnod	*f = (struct fndnod *)t;
79*7c478bd9Sstevel@tonic-gate 				struct namnod	*n = lookup(f->fndnam);
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate 				exitval = 0;
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate 				if (n->namflg & N_RDONLY)
84*7c478bd9Sstevel@tonic-gate 					failed(n->namid, wtfailed);
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate 				if (flags & rshflg && (n == &pathnod ||
87*7c478bd9Sstevel@tonic-gate 					eq(n->namid, "SHELL")))
88*7c478bd9Sstevel@tonic-gate 					failed(n->namid, restricted);
89*7c478bd9Sstevel@tonic-gate 				if (n->namflg & N_FUNCTN)
90*7c478bd9Sstevel@tonic-gate 					freefunc(n);
91*7c478bd9Sstevel@tonic-gate 				else
92*7c478bd9Sstevel@tonic-gate 				{
93*7c478bd9Sstevel@tonic-gate 					free(n->namval);
94*7c478bd9Sstevel@tonic-gate 					free(n->namenv);
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate 					n->namval = 0;
97*7c478bd9Sstevel@tonic-gate 					n->namflg &= ~(N_EXPORT | N_ENVCHG);
98*7c478bd9Sstevel@tonic-gate 				}
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 				if (funcnt)
101*7c478bd9Sstevel@tonic-gate 					f->fndval->tretyp++;
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate 				n->namenv = (unsigned char *)f->fndval;
104*7c478bd9Sstevel@tonic-gate 				attrib(n, N_FUNCTN);
105*7c478bd9Sstevel@tonic-gate 				hash_func(n->namid);
106*7c478bd9Sstevel@tonic-gate 				break;
107*7c478bd9Sstevel@tonic-gate 			}
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate 		case TCOM:
110*7c478bd9Sstevel@tonic-gate 			{
111*7c478bd9Sstevel@tonic-gate 				unsigned char	*a1, *name;
112*7c478bd9Sstevel@tonic-gate 				int	argn, internal;
113*7c478bd9Sstevel@tonic-gate 				struct argnod	*schain = gchain;
114*7c478bd9Sstevel@tonic-gate 				struct ionod	*io = t->treio;
115*7c478bd9Sstevel@tonic-gate 				short 	cmdhash;
116*7c478bd9Sstevel@tonic-gate 				short	comtype;
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 				exitval = 0;
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate 				gchain = 0;
121*7c478bd9Sstevel@tonic-gate 				argn = getarg(t);
122*7c478bd9Sstevel@tonic-gate 				com = scan(argn);
123*7c478bd9Sstevel@tonic-gate 				a1 = com[1];
124*7c478bd9Sstevel@tonic-gate 				gchain = schain;
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate 				if (argn != 0)
127*7c478bd9Sstevel@tonic-gate 					cmdhash = pathlook(com[0], 1, comptr(t)->comset);
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate 				if (argn == 0 || (comtype = hashtype(cmdhash)) == BUILTIN) {
130*7c478bd9Sstevel@tonic-gate 					setlist(comptr(t)->comset, 0);
131*7c478bd9Sstevel@tonic-gate 				}
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 				if (argn && (flags&noexec) == 0)
134*7c478bd9Sstevel@tonic-gate 				{
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 					/* print command if execpr */
137*7c478bd9Sstevel@tonic-gate 					if (flags & execpr)
138*7c478bd9Sstevel@tonic-gate 						execprint(com);
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate 					if (comtype == NOTFOUND)
141*7c478bd9Sstevel@tonic-gate 					{
142*7c478bd9Sstevel@tonic-gate 						pos = hashdata(cmdhash);
143*7c478bd9Sstevel@tonic-gate 						if (pos == 1)
144*7c478bd9Sstevel@tonic-gate 							failure(*com, notfound);
145*7c478bd9Sstevel@tonic-gate 						else if (pos == 2)
146*7c478bd9Sstevel@tonic-gate 							failure(*com, badexec);
147*7c478bd9Sstevel@tonic-gate 						else
148*7c478bd9Sstevel@tonic-gate 							failure(*com, badperm);
149*7c478bd9Sstevel@tonic-gate 						break;
150*7c478bd9Sstevel@tonic-gate 					}
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate 					else if (comtype == PATH_COMMAND)
153*7c478bd9Sstevel@tonic-gate 					{
154*7c478bd9Sstevel@tonic-gate 						pos = -1;
155*7c478bd9Sstevel@tonic-gate 					}
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 					else if (comtype & (COMMAND | REL_COMMAND))
158*7c478bd9Sstevel@tonic-gate 					{
159*7c478bd9Sstevel@tonic-gate 						pos = hashdata(cmdhash);
160*7c478bd9Sstevel@tonic-gate 					}
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 					else if (comtype == BUILTIN) {
163*7c478bd9Sstevel@tonic-gate 						builtin(hashdata(cmdhash),argn,com,t);
164*7c478bd9Sstevel@tonic-gate 						freejobs();
165*7c478bd9Sstevel@tonic-gate 						break;
166*7c478bd9Sstevel@tonic-gate 					}
167*7c478bd9Sstevel@tonic-gate 					else if (comtype == FUNCTION)
168*7c478bd9Sstevel@tonic-gate 					{
169*7c478bd9Sstevel@tonic-gate 						struct dolnod *olddolh;
170*7c478bd9Sstevel@tonic-gate 						struct namnod *n, *opt;
171*7c478bd9Sstevel@tonic-gate 						short index;
172*7c478bd9Sstevel@tonic-gate 						unsigned char **olddolv = dolv;
173*7c478bd9Sstevel@tonic-gate 						int olddolc = dolc;
174*7c478bd9Sstevel@tonic-gate 						n = findnam(com[0]);
175*7c478bd9Sstevel@tonic-gate 					/* save current positional parameters */
176*7c478bd9Sstevel@tonic-gate 						olddolh = (struct dolnod *)savargs(funcnt);
177*7c478bd9Sstevel@tonic-gate 						funcnt++;
178*7c478bd9Sstevel@tonic-gate 						index = initio(io, 1);
179*7c478bd9Sstevel@tonic-gate 						setargs(com);
180*7c478bd9Sstevel@tonic-gate 						execute((struct trenod *)(n->namenv), xflags, errorflg, pf1, pf2);
181*7c478bd9Sstevel@tonic-gate 						execbrk = 0;
182*7c478bd9Sstevel@tonic-gate 						restore(index);
183*7c478bd9Sstevel@tonic-gate 						(void) restorargs(olddolh, funcnt);
184*7c478bd9Sstevel@tonic-gate 						dolv = olddolv;
185*7c478bd9Sstevel@tonic-gate 						dolc = olddolc;
186*7c478bd9Sstevel@tonic-gate 						funcnt--;
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate 						break;
189*7c478bd9Sstevel@tonic-gate 					}
190*7c478bd9Sstevel@tonic-gate 				}
191*7c478bd9Sstevel@tonic-gate 				else if (t->treio == 0)
192*7c478bd9Sstevel@tonic-gate 				{
193*7c478bd9Sstevel@tonic-gate 					chktrap();
194*7c478bd9Sstevel@tonic-gate 					break;
195*7c478bd9Sstevel@tonic-gate 				}
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate 			}
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 		case TFORK:
200*7c478bd9Sstevel@tonic-gate 		{
201*7c478bd9Sstevel@tonic-gate 			int monitor = 0;
202*7c478bd9Sstevel@tonic-gate 			int linked = 0;
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate 			exitval = 0;
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate 			if (!(xflags & XEC_EXECED) || treeflgs&(FPOU|FAMP))
207*7c478bd9Sstevel@tonic-gate 			{
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate 				int forkcnt = 1;
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate 				if (!(treeflgs&FPOU))
212*7c478bd9Sstevel@tonic-gate 				{
213*7c478bd9Sstevel@tonic-gate 					monitor = (!(xflags & XEC_NOSTOP)
214*7c478bd9Sstevel@tonic-gate 					  && (flags&(monitorflg|jcflg|jcoff))
215*7c478bd9Sstevel@tonic-gate 					  == (monitorflg|jcflg));
216*7c478bd9Sstevel@tonic-gate 					if (monitor) {
217*7c478bd9Sstevel@tonic-gate 						int savefd;
218*7c478bd9Sstevel@tonic-gate 						unsigned char *savebot;
219*7c478bd9Sstevel@tonic-gate 						savefd = setb(-1);
220*7c478bd9Sstevel@tonic-gate 						savebot = stakbot;
221*7c478bd9Sstevel@tonic-gate 						prcmd(t);
222*7c478bd9Sstevel@tonic-gate 						(void)setb(savefd);
223*7c478bd9Sstevel@tonic-gate 						allocjob(savebot, cwdget(), monitor);
224*7c478bd9Sstevel@tonic-gate 					} else
225*7c478bd9Sstevel@tonic-gate 						allocjob("", "", 0);
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 				}
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate 				if (treeflgs & (FPOU|FAMP)) {
230*7c478bd9Sstevel@tonic-gate 					link_iodocs(iotemp);
231*7c478bd9Sstevel@tonic-gate 					linked = 1;
232*7c478bd9Sstevel@tonic-gate 				}
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate 				while ((parent = fork()) == -1)
235*7c478bd9Sstevel@tonic-gate 				{
236*7c478bd9Sstevel@tonic-gate 				/*
237*7c478bd9Sstevel@tonic-gate 				 * FORKLIM is the max period between forks -
238*7c478bd9Sstevel@tonic-gate 				 * power of 2 usually.	Currently shell tries
239*7c478bd9Sstevel@tonic-gate 				 * after 2,4,8,16, and 32 seconds and then quits
240*7c478bd9Sstevel@tonic-gate 				 */
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 				if ((forkcnt = (forkcnt * 2)) > FORKLIM)
243*7c478bd9Sstevel@tonic-gate 				{
244*7c478bd9Sstevel@tonic-gate 					switch (errno)
245*7c478bd9Sstevel@tonic-gate 					{
246*7c478bd9Sstevel@tonic-gate 					case ENOMEM:
247*7c478bd9Sstevel@tonic-gate 						deallocjob();
248*7c478bd9Sstevel@tonic-gate 						error(noswap);
249*7c478bd9Sstevel@tonic-gate 						break;
250*7c478bd9Sstevel@tonic-gate 					default:
251*7c478bd9Sstevel@tonic-gate 						deallocjob();
252*7c478bd9Sstevel@tonic-gate 						error(nofork);
253*7c478bd9Sstevel@tonic-gate 						break;
254*7c478bd9Sstevel@tonic-gate 					}
255*7c478bd9Sstevel@tonic-gate 				} else if (errno == EPERM) {
256*7c478bd9Sstevel@tonic-gate 					deallocjob();
257*7c478bd9Sstevel@tonic-gate 					error(eacces);
258*7c478bd9Sstevel@tonic-gate 					break;
259*7c478bd9Sstevel@tonic-gate 				}
260*7c478bd9Sstevel@tonic-gate 				sigchk();
261*7c478bd9Sstevel@tonic-gate 				sleep(forkcnt);
262*7c478bd9Sstevel@tonic-gate 				}
263*7c478bd9Sstevel@tonic-gate 
264*7c478bd9Sstevel@tonic-gate 				if (parent) {
265*7c478bd9Sstevel@tonic-gate 					if (monitor)
266*7c478bd9Sstevel@tonic-gate 						setpgid(parent, 0);
267*7c478bd9Sstevel@tonic-gate 					if (treeflgs & FPIN)
268*7c478bd9Sstevel@tonic-gate 						closepipe(pf1);
269*7c478bd9Sstevel@tonic-gate 					if (!(treeflgs&FPOU)) {
270*7c478bd9Sstevel@tonic-gate 						postjob(parent,!(treeflgs&FAMP));
271*7c478bd9Sstevel@tonic-gate 						freejobs();
272*7c478bd9Sstevel@tonic-gate 					}
273*7c478bd9Sstevel@tonic-gate 					chktrap();
274*7c478bd9Sstevel@tonic-gate 					break;
275*7c478bd9Sstevel@tonic-gate 				}
276*7c478bd9Sstevel@tonic-gate 				mypid = getpid();
277*7c478bd9Sstevel@tonic-gate 			}
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate 			/*
280*7c478bd9Sstevel@tonic-gate 			 * Forked process:  assume it is not a subshell for
281*7c478bd9Sstevel@tonic-gate 			 * now.  If it is, the presence of a left parenthesis
282*7c478bd9Sstevel@tonic-gate 			 * will trigger the jcoff flag to be turned off.
283*7c478bd9Sstevel@tonic-gate 			 * When jcoff is turned on, monitoring is not going on
284*7c478bd9Sstevel@tonic-gate 			 * and waitpid will not look for WUNTRACED.
285*7c478bd9Sstevel@tonic-gate 			 */
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate 			flags |= (forked|jcoff);
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate 			fiotemp  = 0;
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate 			if (linked == 1) {
292*7c478bd9Sstevel@tonic-gate 				swap_iodoc_nm(iotemp);
293*7c478bd9Sstevel@tonic-gate 				xflags |= XEC_LINKED;
294*7c478bd9Sstevel@tonic-gate 			} else if (!(xflags & XEC_LINKED))
295*7c478bd9Sstevel@tonic-gate 				iotemp = 0;
296*7c478bd9Sstevel@tonic-gate #ifdef ACCT
297*7c478bd9Sstevel@tonic-gate 			suspacct();
298*7c478bd9Sstevel@tonic-gate #endif
299*7c478bd9Sstevel@tonic-gate 			settmp();
300*7c478bd9Sstevel@tonic-gate 			oldsigs();
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 			if (!(treeflgs & FPOU))
303*7c478bd9Sstevel@tonic-gate 				makejob(monitor, !(treeflgs & FAMP));
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate 			/*
306*7c478bd9Sstevel@tonic-gate 			 * pipe in or out
307*7c478bd9Sstevel@tonic-gate 			 */
308*7c478bd9Sstevel@tonic-gate 			if (treeflgs & FPIN)
309*7c478bd9Sstevel@tonic-gate 			{
310*7c478bd9Sstevel@tonic-gate 				renamef(pf1[INPIPE], 0);
311*7c478bd9Sstevel@tonic-gate 				close(pf1[OTPIPE]);
312*7c478bd9Sstevel@tonic-gate 			}
313*7c478bd9Sstevel@tonic-gate 
314*7c478bd9Sstevel@tonic-gate 			if (treeflgs & FPOU)
315*7c478bd9Sstevel@tonic-gate 			{
316*7c478bd9Sstevel@tonic-gate 				close(pf2[INPIPE]);
317*7c478bd9Sstevel@tonic-gate 				renamef(pf2[OTPIPE], 1);
318*7c478bd9Sstevel@tonic-gate 			}
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate 			/*
321*7c478bd9Sstevel@tonic-gate 			 * io redirection
322*7c478bd9Sstevel@tonic-gate 			 */
323*7c478bd9Sstevel@tonic-gate 			initio(t->treio, 0);
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate 			if (type == TFORK)
326*7c478bd9Sstevel@tonic-gate 				execute(forkptr(t)->forktre, xflags | XEC_EXECED, errorflg);
327*7c478bd9Sstevel@tonic-gate 			else if (com[0] != ENDARGS)
328*7c478bd9Sstevel@tonic-gate 			{
329*7c478bd9Sstevel@tonic-gate 				eflag = 0;
330*7c478bd9Sstevel@tonic-gate 				setlist(comptr(t)->comset, N_EXPORT);
331*7c478bd9Sstevel@tonic-gate 				rmtemp(0);
332*7c478bd9Sstevel@tonic-gate 				clearjobs();
333*7c478bd9Sstevel@tonic-gate 				execa(com, pos);
334*7c478bd9Sstevel@tonic-gate 			}
335*7c478bd9Sstevel@tonic-gate 			done(0);
336*7c478bd9Sstevel@tonic-gate 		}
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate 		case TPAR:
339*7c478bd9Sstevel@tonic-gate 			/* Forked process is subshell:  may want job control */
340*7c478bd9Sstevel@tonic-gate 			flags &= ~jcoff;
341*7c478bd9Sstevel@tonic-gate 			clearjobs();
342*7c478bd9Sstevel@tonic-gate 			execute(parptr(t)->partre, xflags, errorflg);
343*7c478bd9Sstevel@tonic-gate 			done(0);
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate 		case TFIL:
346*7c478bd9Sstevel@tonic-gate 			{
347*7c478bd9Sstevel@tonic-gate 				int pv[2];
348*7c478bd9Sstevel@tonic-gate 
349*7c478bd9Sstevel@tonic-gate 				chkpipe(pv);
350*7c478bd9Sstevel@tonic-gate 				if (execute(lstptr(t)->lstlef, xflags & XEC_NOSTOP, errorflg, pf1, pv) == 0)
351*7c478bd9Sstevel@tonic-gate 					execute(lstptr(t)->lstrit, xflags, errorflg, pv, pf2);
352*7c478bd9Sstevel@tonic-gate 				else
353*7c478bd9Sstevel@tonic-gate 					closepipe(pv);
354*7c478bd9Sstevel@tonic-gate 			}
355*7c478bd9Sstevel@tonic-gate 			break;
356*7c478bd9Sstevel@tonic-gate 
357*7c478bd9Sstevel@tonic-gate 		case TLST:
358*7c478bd9Sstevel@tonic-gate 			execute(lstptr(t)->lstlef, xflags&XEC_NOSTOP, errorflg);
359*7c478bd9Sstevel@tonic-gate 			/* Update errorflg if set -e is invoked in the sub-sh*/
360*7c478bd9Sstevel@tonic-gate 			execute(lstptr(t)->lstrit, xflags, (errorflg | (eflag & errflg)));
361*7c478bd9Sstevel@tonic-gate 			break;
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate 		case TAND:
364*7c478bd9Sstevel@tonic-gate 		case TORF:
365*7c478bd9Sstevel@tonic-gate 		{
366*7c478bd9Sstevel@tonic-gate 			register xval;
367*7c478bd9Sstevel@tonic-gate 			xval = execute(lstptr(t)->lstlef, XEC_NOSTOP, 0);
368*7c478bd9Sstevel@tonic-gate 			if ((xval == 0) == (type == TAND))
369*7c478bd9Sstevel@tonic-gate 				execute(lstptr(t)->lstrit, xflags|XEC_NOSTOP, errorflg);
370*7c478bd9Sstevel@tonic-gate 			break;
371*7c478bd9Sstevel@tonic-gate 		}
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate 		case TFOR:
374*7c478bd9Sstevel@tonic-gate 			{
375*7c478bd9Sstevel@tonic-gate 				struct namnod *n = lookup(forptr(t)->fornam);
376*7c478bd9Sstevel@tonic-gate 				unsigned char	**args;
377*7c478bd9Sstevel@tonic-gate 				struct dolnod *argsav = 0;
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate 				if (forptr(t)->forlst == 0)
380*7c478bd9Sstevel@tonic-gate 				{
381*7c478bd9Sstevel@tonic-gate 					args = dolv + 1;
382*7c478bd9Sstevel@tonic-gate 					argsav = useargs();
383*7c478bd9Sstevel@tonic-gate 				}
384*7c478bd9Sstevel@tonic-gate 				else
385*7c478bd9Sstevel@tonic-gate 				{
386*7c478bd9Sstevel@tonic-gate 					struct argnod *schain = gchain;
387*7c478bd9Sstevel@tonic-gate 
388*7c478bd9Sstevel@tonic-gate 					gchain = 0;
389*7c478bd9Sstevel@tonic-gate 					args = scan(getarg(forptr(t)->forlst));
390*7c478bd9Sstevel@tonic-gate 					gchain = schain;
391*7c478bd9Sstevel@tonic-gate 				}
392*7c478bd9Sstevel@tonic-gate 				loopcnt++;
393*7c478bd9Sstevel@tonic-gate 				while (*args != ENDARGS && execbrk == 0)
394*7c478bd9Sstevel@tonic-gate 				{
395*7c478bd9Sstevel@tonic-gate 					assign(n, *args++);
396*7c478bd9Sstevel@tonic-gate 					execute(forptr(t)->fortre, XEC_NOSTOP, errorflg);
397*7c478bd9Sstevel@tonic-gate 					if (breakcnt < 0)
398*7c478bd9Sstevel@tonic-gate 						execbrk = (++breakcnt != 0);
399*7c478bd9Sstevel@tonic-gate 				}
400*7c478bd9Sstevel@tonic-gate 				if (breakcnt > 0)
401*7c478bd9Sstevel@tonic-gate 						execbrk = (--breakcnt != 0);
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate 				loopcnt--;
404*7c478bd9Sstevel@tonic-gate 				if(argsav)
405*7c478bd9Sstevel@tonic-gate 					argfor = (struct dolnod *)freeargs(argsav);
406*7c478bd9Sstevel@tonic-gate 			}
407*7c478bd9Sstevel@tonic-gate 			break;
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate 		case TWH:
410*7c478bd9Sstevel@tonic-gate 		case TUN:
411*7c478bd9Sstevel@tonic-gate 			{
412*7c478bd9Sstevel@tonic-gate 				int	i = 0;
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate 				loopcnt++;
415*7c478bd9Sstevel@tonic-gate 				while (execbrk == 0 && (execute(whptr(t)->whtre,
416*7c478bd9Sstevel@tonic-gate 				    XEC_NOSTOP, 0) == 0) == (type == TWH) &&
417*7c478bd9Sstevel@tonic-gate 				    (flags&noexec) == 0)
418*7c478bd9Sstevel@tonic-gate {
419*7c478bd9Sstevel@tonic-gate 					i = execute(whptr(t)->dotre, XEC_NOSTOP, errorflg);
420*7c478bd9Sstevel@tonic-gate 					if (breakcnt < 0)
421*7c478bd9Sstevel@tonic-gate 						execbrk = (++breakcnt != 0);
422*7c478bd9Sstevel@tonic-gate 				}
423*7c478bd9Sstevel@tonic-gate 				if (breakcnt > 0)
424*7c478bd9Sstevel@tonic-gate 						execbrk = (--breakcnt != 0);
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate 				loopcnt--;
427*7c478bd9Sstevel@tonic-gate 				exitval = i;
428*7c478bd9Sstevel@tonic-gate 			}
429*7c478bd9Sstevel@tonic-gate 			break;
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 		case TIF:
432*7c478bd9Sstevel@tonic-gate 			if (execute(ifptr(t)->iftre, XEC_NOSTOP, 0) == 0)
433*7c478bd9Sstevel@tonic-gate 				execute(ifptr(t)->thtre, xflags|XEC_NOSTOP, errorflg);
434*7c478bd9Sstevel@tonic-gate 			else if (ifptr(t)->eltre)
435*7c478bd9Sstevel@tonic-gate 				execute(ifptr(t)->eltre, xflags|XEC_NOSTOP, errorflg);
436*7c478bd9Sstevel@tonic-gate 			else
437*7c478bd9Sstevel@tonic-gate 				exitval = 0;	/* force zero exit for if-then-fi */
438*7c478bd9Sstevel@tonic-gate 			break;
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate 		case TSW:
441*7c478bd9Sstevel@tonic-gate 			{
442*7c478bd9Sstevel@tonic-gate 				register unsigned char	*r = mactrim(swptr(t)->swarg);
443*7c478bd9Sstevel@tonic-gate 				register struct regnod *regp;
444*7c478bd9Sstevel@tonic-gate 
445*7c478bd9Sstevel@tonic-gate 				regp = swptr(t)->swlst;
446*7c478bd9Sstevel@tonic-gate 				while (regp)
447*7c478bd9Sstevel@tonic-gate 				{
448*7c478bd9Sstevel@tonic-gate 					struct argnod *rex = regp->regptr;
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate 					while (rex)
451*7c478bd9Sstevel@tonic-gate 					{
452*7c478bd9Sstevel@tonic-gate 						register unsigned char	*s;
453*7c478bd9Sstevel@tonic-gate 
454*7c478bd9Sstevel@tonic-gate 						if (gmatch(r, s = macro(rex->argval)) || (trim(s), eq(r, s)))
455*7c478bd9Sstevel@tonic-gate 						{
456*7c478bd9Sstevel@tonic-gate 							execute(regp->regcom, XEC_NOSTOP, errorflg);
457*7c478bd9Sstevel@tonic-gate 							regp = 0;
458*7c478bd9Sstevel@tonic-gate 							break;
459*7c478bd9Sstevel@tonic-gate 						}
460*7c478bd9Sstevel@tonic-gate 						else
461*7c478bd9Sstevel@tonic-gate 							rex = rex->argnxt;
462*7c478bd9Sstevel@tonic-gate 					}
463*7c478bd9Sstevel@tonic-gate 					if (regp)
464*7c478bd9Sstevel@tonic-gate 						regp = regp->regnxt;
465*7c478bd9Sstevel@tonic-gate 				}
466*7c478bd9Sstevel@tonic-gate 			}
467*7c478bd9Sstevel@tonic-gate 			break;
468*7c478bd9Sstevel@tonic-gate 		}
469*7c478bd9Sstevel@tonic-gate 		exitset();
470*7c478bd9Sstevel@tonic-gate 	}
471*7c478bd9Sstevel@tonic-gate 	sigchk();
472*7c478bd9Sstevel@tonic-gate 	tdystak(sav);
473*7c478bd9Sstevel@tonic-gate 	flags |= eflag;
474*7c478bd9Sstevel@tonic-gate 	return(exitval);
475*7c478bd9Sstevel@tonic-gate }
476*7c478bd9Sstevel@tonic-gate 
477*7c478bd9Sstevel@tonic-gate execexp(s, f)
478*7c478bd9Sstevel@tonic-gate unsigned char	*s;
479*7c478bd9Sstevel@tonic-gate int	f;
480*7c478bd9Sstevel@tonic-gate {
481*7c478bd9Sstevel@tonic-gate 	struct fileblk	fb;
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate 	push(&fb);
484*7c478bd9Sstevel@tonic-gate 	if (s)
485*7c478bd9Sstevel@tonic-gate 	{
486*7c478bd9Sstevel@tonic-gate 		estabf(s);
487*7c478bd9Sstevel@tonic-gate 		fb.feval = (unsigned char **)(f);
488*7c478bd9Sstevel@tonic-gate 	}
489*7c478bd9Sstevel@tonic-gate 	else if (f >= 0)
490*7c478bd9Sstevel@tonic-gate 		initf(f);
491*7c478bd9Sstevel@tonic-gate 	execute(cmd(NL, NLFLG | MTFLG), 0, (int)(flags & errflg));
492*7c478bd9Sstevel@tonic-gate 	pop();
493*7c478bd9Sstevel@tonic-gate }
494*7c478bd9Sstevel@tonic-gate 
495*7c478bd9Sstevel@tonic-gate execprint(com)
496*7c478bd9Sstevel@tonic-gate 	unsigned char **com;
497*7c478bd9Sstevel@tonic-gate {
498*7c478bd9Sstevel@tonic-gate 	register int 	argn = 0;
499*7c478bd9Sstevel@tonic-gate 	unsigned char	*s;
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate 	prs(execpmsg);
502*7c478bd9Sstevel@tonic-gate 	while(com[argn] != ENDARGS)
503*7c478bd9Sstevel@tonic-gate 	{
504*7c478bd9Sstevel@tonic-gate 		s = com[argn++];
505*7c478bd9Sstevel@tonic-gate 		write(output, s, length(s) - 1);
506*7c478bd9Sstevel@tonic-gate 		blank();
507*7c478bd9Sstevel@tonic-gate 	}
508*7c478bd9Sstevel@tonic-gate 
509*7c478bd9Sstevel@tonic-gate 	newline();
510*7c478bd9Sstevel@tonic-gate }
511