xref: /titanic_50/usr/src/cmd/csh/sh.sem.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
7*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
8*7c478bd9Sstevel@tonic-gate 
9*7c478bd9Sstevel@tonic-gate /*
10*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
11*7c478bd9Sstevel@tonic-gate  * All rights reserved. The Berkeley Software License Agreement
12*7c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
13*7c478bd9Sstevel@tonic-gate  */
14*7c478bd9Sstevel@tonic-gate 
15*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
16*7c478bd9Sstevel@tonic-gate 
17*7c478bd9Sstevel@tonic-gate #include <unistd.h>
18*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
19*7c478bd9Sstevel@tonic-gate #include "sh.h"
20*7c478bd9Sstevel@tonic-gate #include "sh.proc.h"
21*7c478bd9Sstevel@tonic-gate #include "sh.tconst.h"
22*7c478bd9Sstevel@tonic-gate 
23*7c478bd9Sstevel@tonic-gate /*
24*7c478bd9Sstevel@tonic-gate  * C shell
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*
28*7c478bd9Sstevel@tonic-gate  * Return true if there is a back-quote (`) anywhere in the argument list.
29*7c478bd9Sstevel@tonic-gate  * Its presence would cause glob() to be invoked in the child process
30*7c478bd9Sstevel@tonic-gate  * and this would cause chaos if the child is created with vfork().
31*7c478bd9Sstevel@tonic-gate  */
32*7c478bd9Sstevel@tonic-gate static bool
33*7c478bd9Sstevel@tonic-gate AnyBquote(struct command *t)
34*7c478bd9Sstevel@tonic-gate {
35*7c478bd9Sstevel@tonic-gate 	tchar **pp;
36*7c478bd9Sstevel@tonic-gate 	tchar *p;
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate 	if (noexec)
39*7c478bd9Sstevel@tonic-gate 		return (0);
40*7c478bd9Sstevel@tonic-gate 	for (pp = t->t_dcom; p = *pp++;) {
41*7c478bd9Sstevel@tonic-gate 		if (any('`', p))
42*7c478bd9Sstevel@tonic-gate 			return (1);
43*7c478bd9Sstevel@tonic-gate 	}
44*7c478bd9Sstevel@tonic-gate 	return (0);
45*7c478bd9Sstevel@tonic-gate }
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate /*VARARGS 1*/
48*7c478bd9Sstevel@tonic-gate execute(t, wanttty, pipein, pipeout)
49*7c478bd9Sstevel@tonic-gate 	register struct command *t;
50*7c478bd9Sstevel@tonic-gate 	int wanttty, *pipein, *pipeout;
51*7c478bd9Sstevel@tonic-gate {
52*7c478bd9Sstevel@tonic-gate 	bool forked = 0;
53*7c478bd9Sstevel@tonic-gate 	struct biltins *bifunc;
54*7c478bd9Sstevel@tonic-gate 	int pid = 0;
55*7c478bd9Sstevel@tonic-gate 	int pv[2];
56*7c478bd9Sstevel@tonic-gate 	extern int globcnt;
57*7c478bd9Sstevel@tonic-gate #ifdef TRACE
58*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- execute()\n");
59*7c478bd9Sstevel@tonic-gate #endif
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate 	if (t == 0)
62*7c478bd9Sstevel@tonic-gate 		return;
63*7c478bd9Sstevel@tonic-gate 	if ((t->t_dflg & FAND) && wanttty > 0)
64*7c478bd9Sstevel@tonic-gate 		wanttty = 0;
65*7c478bd9Sstevel@tonic-gate 	switch (t->t_dtyp) {
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate 	case TCOM:
68*7c478bd9Sstevel@tonic-gate 		if (t->t_dcom[0][0] == (tchar)S_TOPBIT[0])
69*7c478bd9Sstevel@tonic-gate 			(void) strcpy_(t->t_dcom[0], t->t_dcom[0] + 1);
70*7c478bd9Sstevel@tonic-gate 		if ((t->t_dflg & FREDO) == 0)
71*7c478bd9Sstevel@tonic-gate 			Dfix(t);		/* $ " ' \ */
72*7c478bd9Sstevel@tonic-gate 		if (t->t_dcom[0] == 0)
73*7c478bd9Sstevel@tonic-gate 			return;
74*7c478bd9Sstevel@tonic-gate 		/* fall into... */
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate 	case TPAR:
77*7c478bd9Sstevel@tonic-gate 		if (t->t_dflg & FPOU)
78*7c478bd9Sstevel@tonic-gate 			mypipe(pipeout);
79*7c478bd9Sstevel@tonic-gate 		/*
80*7c478bd9Sstevel@tonic-gate 		 * Must do << early so parent will know
81*7c478bd9Sstevel@tonic-gate 		 * where input pointer should be.
82*7c478bd9Sstevel@tonic-gate 		 * If noexec then this is all we do.
83*7c478bd9Sstevel@tonic-gate 		 */
84*7c478bd9Sstevel@tonic-gate 		if (t->t_dflg & FHERE) {
85*7c478bd9Sstevel@tonic-gate 			(void) close(0);
86*7c478bd9Sstevel@tonic-gate 			unsetfd(0);
87*7c478bd9Sstevel@tonic-gate 			heredoc(t->t_dlef);
88*7c478bd9Sstevel@tonic-gate 			if (noexec) {
89*7c478bd9Sstevel@tonic-gate 				(void) close(0);
90*7c478bd9Sstevel@tonic-gate 				unsetfd(0);
91*7c478bd9Sstevel@tonic-gate 			}
92*7c478bd9Sstevel@tonic-gate 		}
93*7c478bd9Sstevel@tonic-gate 		if (noexec)
94*7c478bd9Sstevel@tonic-gate 			break;
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate 		set(S_status, S_0);
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate 		/*
99*7c478bd9Sstevel@tonic-gate 		 * This mess is the necessary kludge to handle the prefix
100*7c478bd9Sstevel@tonic-gate 		 * builtins: nice, nohup, time.  These commands can also
101*7c478bd9Sstevel@tonic-gate 		 * be used by themselves, and this is not handled here.
102*7c478bd9Sstevel@tonic-gate 		 * This will also work when loops are parsed.
103*7c478bd9Sstevel@tonic-gate 		 */
104*7c478bd9Sstevel@tonic-gate 		while (t->t_dtyp == TCOM)
105*7c478bd9Sstevel@tonic-gate 			if (eq(t->t_dcom[0], S_nice /*"nice"*/))
106*7c478bd9Sstevel@tonic-gate 				if (t->t_dcom[1])
107*7c478bd9Sstevel@tonic-gate 					/*if (any(t->t_dcom[1][0], "+-"))*/
108*7c478bd9Sstevel@tonic-gate 					if (t->t_dcom[1][0] == '+' ||
109*7c478bd9Sstevel@tonic-gate 					    t->t_dcom[1][0] == '-')
110*7c478bd9Sstevel@tonic-gate 						if (t->t_dcom[2]) {
111*7c478bd9Sstevel@tonic-gate 							setname(S_nice /*"nice"*/);
112*7c478bd9Sstevel@tonic-gate 							t->t_nice = getn(t->t_dcom[1]);
113*7c478bd9Sstevel@tonic-gate 							lshift(t->t_dcom, 2);
114*7c478bd9Sstevel@tonic-gate 							t->t_dflg |= FNICE;
115*7c478bd9Sstevel@tonic-gate 						} else
116*7c478bd9Sstevel@tonic-gate 							break;
117*7c478bd9Sstevel@tonic-gate 					else {
118*7c478bd9Sstevel@tonic-gate 						t->t_nice = 4;
119*7c478bd9Sstevel@tonic-gate 						lshift(t->t_dcom, 1);
120*7c478bd9Sstevel@tonic-gate 						t->t_dflg |= FNICE;
121*7c478bd9Sstevel@tonic-gate 					}
122*7c478bd9Sstevel@tonic-gate 				else
123*7c478bd9Sstevel@tonic-gate 					break;
124*7c478bd9Sstevel@tonic-gate 			else if (eq(t->t_dcom[0], S_nohup /*"nohup"*/))
125*7c478bd9Sstevel@tonic-gate 				if (t->t_dcom[1]) {
126*7c478bd9Sstevel@tonic-gate 					t->t_dflg |= FNOHUP;
127*7c478bd9Sstevel@tonic-gate 					lshift(t->t_dcom, 1);
128*7c478bd9Sstevel@tonic-gate 				} else
129*7c478bd9Sstevel@tonic-gate 					break;
130*7c478bd9Sstevel@tonic-gate 			else if (eq(t->t_dcom[0], S_time /*"time"*/))
131*7c478bd9Sstevel@tonic-gate 				if (t->t_dcom[1]) {
132*7c478bd9Sstevel@tonic-gate 					t->t_dflg |= FTIME;
133*7c478bd9Sstevel@tonic-gate 					lshift(t->t_dcom, 1);
134*7c478bd9Sstevel@tonic-gate 				} else
135*7c478bd9Sstevel@tonic-gate 					break;
136*7c478bd9Sstevel@tonic-gate 			else
137*7c478bd9Sstevel@tonic-gate 				break;
138*7c478bd9Sstevel@tonic-gate 		/*
139*7c478bd9Sstevel@tonic-gate 		 * Check if we have a builtin function and remember which one.
140*7c478bd9Sstevel@tonic-gate 		 */
141*7c478bd9Sstevel@tonic-gate 		bifunc = t->t_dtyp == TCOM ? isbfunc(t) : (struct biltins *) 0;
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate 		/*
144*7c478bd9Sstevel@tonic-gate 		 * We fork only if we are timed, or are not the end of
145*7c478bd9Sstevel@tonic-gate 		 * a parenthesized list and not a simple builtin function.
146*7c478bd9Sstevel@tonic-gate 		 * Simple meaning one that is not pipedout, niced, nohupped,
147*7c478bd9Sstevel@tonic-gate 		 * or &'d.
148*7c478bd9Sstevel@tonic-gate 		 * It would be nice(?) to not fork in some of these cases.
149*7c478bd9Sstevel@tonic-gate 		 */
150*7c478bd9Sstevel@tonic-gate 		if (((t->t_dflg & FTIME) || (t->t_dflg & FPAR) == 0 &&
151*7c478bd9Sstevel@tonic-gate 		     (!bifunc || t->t_dflg & (FPOU|FAND|FNICE|FNOHUP))))
152*7c478bd9Sstevel@tonic-gate #ifdef VFORK
153*7c478bd9Sstevel@tonic-gate 		    if (t->t_dtyp == TPAR || t->t_dflg&(FREDO|FAND) ||
154*7c478bd9Sstevel@tonic-gate 			bifunc || AnyBquote(t))
155*7c478bd9Sstevel@tonic-gate #endif
156*7c478bd9Sstevel@tonic-gate 			{ forked++; pid = pfork(t, wanttty); }
157*7c478bd9Sstevel@tonic-gate #ifdef VFORK
158*7c478bd9Sstevel@tonic-gate 		    else {
159*7c478bd9Sstevel@tonic-gate 			void vffree();
160*7c478bd9Sstevel@tonic-gate 			struct sv {
161*7c478bd9Sstevel@tonic-gate 				int mask, child, setintr, haderr, didfds;
162*7c478bd9Sstevel@tonic-gate 				int SHIN, SHOUT, SHDIAG, OLDSTD, tpgrp;
163*7c478bd9Sstevel@tonic-gate 				struct sigvec sigv;
164*7c478bd9Sstevel@tonic-gate 			} sv;
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 			/*
167*7c478bd9Sstevel@tonic-gate 			 * Prepare for the vfork by saving everything
168*7c478bd9Sstevel@tonic-gate 			 * that the child corrupts before it exec's.
169*7c478bd9Sstevel@tonic-gate 			 * Note that in some signal implementations
170*7c478bd9Sstevel@tonic-gate 			 * which keep the signal info in user space
171*7c478bd9Sstevel@tonic-gate 			 * (e.g. Sun's) it will also be necessary to
172*7c478bd9Sstevel@tonic-gate  			 * save and restore the current sigvec's for
173*7c478bd9Sstevel@tonic-gate 			 * the signals the child touches before it
174*7c478bd9Sstevel@tonic-gate 			 * exec's.
175*7c478bd9Sstevel@tonic-gate 			 */
176*7c478bd9Sstevel@tonic-gate 			sv.mask = sigblock(sigmask(SIGCHLD));
177*7c478bd9Sstevel@tonic-gate 			sv.child = child; sv.setintr = setintr;
178*7c478bd9Sstevel@tonic-gate 			sv.haderr = haderr; sv.didfds = didfds;
179*7c478bd9Sstevel@tonic-gate 			sv.SHIN = SHIN; sv.SHOUT = SHOUT;
180*7c478bd9Sstevel@tonic-gate 			sv.SHDIAG = SHDIAG; sv.OLDSTD = OLDSTD;
181*7c478bd9Sstevel@tonic-gate 			sv.tpgrp = tpgrp;
182*7c478bd9Sstevel@tonic-gate 			Vsav = Vdp = 0; Vav = 0;
183*7c478bd9Sstevel@tonic-gate 			(void) sigvec(SIGINT, (struct sigvec *)0, &sv.sigv);
184*7c478bd9Sstevel@tonic-gate 			pid = vfork();
185*7c478bd9Sstevel@tonic-gate 			if (pid < 0) {
186*7c478bd9Sstevel@tonic-gate 				(void) sigsetmask(sv.mask);
187*7c478bd9Sstevel@tonic-gate 				error("Vfork failed");
188*7c478bd9Sstevel@tonic-gate 			}
189*7c478bd9Sstevel@tonic-gate 			forked++;
190*7c478bd9Sstevel@tonic-gate 			if (pid) {	/* parent */
191*7c478bd9Sstevel@tonic-gate 				int ppid;
192*7c478bd9Sstevel@tonic-gate 				closelog();
193*7c478bd9Sstevel@tonic-gate 				child = sv.child; setintr = sv.setintr;
194*7c478bd9Sstevel@tonic-gate 				haderr = sv.haderr; didfds = sv.didfds;
195*7c478bd9Sstevel@tonic-gate 				SHIN = sv.SHIN;
196*7c478bd9Sstevel@tonic-gate 				SHOUT = sv.SHOUT; SHDIAG = sv.SHDIAG;
197*7c478bd9Sstevel@tonic-gate 				OLDSTD = sv.OLDSTD; tpgrp = sv.tpgrp;
198*7c478bd9Sstevel@tonic-gate 				xfree(Vsav); Vsav = 0;
199*7c478bd9Sstevel@tonic-gate 				xfree(Vdp); Vdp = 0;
200*7c478bd9Sstevel@tonic-gate 				xfree( (tchar *)Vav); Vav = 0;
201*7c478bd9Sstevel@tonic-gate 				/* this is from pfork() */
202*7c478bd9Sstevel@tonic-gate 				ppid = pcurrjob ? pcurrjob->p_jobid : pid;
203*7c478bd9Sstevel@tonic-gate 				if (wanttty >= 0 && tpgrp >= 0)
204*7c478bd9Sstevel@tonic-gate 					setpgid (ppid, ppid);
205*7c478bd9Sstevel@tonic-gate 				palloc(pid, t);
206*7c478bd9Sstevel@tonic-gate 				/*
207*7c478bd9Sstevel@tonic-gate 				 * Restore SIGINT handler.
208*7c478bd9Sstevel@tonic-gate 				 */
209*7c478bd9Sstevel@tonic-gate 				(void) sigvec(SIGINT, &sv.sigv, (struct sigvec *)0);
210*7c478bd9Sstevel@tonic-gate 				(void) sigsetmask(sv.mask);
211*7c478bd9Sstevel@tonic-gate 			} else {	/* child */
212*7c478bd9Sstevel@tonic-gate 				/* this is from pfork() */
213*7c478bd9Sstevel@tonic-gate 				int pgrp;
214*7c478bd9Sstevel@tonic-gate 				bool ignint = 0;
215*7c478bd9Sstevel@tonic-gate 				int sigttou;
216*7c478bd9Sstevel@tonic-gate 				if (setintr)
217*7c478bd9Sstevel@tonic-gate 					ignint =
218*7c478bd9Sstevel@tonic-gate 					    (tpgrp == -1 && (t->t_dflg&FINT))
219*7c478bd9Sstevel@tonic-gate 					    || gointr
220*7c478bd9Sstevel@tonic-gate 						&& eq(gointr, S_MINUS/*"-"*/);
221*7c478bd9Sstevel@tonic-gate 				pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
222*7c478bd9Sstevel@tonic-gate 				child++;
223*7c478bd9Sstevel@tonic-gate 				if (setintr) {
224*7c478bd9Sstevel@tonic-gate 					setintr = 0;
225*7c478bd9Sstevel@tonic-gate #ifdef notdef
226*7c478bd9Sstevel@tonic-gate 					(void) signal(SIGCHLD, SIG_DFL);
227*7c478bd9Sstevel@tonic-gate #endif
228*7c478bd9Sstevel@tonic-gate 					(void) signal(SIGINT, ignint ?
229*7c478bd9Sstevel@tonic-gate 						SIG_IGN : vffree);
230*7c478bd9Sstevel@tonic-gate 					(void) signal(SIGQUIT, ignint ?
231*7c478bd9Sstevel@tonic-gate 						SIG_IGN : SIG_DFL);
232*7c478bd9Sstevel@tonic-gate 					if (wanttty >= 0) {
233*7c478bd9Sstevel@tonic-gate 						(void) signal(SIGTSTP, SIG_DFL);
234*7c478bd9Sstevel@tonic-gate 						(void) signal(SIGTTIN, SIG_DFL);
235*7c478bd9Sstevel@tonic-gate 						(void) signal(SIGTTOU, SIG_DFL);
236*7c478bd9Sstevel@tonic-gate 					}
237*7c478bd9Sstevel@tonic-gate 					(void) signal(SIGTERM, parterm);
238*7c478bd9Sstevel@tonic-gate 				} else if (tpgrp == -1 && (t->t_dflg&FINT)) {
239*7c478bd9Sstevel@tonic-gate 					(void) signal(SIGINT, SIG_IGN);
240*7c478bd9Sstevel@tonic-gate 					(void) signal(SIGQUIT, SIG_IGN);
241*7c478bd9Sstevel@tonic-gate 				}
242*7c478bd9Sstevel@tonic-gate 				if (wanttty >= 0 && tpgrp >= 0)
243*7c478bd9Sstevel@tonic-gate 					(void) setpgid(0, pgrp);
244*7c478bd9Sstevel@tonic-gate 				if (wanttty > 0) {
245*7c478bd9Sstevel@tonic-gate 					sigttou = sigblock (
246*7c478bd9Sstevel@tonic-gate 						sigmask(SIGTTOU) |
247*7c478bd9Sstevel@tonic-gate 						sigmask(SIGTTIN) |
248*7c478bd9Sstevel@tonic-gate 						sigmask(SIGTSTP));
249*7c478bd9Sstevel@tonic-gate 					(void) ioctl(FSHTTY, TIOCSPGRP,
250*7c478bd9Sstevel@tonic-gate 						 (tchar *)&pgrp);
251*7c478bd9Sstevel@tonic-gate 					sigsetmask (sigttou);
252*7c478bd9Sstevel@tonic-gate 				}
253*7c478bd9Sstevel@tonic-gate 				if (tpgrp > 0)
254*7c478bd9Sstevel@tonic-gate 					tpgrp = 0;
255*7c478bd9Sstevel@tonic-gate 				if (t->t_dflg & FNOHUP)
256*7c478bd9Sstevel@tonic-gate 					(void) signal(SIGHUP, SIG_IGN);
257*7c478bd9Sstevel@tonic-gate 				if (t->t_dflg & FNICE)
258*7c478bd9Sstevel@tonic-gate 					(void) setpriority(PRIO_PROCESS,
259*7c478bd9Sstevel@tonic-gate 						0, t->t_nice);
260*7c478bd9Sstevel@tonic-gate 			}
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate 		    }
263*7c478bd9Sstevel@tonic-gate #endif
264*7c478bd9Sstevel@tonic-gate 		if (pid != 0) {
265*7c478bd9Sstevel@tonic-gate 			/*
266*7c478bd9Sstevel@tonic-gate 			 * It would be better if we could wait for the
267*7c478bd9Sstevel@tonic-gate 			 * whole job when we knew the last process
268*7c478bd9Sstevel@tonic-gate 			 * had been started.  Pwait, in fact, does
269*7c478bd9Sstevel@tonic-gate 			 * wait for the whole job anyway, but this test
270*7c478bd9Sstevel@tonic-gate 			 * doesn't really express our intentions.
271*7c478bd9Sstevel@tonic-gate 			 */
272*7c478bd9Sstevel@tonic-gate 			if (didfds==0 && t->t_dflg&FPIN) {
273*7c478bd9Sstevel@tonic-gate 				(void) close(pipein[0]);
274*7c478bd9Sstevel@tonic-gate 				unsetfd(pipein[0]);
275*7c478bd9Sstevel@tonic-gate 				(void) close(pipein[1]);
276*7c478bd9Sstevel@tonic-gate 				unsetfd(pipein[1]);
277*7c478bd9Sstevel@tonic-gate 			}
278*7c478bd9Sstevel@tonic-gate 			if ((t->t_dflg & (FPOU|FAND)) == 0)
279*7c478bd9Sstevel@tonic-gate 				pwait();
280*7c478bd9Sstevel@tonic-gate 			break;
281*7c478bd9Sstevel@tonic-gate 		}
282*7c478bd9Sstevel@tonic-gate 		doio(t, pipein, pipeout);
283*7c478bd9Sstevel@tonic-gate 		if (t->t_dflg & FPOU) {
284*7c478bd9Sstevel@tonic-gate 			(void) close(pipeout[0]);
285*7c478bd9Sstevel@tonic-gate 			(void) unsetfd(pipeout[0]);
286*7c478bd9Sstevel@tonic-gate 			(void) close(pipeout[1]);
287*7c478bd9Sstevel@tonic-gate 			(void) unsetfd(pipeout[1]);
288*7c478bd9Sstevel@tonic-gate 		}
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate 		/*
291*7c478bd9Sstevel@tonic-gate 		 * Perform a builtin function.
292*7c478bd9Sstevel@tonic-gate 		 * If we are not forked, arrange for possible stopping
293*7c478bd9Sstevel@tonic-gate 		 */
294*7c478bd9Sstevel@tonic-gate 		if (bifunc) {
295*7c478bd9Sstevel@tonic-gate 			func(t, bifunc);
296*7c478bd9Sstevel@tonic-gate 			if (forked)
297*7c478bd9Sstevel@tonic-gate 				exitstat();
298*7c478bd9Sstevel@tonic-gate 			break;
299*7c478bd9Sstevel@tonic-gate 		}
300*7c478bd9Sstevel@tonic-gate 		if (t->t_dtyp != TPAR) {
301*7c478bd9Sstevel@tonic-gate 			doexec(t);
302*7c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
303*7c478bd9Sstevel@tonic-gate 		}
304*7c478bd9Sstevel@tonic-gate 		/*
305*7c478bd9Sstevel@tonic-gate 		 * For () commands must put new 0,1,2 in FSH* and recurse
306*7c478bd9Sstevel@tonic-gate 		 */
307*7c478bd9Sstevel@tonic-gate 		OLDSTD = dcopy(0, FOLDSTD);
308*7c478bd9Sstevel@tonic-gate 		SHOUT = dcopy(1, FSHOUT);
309*7c478bd9Sstevel@tonic-gate 		SHDIAG = dcopy(2, FSHDIAG);
310*7c478bd9Sstevel@tonic-gate 		(void) close(SHIN);
311*7c478bd9Sstevel@tonic-gate 		(void) unsetfd(SHIN);
312*7c478bd9Sstevel@tonic-gate 		SHIN = -1;
313*7c478bd9Sstevel@tonic-gate 		didfds = 0;
314*7c478bd9Sstevel@tonic-gate 		wanttty = -1;
315*7c478bd9Sstevel@tonic-gate 		t->t_dspr->t_dflg |= t->t_dflg & FINT;
316*7c478bd9Sstevel@tonic-gate 		execute(t->t_dspr, wanttty);
317*7c478bd9Sstevel@tonic-gate 		exitstat();
318*7c478bd9Sstevel@tonic-gate 
319*7c478bd9Sstevel@tonic-gate 	case TFIL:
320*7c478bd9Sstevel@tonic-gate 		t->t_dcar->t_dflg |= FPOU |
321*7c478bd9Sstevel@tonic-gate 		    (t->t_dflg & (FPIN|FAND|FDIAG|FINT));
322*7c478bd9Sstevel@tonic-gate 		execute(t->t_dcar, wanttty, pipein, pv);
323*7c478bd9Sstevel@tonic-gate 		t->t_dcdr->t_dflg |= FPIN |
324*7c478bd9Sstevel@tonic-gate 		    (t->t_dflg & (FPOU|FAND|FPAR|FINT));
325*7c478bd9Sstevel@tonic-gate 		if (wanttty > 0)
326*7c478bd9Sstevel@tonic-gate 			wanttty = 0;		/* got tty already */
327*7c478bd9Sstevel@tonic-gate 		execute(t->t_dcdr, wanttty, pv, pipeout);
328*7c478bd9Sstevel@tonic-gate 		break;
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	case TLST:
331*7c478bd9Sstevel@tonic-gate 		if (t->t_dcar) {
332*7c478bd9Sstevel@tonic-gate 			t->t_dcar->t_dflg |= t->t_dflg & FINT;
333*7c478bd9Sstevel@tonic-gate 			execute(t->t_dcar, wanttty);
334*7c478bd9Sstevel@tonic-gate 			/*
335*7c478bd9Sstevel@tonic-gate 			 * In strange case of A&B make a new job after A
336*7c478bd9Sstevel@tonic-gate 			 */
337*7c478bd9Sstevel@tonic-gate 			if (t->t_dcar->t_dflg&FAND && t->t_dcdr &&
338*7c478bd9Sstevel@tonic-gate 			    (t->t_dcdr->t_dflg&FAND) == 0)
339*7c478bd9Sstevel@tonic-gate 				pendjob();
340*7c478bd9Sstevel@tonic-gate 		}
341*7c478bd9Sstevel@tonic-gate 		if (t->t_dcdr) {
342*7c478bd9Sstevel@tonic-gate 			t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
343*7c478bd9Sstevel@tonic-gate 			execute(t->t_dcdr, wanttty);
344*7c478bd9Sstevel@tonic-gate 		}
345*7c478bd9Sstevel@tonic-gate 		break;
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate 	case TOR:
348*7c478bd9Sstevel@tonic-gate 	case TAND:
349*7c478bd9Sstevel@tonic-gate 		if (t->t_dcar) {
350*7c478bd9Sstevel@tonic-gate 			t->t_dcar->t_dflg |= t->t_dflg & FINT;
351*7c478bd9Sstevel@tonic-gate 			execute(t->t_dcar, wanttty);
352*7c478bd9Sstevel@tonic-gate 			if ((getn(value(S_status/*"status"*/)) == 0) != (t->t_dtyp == TAND))
353*7c478bd9Sstevel@tonic-gate 				return;
354*7c478bd9Sstevel@tonic-gate 		}
355*7c478bd9Sstevel@tonic-gate 		if (t->t_dcdr) {
356*7c478bd9Sstevel@tonic-gate 			t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
357*7c478bd9Sstevel@tonic-gate 			execute(t->t_dcdr, wanttty);
358*7c478bd9Sstevel@tonic-gate 		}
359*7c478bd9Sstevel@tonic-gate 		break;
360*7c478bd9Sstevel@tonic-gate 	}
361*7c478bd9Sstevel@tonic-gate 	/*
362*7c478bd9Sstevel@tonic-gate 	 * Fall through for all breaks from switch
363*7c478bd9Sstevel@tonic-gate 	 *
364*7c478bd9Sstevel@tonic-gate 	 * If there will be no more executions of this
365*7c478bd9Sstevel@tonic-gate 	 * command, flush all file descriptors.
366*7c478bd9Sstevel@tonic-gate 	 * Places that turn on the FREDO bit are responsible
367*7c478bd9Sstevel@tonic-gate 	 * for doing donefds after the last re-execution
368*7c478bd9Sstevel@tonic-gate 	 */
369*7c478bd9Sstevel@tonic-gate 	if (didfds && !(t->t_dflg & FREDO))
370*7c478bd9Sstevel@tonic-gate 		donefds();
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 	/*
373*7c478bd9Sstevel@tonic-gate 	 * If glob() was called and arguments list is not yet
374*7c478bd9Sstevel@tonic-gate 	 * free'ed, free them here.
375*7c478bd9Sstevel@tonic-gate 	 */
376*7c478bd9Sstevel@tonic-gate 	if (gargv) {
377*7c478bd9Sstevel@tonic-gate 		blkfree(gargv);
378*7c478bd9Sstevel@tonic-gate 		gargv = 0;
379*7c478bd9Sstevel@tonic-gate 		globcnt = 0;
380*7c478bd9Sstevel@tonic-gate 	}
381*7c478bd9Sstevel@tonic-gate }
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate #ifdef VFORK
384*7c478bd9Sstevel@tonic-gate void
385*7c478bd9Sstevel@tonic-gate vffree()
386*7c478bd9Sstevel@tonic-gate {
387*7c478bd9Sstevel@tonic-gate 	register tchar **v;
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate #ifdef TRACE
390*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- vffree()\n");
391*7c478bd9Sstevel@tonic-gate #endif
392*7c478bd9Sstevel@tonic-gate 	if (v = gargv)
393*7c478bd9Sstevel@tonic-gate 		gargv = 0, xfree( (tchar *)v);
394*7c478bd9Sstevel@tonic-gate 	if (v = pargv)
395*7c478bd9Sstevel@tonic-gate 		pargv = 0, xfree( (tchar *)v);
396*7c478bd9Sstevel@tonic-gate 	_exit(1);
397*7c478bd9Sstevel@tonic-gate }
398*7c478bd9Sstevel@tonic-gate #endif
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate /*
401*7c478bd9Sstevel@tonic-gate  * Perform io redirection.
402*7c478bd9Sstevel@tonic-gate  * We may or maynot be forked here.
403*7c478bd9Sstevel@tonic-gate  */
404*7c478bd9Sstevel@tonic-gate doio(t, pipein, pipeout)
405*7c478bd9Sstevel@tonic-gate 	register struct command *t;
406*7c478bd9Sstevel@tonic-gate 	int *pipein, *pipeout;
407*7c478bd9Sstevel@tonic-gate {
408*7c478bd9Sstevel@tonic-gate 	register tchar *cp, *dp;
409*7c478bd9Sstevel@tonic-gate 	register int flags = t->t_dflg;
410*7c478bd9Sstevel@tonic-gate 	int fd;
411*7c478bd9Sstevel@tonic-gate 
412*7c478bd9Sstevel@tonic-gate #ifdef TRACE
413*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- doio()\n");
414*7c478bd9Sstevel@tonic-gate #endif
415*7c478bd9Sstevel@tonic-gate 	if (didfds || (flags & FREDO))
416*7c478bd9Sstevel@tonic-gate 		return;
417*7c478bd9Sstevel@tonic-gate 	if ((flags & FHERE) == 0) {	/* FHERE already done */
418*7c478bd9Sstevel@tonic-gate 		(void) close(0);
419*7c478bd9Sstevel@tonic-gate 		(void) unsetfd(0);
420*7c478bd9Sstevel@tonic-gate 		if (cp = t->t_dlef) {
421*7c478bd9Sstevel@tonic-gate 			dp = Dfix1(cp);
422*7c478bd9Sstevel@tonic-gate 			cp = globone(dp);
423*7c478bd9Sstevel@tonic-gate 			xfree(dp);
424*7c478bd9Sstevel@tonic-gate 			xfree(cp);
425*7c478bd9Sstevel@tonic-gate 			if (open_(cp, 0) < 0)
426*7c478bd9Sstevel@tonic-gate 				Perror(cp);
427*7c478bd9Sstevel@tonic-gate 		} else if (flags & FPIN) {
428*7c478bd9Sstevel@tonic-gate 			fd = dup(pipein[0]);
429*7c478bd9Sstevel@tonic-gate 			if (fd != -1)
430*7c478bd9Sstevel@tonic-gate 				setfd(fd);
431*7c478bd9Sstevel@tonic-gate 			(void) close(pipein[0]);
432*7c478bd9Sstevel@tonic-gate 			(void) unsetfd(pipein[0]);
433*7c478bd9Sstevel@tonic-gate 			(void) close(pipein[1]);
434*7c478bd9Sstevel@tonic-gate 			(void) unsetfd(pipein[1]);
435*7c478bd9Sstevel@tonic-gate 		} else if ((flags & FINT) && tpgrp == -1) {
436*7c478bd9Sstevel@tonic-gate 			(void) close(0);	/* no need for unsetfd */
437*7c478bd9Sstevel@tonic-gate 			(void) open("/dev/null", 0); /* no need for setfd */
438*7c478bd9Sstevel@tonic-gate 		} else {
439*7c478bd9Sstevel@tonic-gate 			fd = dup(OLDSTD);
440*7c478bd9Sstevel@tonic-gate 			if (fd != -1)
441*7c478bd9Sstevel@tonic-gate 				setfd(fd);
442*7c478bd9Sstevel@tonic-gate 		}
443*7c478bd9Sstevel@tonic-gate 	}
444*7c478bd9Sstevel@tonic-gate 	(void) close(1);
445*7c478bd9Sstevel@tonic-gate 	(void) unsetfd(1);
446*7c478bd9Sstevel@tonic-gate 	if (cp = t->t_drit) {
447*7c478bd9Sstevel@tonic-gate 		dp = Dfix1(cp);
448*7c478bd9Sstevel@tonic-gate 		cp = globone(dp);
449*7c478bd9Sstevel@tonic-gate 		xfree(dp);
450*7c478bd9Sstevel@tonic-gate 		if ((flags & FCAT) && open_(cp, 1) >= 0)
451*7c478bd9Sstevel@tonic-gate 			(void) lseek(1, (off_t)0, 2);
452*7c478bd9Sstevel@tonic-gate 		else {
453*7c478bd9Sstevel@tonic-gate 			if (!(flags & FANY) && adrof(S_noclobber/*"noclobber"*/)) {
454*7c478bd9Sstevel@tonic-gate 				if (flags & FCAT)
455*7c478bd9Sstevel@tonic-gate 					Perror(cp);
456*7c478bd9Sstevel@tonic-gate 				chkclob(cp);
457*7c478bd9Sstevel@tonic-gate 			}
458*7c478bd9Sstevel@tonic-gate 			if (creat_(cp, 0666) < 0)
459*7c478bd9Sstevel@tonic-gate 				Perror(cp);
460*7c478bd9Sstevel@tonic-gate 		}
461*7c478bd9Sstevel@tonic-gate 		xfree(cp);
462*7c478bd9Sstevel@tonic-gate 	} else if (flags & FPOU) {
463*7c478bd9Sstevel@tonic-gate 		fd = dup(pipeout[1]);
464*7c478bd9Sstevel@tonic-gate 		if (fd != -1)
465*7c478bd9Sstevel@tonic-gate 			setfd (fd);
466*7c478bd9Sstevel@tonic-gate 	}
467*7c478bd9Sstevel@tonic-gate 	else {
468*7c478bd9Sstevel@tonic-gate 		fd = dup(SHOUT);
469*7c478bd9Sstevel@tonic-gate 		if (fd != -1)
470*7c478bd9Sstevel@tonic-gate 			setfd(fd);
471*7c478bd9Sstevel@tonic-gate 	}
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate 	(void) close(2);
474*7c478bd9Sstevel@tonic-gate 	(void) unsetfd(2);
475*7c478bd9Sstevel@tonic-gate 	if (flags & FDIAG) {
476*7c478bd9Sstevel@tonic-gate 		fd = dup(1);
477*7c478bd9Sstevel@tonic-gate 		if (fd != -1)
478*7c478bd9Sstevel@tonic-gate 			setfd(fd);
479*7c478bd9Sstevel@tonic-gate 	}
480*7c478bd9Sstevel@tonic-gate 	else {
481*7c478bd9Sstevel@tonic-gate 		fd = dup(SHDIAG);
482*7c478bd9Sstevel@tonic-gate 		if (fd != -1)
483*7c478bd9Sstevel@tonic-gate 			setfd(fd);
484*7c478bd9Sstevel@tonic-gate 	}
485*7c478bd9Sstevel@tonic-gate 	didfds = 1;
486*7c478bd9Sstevel@tonic-gate }
487*7c478bd9Sstevel@tonic-gate 
488*7c478bd9Sstevel@tonic-gate mypipe(pv)
489*7c478bd9Sstevel@tonic-gate 	register int *pv;
490*7c478bd9Sstevel@tonic-gate {
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate #ifdef TRACE
493*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- mypipe()\n");
494*7c478bd9Sstevel@tonic-gate #endif
495*7c478bd9Sstevel@tonic-gate 	if (pipe(pv) < 0)
496*7c478bd9Sstevel@tonic-gate 		goto oops;
497*7c478bd9Sstevel@tonic-gate 	setfd(pv[0]);
498*7c478bd9Sstevel@tonic-gate 	setfd(pv[1]);
499*7c478bd9Sstevel@tonic-gate 
500*7c478bd9Sstevel@tonic-gate 	pv[0] = dmove(pv[0], -1);
501*7c478bd9Sstevel@tonic-gate 	pv[1] = dmove(pv[1], -1);
502*7c478bd9Sstevel@tonic-gate 	if (pv[0] >= 0 && pv[1] >= 0)
503*7c478bd9Sstevel@tonic-gate 		return;
504*7c478bd9Sstevel@tonic-gate oops:
505*7c478bd9Sstevel@tonic-gate 	error("Can't make pipe");
506*7c478bd9Sstevel@tonic-gate }
507*7c478bd9Sstevel@tonic-gate 
508*7c478bd9Sstevel@tonic-gate chkclob(cp)
509*7c478bd9Sstevel@tonic-gate 	register tchar *cp;
510*7c478bd9Sstevel@tonic-gate {
511*7c478bd9Sstevel@tonic-gate 	struct stat stb;
512*7c478bd9Sstevel@tonic-gate 	unsigned short	type;
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate #ifdef TRACE
515*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- chkclob()\n");
516*7c478bd9Sstevel@tonic-gate #endif
517*7c478bd9Sstevel@tonic-gate 	if (stat_(cp, &stb) < 0)
518*7c478bd9Sstevel@tonic-gate 		return;
519*7c478bd9Sstevel@tonic-gate 	type = stb.st_mode & S_IFMT;
520*7c478bd9Sstevel@tonic-gate 	if (type == S_IFCHR || type == S_IFIFO)
521*7c478bd9Sstevel@tonic-gate 		return;
522*7c478bd9Sstevel@tonic-gate 	error("%t: File exists", cp);
523*7c478bd9Sstevel@tonic-gate }
524