sh.sem.c revision 69408
1/* $Header: /src/pub/tcsh/sh.sem.c,v 3.51 2000/11/11 23:03:38 christos Exp $ */
2/*
3 * sh.sem.c: I/O redirections and job forking. A touchy issue!
4 *	     Most stuff with builtins is incorrect
5 */
6/*-
7 * Copyright (c) 1980, 1991 The Regents of the University of California.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by the University of
21 *	California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38#include "sh.h"
39
40RCSID("$Id: sh.sem.c,v 3.51 2000/11/11 23:03:38 christos Exp $")
41
42#include "tc.h"
43#include "tw.h"
44#ifdef WINNT_NATIVE
45#include "nt.const.h"
46#endif /*WINNT_NATIVE*/
47
48#ifdef CLOSE_ON_EXEC
49# ifndef SUNOS4
50#  ifndef CLEX_DUPS
51#   define CLEX_DUPS
52#  endif /* CLEX_DUPS */
53# endif /* !SUNOS4 */
54#endif /* CLOSE_ON_EXEC */
55
56#if defined(__sparc__) || defined(sparc)
57# if !defined(MACH) && SYSVREL == 0 && !defined(Lynx) && !defined(BSD4_4) && !defined(linux)
58#  include <vfork.h>
59# endif /* !MACH && SYSVREL == 0 && !Lynx && !BSD4_4 && !linux */
60#endif /* __sparc__ || sparc */
61
62#ifdef VFORK
63static	sigret_t	vffree	__P((int));
64#endif
65static	Char		*splicepipe	__P((struct command *, Char *));
66static	void		 doio		__P((struct command *, int *, int *));
67static	void		 chkclob	__P((char *));
68
69/*
70 * C shell
71 */
72
73/*
74 * For SVR4, there are problems with pipelines having the first process as
75 * the group leader.  The problem occurs when the first process exits before
76 * the others have a chance to setpgid().  This is because in SVR4 you can't
77 * have a zombie as a group leader.  The solution I have used is to reverse
78 * the order in which pipelines are started, making the last process the
79 * group leader.  (Note I am not using 'pipeline' in the generic sense -- I
80 * mean processes connected by '|'.)  I don't know yet if this causes other
81 * problems.
82 *
83 * All the changes for this are in execute(), and are enclosed in
84 * '#ifdef BACKPIPE'
85 *
86 * David Dawes (dawes@physics.su.oz.au) Oct 1991
87 */
88
89/*VARARGS 1*/
90void
91execute(t, wanttty, pipein, pipeout)
92    register struct command *t;
93    int     wanttty;
94    int *pipein, *pipeout;
95{
96#ifdef VFORK
97    extern bool use_fork;	/* use fork() instead of vfork()? */
98#endif
99
100    bool    forked = 0;
101    struct biltins *bifunc;
102    int     pid = 0;
103    int     pv[2];
104#ifdef BSDSIGS
105    static sigmask_t csigmask;
106#endif /* BSDSIGS */
107#ifdef VFORK
108    static int onosigchld = 0;
109#endif /* VFORK */
110    static int nosigchld = 0;
111
112    (void) &wanttty;
113    (void) &forked;
114    (void) &bifunc;
115
116    if (t == 0)
117	return;
118
119#ifdef WINNT_NATIVE
120    {
121        if ((varval(STRNTslowexec) == STRNULL) &&
122            !t->t_dcdr && !t->t_dcar && !t->t_dflg && !didfds &&
123            (intty || intact) && (t->t_dtyp == NODE_COMMAND) &&
124	    !isbfunc(t)) {
125	    if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE)
126		(void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
127	    Dfix(t);
128            if (nt_try_fast_exec(t) == 0)
129                return;
130        }
131    }
132#endif /* WINNT_NATIVE */
133
134    /*
135     * Ed hutchins@sgi.com & Dominic dbg@sgi.com
136     * Sat Feb 25 03:13:11 PST 1995
137     * try implicit cd if we have a 1 word command
138     */
139    if (implicit_cd && (intty || intact) && t->t_dcom && t->t_dcom[0] &&
140	 t->t_dcom[0][0] && (blklen(t->t_dcom) == 1) && !noexec) {
141	Char sCName[MAXPATHLEN];
142	Char *pCN;
143	struct stat stbuf;
144	char *pathname;
145
146	dollar(sCName, t->t_dcom[0]);
147	pCN = sCName;
148	if (pCN[0] == '~') {
149	    Char sCPath[MAXPATHLEN];
150	    Char *pCP = sCPath;
151
152	    ++pCN;
153	    while (*pCN && *pCN != '/')
154		*pCP++ = *pCN++;
155	    *pCP = 0;
156	    if (sCPath[0])
157		gethdir(sCPath);
158	    else
159		(void) Strcpy(sCPath, varval(STRhome));
160	    catn(sCPath, pCN, MAXPATHLEN);
161	    (void) Strcpy(sCName, sCPath);
162	}
163
164	pathname = short2str(sCName);
165	/* if this is a dir, tack a "cd" on as the first arg */
166	if ((stat(pathname, &stbuf) != -1 && S_ISDIR(stbuf.st_mode))
167#ifdef WINNT_NATIVE
168	    || (pathname[0] && pathname[1] == ':' && pathname[2] == '\0')
169#endif /* WINNT_NATIVE */
170	) {
171	    Char *vCD[2];
172	    Char **ot_dcom = t->t_dcom;
173
174	    vCD[0] = Strsave(STRcd);
175	    vCD[1] = NULL;
176	    t->t_dcom = blkspl(vCD, ot_dcom);
177	    if (implicit_cd > 1) {
178		blkpr(t->t_dcom);
179		xputchar( '\n' );
180	    }
181	    xfree((ptr_t) ot_dcom);
182	}
183    }
184
185    /*
186     * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
187     * Don't check for wantty > 0...
188     */
189    if (t->t_dflg & F_AMPERSAND)
190	wanttty = 0;
191    switch (t->t_dtyp) {
192
193    case NODE_COMMAND:
194	if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE)
195	    (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
196	if ((t->t_dflg & F_REPEAT) == 0)
197	    Dfix(t);		/* $ " ' \ */
198	if (t->t_dcom[0] == 0) {
199	    return;
200	}
201	/*FALLTHROUGH*/
202
203    case NODE_PAREN:
204#ifdef BACKPIPE
205	if (t->t_dflg & F_PIPEIN)
206	    mypipe(pipein);
207#else /* !BACKPIPE */
208	if (t->t_dflg & F_PIPEOUT)
209	    mypipe(pipeout);
210#endif /* BACKPIPE */
211	/*
212	 * Must do << early so parent will know where input pointer should be.
213	 * If noexec then this is all we do.
214	 */
215	if (t->t_dflg & F_READ) {
216	    (void) close(0);
217	    heredoc(t->t_dlef);
218	    if (noexec)
219		(void) close(0);
220	}
221
222	set(STRstatus, Strsave(STR0), VAR_READWRITE);
223
224	/*
225	 * This mess is the necessary kludge to handle the prefix builtins:
226	 * nice, nohup, time.  These commands can also be used by themselves,
227	 * and this is not handled here. This will also work when loops are
228	 * parsed.
229	 */
230	while (t->t_dtyp == NODE_COMMAND)
231	    if (eq(t->t_dcom[0], STRnice)) {
232		if (t->t_dcom[1]) {
233		    if (strchr("+-", t->t_dcom[1][0])) {
234			if (t->t_dcom[2]) {
235			    setname("nice");
236			    t->t_nice =
237				getn(t->t_dcom[1]);
238			    lshift(t->t_dcom, 2);
239			    t->t_dflg |= F_NICE;
240			}
241			else
242			    break;
243		    }
244		    else {
245			t->t_nice = 4;
246			lshift(t->t_dcom, 1);
247			t->t_dflg |= F_NICE;
248		    }
249		}
250		else
251		    break;
252	    }
253	    else if (eq(t->t_dcom[0], STRnohup)) {
254		if (t->t_dcom[1]) {
255		    t->t_dflg |= F_NOHUP;
256		    lshift(t->t_dcom, 1);
257		}
258		else
259		    break;
260	    }
261	    else if (eq(t->t_dcom[0], STRhup)) {
262		if (t->t_dcom[1]) {
263		    t->t_dflg |= F_HUP;
264		    lshift(t->t_dcom, 1);
265		}
266		else
267		    break;
268	    }
269	    else if (eq(t->t_dcom[0], STRtime)) {
270		if (t->t_dcom[1]) {
271		    t->t_dflg |= F_TIME;
272		    lshift(t->t_dcom, 1);
273		}
274		else
275		    break;
276	    }
277#ifdef F_VER
278	    else if (eq(t->t_dcom[0], STRver))
279		if (t->t_dcom[1] && t->t_dcom[2]) {
280		    setname("ver");
281		    t->t_systype = getv(t->t_dcom[1]);
282		    lshift(t->t_dcom, 2);
283		    t->t_dflg |= F_VER;
284		}
285		else
286		    break;
287#endif  /* F_VER */
288	    else
289		break;
290
291	/* is it a command */
292	if (t->t_dtyp == NODE_COMMAND) {
293	    /*
294	     * Check if we have a builtin function and remember which one.
295	     */
296	    bifunc = isbfunc(t);
297 	    if (noexec && bifunc) {
298		/*
299		 * Continue for builtins that are part of the scripting language
300		 */
301		if (bifunc->bfunct != (bfunc_t)dobreak	&&
302		    bifunc->bfunct != (bfunc_t)docontin	&&
303		    bifunc->bfunct != (bfunc_t)doelse	&&
304		    bifunc->bfunct != (bfunc_t)doend	&&
305		    bifunc->bfunct != (bfunc_t)doforeach&&
306		    bifunc->bfunct != (bfunc_t)dogoto	&&
307		    bifunc->bfunct != (bfunc_t)doif	&&
308		    bifunc->bfunct != (bfunc_t)dorepeat	&&
309		    bifunc->bfunct != (bfunc_t)doswbrk	&&
310		    bifunc->bfunct != (bfunc_t)doswitch	&&
311		    bifunc->bfunct != (bfunc_t)dowhile	&&
312		    bifunc->bfunct != (bfunc_t)dozip)
313		    break;
314	    }
315	}
316	else {			/* not a command */
317	    bifunc = NULL;
318	    if (noexec)
319		break;
320	}
321
322	/*
323	 * We fork only if we are timed, or are not the end of a parenthesized
324	 * list and not a simple builtin function. Simple meaning one that is
325	 * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not
326	 * fork in some of these cases.
327	 */
328	/*
329	 * Prevent forking cd, pushd, popd, chdir cause this will cause the
330	 * shell not to change dir!
331	 */
332#ifdef BACKPIPE
333	/*
334	 * Can't have NOFORK for the tail of a pipe - because it is not the
335	 * last command spawned (even if it is at the end of a parenthesised
336	 * list).
337	 */
338	if (t->t_dflg & F_PIPEIN)
339	    t->t_dflg &= ~(F_NOFORK);
340#endif /* BACKPIPE */
341	if (bifunc && (bifunc->bfunct == (bfunc_t)dochngd ||
342		       bifunc->bfunct == (bfunc_t)dopushd ||
343		       bifunc->bfunct == (bfunc_t)dopopd))
344	    t->t_dflg &= ~(F_NICE);
345	if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 &&
346	     (!bifunc || t->t_dflg &
347	      (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP | F_HUP)))) ||
348	/*
349	 * We have to fork for eval too.
350	 */
351	    (bifunc && (t->t_dflg & F_PIPEIN) != 0 &&
352	     bifunc->bfunct == (bfunc_t)doeval)) {
353#ifdef VFORK
354	    if (t->t_dtyp == NODE_PAREN ||
355		t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc)
356#endif /* VFORK */
357	    {
358		forked++;
359		/*
360		 * We need to block SIGCHLD here, so that if the process does
361		 * not die before we can set the process group
362		 */
363		if (wanttty >= 0 && !nosigchld) {
364#ifdef BSDSIGS
365		    csigmask = sigblock(sigmask(SIGCHLD));
366#else /* !BSDSIGS */
367		    (void) sighold(SIGCHLD);
368#endif /* BSDSIGS */
369
370		    nosigchld = 1;
371		}
372
373		pid = pfork(t, wanttty);
374		if (pid == 0 && nosigchld) {
375#ifdef BSDSIGS
376		    (void) sigsetmask(csigmask);
377#else /* !BSDSIGS */
378		    (void) sigrelse(SIGCHLD);
379#endif /* BSDSIGS */
380		    nosigchld = 0;
381		}
382		else if (pid != 0 && (t->t_dflg & F_AMPERSAND))
383		    backpid = pid;
384	    }
385
386#ifdef VFORK
387	    else {
388		int     ochild, osetintr, ohaderr, odidfds;
389		int     oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp;
390		int     oisoutatty, oisdiagatty;
391
392# ifndef CLOSE_ON_EXEC
393		int     odidcch;
394# endif  /* !CLOSE_ON_EXEC */
395# ifdef BSDSIGS
396		sigmask_t omask, ocsigmask;
397# endif /* BSDSIGS */
398
399		/*
400		 * Prepare for the vfork by saving everything that the child
401		 * corrupts before it exec's. Note that in some signal
402		 * implementations which keep the signal info in user space
403		 * (e.g. Sun's) it will also be necessary to save and restore
404		 * the current sigvec's for the signals the child touches
405		 * before it exec's.
406		 */
407
408		/*
409		 * Sooooo true... If this is a Sun, save the sigvec's. (Skip
410		 * Gilbrech - 11/22/87)
411		 */
412# ifdef SAVESIGVEC
413		sigvec_t savesv[NSIGSAVED];
414		sigmask_t savesm;
415
416# endif /* SAVESIGVEC */
417		if (wanttty >= 0 && !nosigchld && !noexec) {
418# ifdef BSDSIGS
419		    csigmask = sigblock(sigmask(SIGCHLD));
420# else /* !BSDSIGS */
421		    (void) sighold(SIGCHLD);
422# endif  /* BSDSIGS */
423		    nosigchld = 1;
424		}
425# ifdef BSDSIGS
426		omask = sigblock(sigmask(SIGCHLD)|sigmask(SIGINT));
427# else /* !BSDSIGS */
428		(void) sighold(SIGCHLD);
429		(void) sighold(SIGINT);
430# endif  /* BSDSIGS */
431		ochild = child;
432		osetintr = setintr;
433		ohaderr = haderr;
434		odidfds = didfds;
435# ifndef CLOSE_ON_EXEC
436		odidcch = didcch;
437# endif /* !CLOSE_ON_EXEC */
438		oSHIN = SHIN;
439		oSHOUT = SHOUT;
440		oSHDIAG = SHDIAG;
441		oOLDSTD = OLDSTD;
442		otpgrp = tpgrp;
443		oisoutatty = isoutatty;
444		oisdiagatty = isdiagatty;
445# ifdef BSDSIGS
446		ocsigmask = csigmask;
447# endif /* BSDSIGS */
448		onosigchld = nosigchld;
449		Vsav = Vdp = 0;
450		Vexpath = 0;
451		Vt = 0;
452# ifdef SAVESIGVEC
453		savesm = savesigvec(savesv);
454# endif /* SAVESIGVEC */
455		if (use_fork)
456		    pid = fork();
457		else
458		    pid = vfork();
459
460		if (pid < 0) {
461# ifdef BSDSIGS
462#  ifdef SAVESIGVEC
463		    restoresigvec(savesv, savesm);
464#  endif /* SAVESIGVEC */
465		    (void) sigsetmask(omask);
466# else /* !BSDSIGS */
467		    (void) sigrelse(SIGCHLD);
468		    (void) sigrelse(SIGINT);
469# endif  /* BSDSIGS */
470		    stderror(ERR_NOPROC);
471		}
472		forked++;
473		if (pid) {	/* parent */
474# ifdef SAVESIGVEC
475		    restoresigvec(savesv, savesm);
476# endif /* SAVESIGVEC */
477		    child = ochild;
478		    setintr = osetintr;
479		    haderr = ohaderr;
480		    didfds = odidfds;
481		    SHIN = oSHIN;
482# ifndef CLOSE_ON_EXEC
483		    didcch = odidcch;
484# endif /* !CLOSE_ON_EXEC */
485		    SHOUT = oSHOUT;
486		    SHDIAG = oSHDIAG;
487		    OLDSTD = oOLDSTD;
488		    tpgrp = otpgrp;
489		    isoutatty = oisoutatty;
490		    isdiagatty = oisdiagatty;
491# ifdef BSDSIGS
492		    csigmask = ocsigmask;
493# endif /* BSDSIGS */
494		    nosigchld = onosigchld;
495
496		    xfree((ptr_t) Vsav);
497		    Vsav = 0;
498		    xfree((ptr_t) Vdp);
499		    Vdp = 0;
500		    xfree((ptr_t) Vexpath);
501		    Vexpath = 0;
502		    blkfree((Char **) Vt);
503		    Vt = 0;
504		    /* this is from pfork() */
505		    palloc(pid, t);
506# ifdef BSDSIGS
507		    (void) sigsetmask(omask);
508# else /* !BSDSIGS */
509		    (void) sigrelse(SIGCHLD);
510		    (void) sigrelse(SIGINT);
511# endif  /* BSDSIGS */
512		}
513		else {		/* child */
514		    /* this is from pfork() */
515		    int     pgrp;
516		    bool    ignint = 0;
517		    if (nosigchld) {
518# ifdef BSDSIGS
519			(void) sigsetmask(csigmask);
520# else /* !BSDSIGS */
521			(void) sigrelse(SIGCHLD);
522# endif /* BSDSIGS */
523			nosigchld = 0;
524		    }
525
526		    if (setintr)
527			ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
528				|| (gointr && eq(gointr, STRminus));
529		    pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
530		    child++;
531		    if (setintr) {
532			setintr = 0;
533/*
534 * casts made right for SunOS 4.0 by Douglas C. Schmidt
535 * <schmidt%sunshine.ics.uci.edu@ROME.ICS.UCI.EDU>
536 * (thanks! -- PWP)
537 *
538 * ignint ifs cleaned by Johan Widen <mcvax!osiris.sics.se!jw@uunet.UU.NET>
539 * (thanks again)
540 */
541			if (ignint) {
542			    (void) signal(SIGINT, SIG_IGN);
543			    (void) signal(SIGQUIT, SIG_IGN);
544			}
545			else {
546			    (void) signal(SIGINT,  vffree);
547			    (void) signal(SIGQUIT, SIG_DFL);
548			}
549# ifdef BSDJOBS
550			if (wanttty >= 0) {
551			    (void) signal(SIGTSTP, SIG_DFL);
552			    (void) signal(SIGTTIN, SIG_DFL);
553			    (void) signal(SIGTTOU, SIG_DFL);
554			}
555# endif /* BSDJOBS */
556
557			(void) signal(SIGTERM, parterm);
558		    }
559		    else if (tpgrp == -1 &&
560			     (t->t_dflg & F_NOINTERRUPT)) {
561			(void) signal(SIGINT, SIG_IGN);
562			(void) signal(SIGQUIT, SIG_IGN);
563		    }
564
565		    pgetty(wanttty, pgrp);
566
567		    if (t->t_dflg & F_NOHUP)
568			(void) signal(SIGHUP, SIG_IGN);
569		    if (t->t_dflg & F_HUP)
570			(void) signal(SIGHUP, SIG_DFL);
571		    if (t->t_dflg & F_NICE) {
572			int nval = SIGN_EXTEND_CHAR(t->t_nice);
573# ifdef BSDNICE
574			(void) setpriority(PRIO_PROCESS, 0, nval);
575# else /* !BSDNICE */
576			(void) nice(nval);
577# endif /* BSDNICE */
578		    }
579# ifdef F_VER
580		    if (t->t_dflg & F_VER) {
581			tsetenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53);
582			dohash(NULL, NULL);
583		    }
584# endif /* F_VER */
585		}
586
587	    }
588#endif /* VFORK */
589	}
590	if (pid != 0) {
591	    /*
592	     * It would be better if we could wait for the whole job when we
593	     * knew the last process had been started.  Pwait, in fact, does
594	     * wait for the whole job anyway, but this test doesn't really
595	     * express our intentions.
596	     */
597#ifdef BACKPIPE
598	    if (didfds == 0 && t->t_dflg & F_PIPEOUT) {
599		(void) close(pipeout[0]);
600		(void) close(pipeout[1]);
601	    }
602	    if ((t->t_dflg & F_PIPEIN) != 0)
603		break;
604#else /* !BACKPIPE */
605	    if (didfds == 0 && t->t_dflg & F_PIPEIN) {
606		(void) close(pipein[0]);
607		(void) close(pipein[1]);
608	    }
609	    if ((t->t_dflg & F_PIPEOUT) != 0)
610		break;
611#endif /* BACKPIPE */
612
613	    if (nosigchld) {
614#ifdef BSDSIGS
615		(void) sigsetmask(csigmask);
616#else /* !BSDSIGS */
617		(void) sigrelse(SIGCHLD);
618#endif /* BSDSIGS */
619		nosigchld = 0;
620	    }
621	    if ((t->t_dflg & F_AMPERSAND) == 0)
622		pwait();
623	    break;
624	}
625
626	doio(t, pipein, pipeout);
627#ifdef BACKPIPE
628	if (t->t_dflg & F_PIPEIN) {
629	    (void) close(pipein[0]);
630	    (void) close(pipein[1]);
631	}
632#else /* !BACKPIPE */
633	if (t->t_dflg & F_PIPEOUT) {
634	    (void) close(pipeout[0]);
635	    (void) close(pipeout[1]);
636	}
637#endif /* BACKPIPE */
638	/*
639	 * Perform a builtin function. If we are not forked, arrange for
640	 * possible stopping
641	 */
642	if (bifunc) {
643	    func(t, bifunc);
644	    if (forked)
645		exitstat();
646	    break;
647	}
648	if (t->t_dtyp != NODE_PAREN) {
649	    doexec(t);
650	    /* NOTREACHED */
651	}
652	/*
653	 * For () commands must put new 0,1,2 in FSH* and recurse
654	 */
655	OLDSTD = dcopy(0, FOLDSTD);
656	SHOUT = dcopy(1, FSHOUT);
657	isoutatty = isatty(SHOUT);
658	SHDIAG = dcopy(2, FSHDIAG);
659	isdiagatty = isatty(SHDIAG);
660	(void) close(SHIN);
661	SHIN = -1;
662#ifndef CLOSE_ON_EXEC
663	didcch = 0;
664#endif /* !CLOSE_ON_EXEC */
665	didfds = 0;
666	wanttty = -1;
667	t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT;
668	execute(t->t_dspr, wanttty, NULL, NULL);
669	exitstat();
670
671    case NODE_PIPE:
672#ifdef BACKPIPE
673	t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg &
674			(F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT));
675	execute(t->t_dcdr, wanttty, pv, pipeout);
676	t->t_dcar->t_dflg |= F_PIPEOUT |
677	    (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT));
678	execute(t->t_dcar, wanttty, pipein, pv);
679#else /* !BACKPIPE */
680	t->t_dcar->t_dflg |= F_PIPEOUT |
681	    (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT));
682	execute(t->t_dcar, wanttty, pipein, pv);
683	t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg &
684			(F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT));
685	execute(t->t_dcdr, wanttty, pv, pipeout);
686#endif /* BACKPIPE */
687	break;
688
689    case NODE_LIST:
690	if (t->t_dcar) {
691	    t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
692	    execute(t->t_dcar, wanttty, NULL, NULL);
693	    /*
694	     * In strange case of A&B make a new job after A
695	     */
696	    if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr &&
697		(t->t_dcdr->t_dflg & F_AMPERSAND) == 0)
698		pendjob();
699	}
700	if (t->t_dcdr) {
701	    t->t_dcdr->t_dflg |= t->t_dflg &
702		(F_NOFORK | F_NOINTERRUPT);
703	    execute(t->t_dcdr, wanttty, NULL, NULL);
704	}
705	break;
706
707    case NODE_OR:
708    case NODE_AND:
709	if (t->t_dcar) {
710	    t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
711	    execute(t->t_dcar, wanttty, NULL, NULL);
712	    if ((getn(varval(STRstatus)) == 0) !=
713		(t->t_dtyp == NODE_AND)) {
714		return;
715	    }
716	}
717	if (t->t_dcdr) {
718	    t->t_dcdr->t_dflg |= t->t_dflg &
719		(F_NOFORK | F_NOINTERRUPT);
720	    execute(t->t_dcdr, wanttty, NULL, NULL);
721	}
722	break;
723
724    default:
725	break;
726    }
727    /*
728     * Fall through for all breaks from switch
729     *
730     * If there will be no more executions of this command, flush all file
731     * descriptors. Places that turn on the F_REPEAT bit are responsible for
732     * doing donefds after the last re-execution
733     */
734    if (didfds && !(t->t_dflg & F_REPEAT))
735	donefds();
736}
737
738#ifdef VFORK
739static sigret_t
740/*ARGSUSED*/
741vffree(snum)
742int snum;
743{
744    register Char **v;
745
746    USE(snum);
747    if ((v = gargv) != 0) {
748	gargv = 0;
749	xfree((ptr_t) v);
750    }
751
752    if ((v = pargv) != 0) {
753	pargv = 0;
754	xfree((ptr_t) v);
755    }
756
757    _exit(1);
758#ifndef SIGVOID
759    /*NOTREACHED*/
760    return(0);
761#endif /* SIGVOID */
762}
763#endif /* VFORK */
764
765/*
766 * Expand and glob the words after an i/o redirection.
767 * If more than one word is generated, then update the command vector.
768 *
769 * This is done differently in all the shells:
770 * 1. in the bourne shell and ksh globbing is not performed
771 * 2. Bash/csh say ambiguous
772 * 3. zsh does i/o to/from all the files
773 * 4. itcsh concatenates the words.
774 *
775 * I don't know what is best to do. I think that Ambiguous is better
776 * than restructuring the command vector, because the user can get
777 * unexpected results. In any case, the command vector restructuring
778 * code is present and the user can choose it by setting noambiguous
779 */
780static Char *
781splicepipe(t, cp)
782    register struct command *t;
783    Char *cp;	/* word after < or > */
784{
785    Char *blk[2];
786
787    if (adrof(STRnoambiguous)) {
788	Char **pv;
789
790	blk[0] = Dfix1(cp); /* expand $ */
791	blk[1] = NULL;
792
793	gflag = 0, tglob(blk);
794	if (gflag) {
795	    pv = globall(blk);
796	    if (pv == NULL) {
797		setname(short2str(blk[0]));
798		xfree((ptr_t) blk[0]);
799		stderror(ERR_NAME | ERR_NOMATCH);
800	    }
801	    gargv = NULL;
802	    if (pv[1] != NULL) { /* we need to fix the command vector */
803		Char **av = blkspl(t->t_dcom, &pv[1]);
804		xfree((ptr_t) t->t_dcom);
805		t->t_dcom = av;
806	    }
807	    xfree((ptr_t) blk[0]);
808	    blk[0] = pv[0];
809	    xfree((ptr_t) pv);
810	}
811    }
812    else {
813	Char buf[BUFSIZE];
814
815	(void) Strcpy(buf, blk[1] = Dfix1(cp));
816	xfree((ptr_t) blk[1]);
817	blk[0] = globone(buf, G_ERROR);
818    }
819    return(blk[0]);
820}
821
822/*
823 * Perform io redirection.
824 * We may or maynot be forked here.
825 */
826static void
827doio(t, pipein, pipeout)
828    register struct command *t;
829    int    *pipein, *pipeout;
830{
831    register int fd;
832    register Char *cp;
833    register unsigned long flags = t->t_dflg;
834
835    if (didfds || (flags & F_REPEAT))
836	return;
837    if ((flags & F_READ) == 0) {/* F_READ already done */
838	if (t->t_dlef) {
839	    char    tmp[MAXPATHLEN+1];
840
841	    /*
842	     * so < /dev/std{in,out,err} work
843	     */
844	    (void) dcopy(SHIN, 0);
845	    (void) dcopy(SHOUT, 1);
846	    (void) dcopy(SHDIAG, 2);
847	    cp = splicepipe(t, t->t_dlef);
848	    (void) strncpy(tmp, short2str(cp), MAXPATHLEN);
849	    tmp[MAXPATHLEN] = '\0';
850	    xfree((ptr_t) cp);
851	    if ((fd = open(tmp, O_RDONLY)) < 0)
852		stderror(ERR_SYSTEM, tmp, strerror(errno));
853#ifdef O_LARGEFILE
854	    /* allow input files larger than 2Gb  */
855	    (void) fcntl(fd, O_LARGEFILE, 0);
856#endif /* O_LARGEFILE */
857	    (void) dmove(fd, 0);
858	}
859	else if (flags & F_PIPEIN) {
860	    (void) close(0);
861	    (void) dup(pipein[0]);
862	    (void) close(pipein[0]);
863	    (void) close(pipein[1]);
864	}
865	else if ((flags & F_NOINTERRUPT) && tpgrp == -1) {
866	    (void) close(0);
867	    (void) open(_PATH_DEVNULL, O_RDONLY);
868	}
869	else {
870	    (void) close(0);
871	    (void) dup(OLDSTD);
872#if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS)
873	    /*
874	     * PWP: Unlike Bezerkeley 4.3, FIONCLEX for Pyramid is preserved
875	     * across dup()s, so we have to UNSET it here or else we get a
876	     * command with NO stdin, stdout, or stderr at all (a bad thing
877	     * indeed)
878	     */
879	    (void) close_on_exec(0, 0);
880#endif /* CLOSE_ON_EXEC && CLEX_DUPS */
881	}
882    }
883    if (t->t_drit) {
884	char    tmp[MAXPATHLEN+1];
885
886	cp = splicepipe(t, t->t_drit);
887	(void) strncpy(tmp, short2str(cp), MAXPATHLEN);
888	tmp[MAXPATHLEN] = '\0';
889	xfree((ptr_t) cp);
890	/*
891	 * so > /dev/std{out,err} work
892	 */
893	(void) dcopy(SHOUT, 1);
894	(void) dcopy(SHDIAG, 2);
895	if ((flags & F_APPEND) != 0) {
896#ifdef O_APPEND
897	    fd = open(tmp, O_WRONLY | O_APPEND);
898#else /* !O_APPEND */
899	    fd = open(tmp, O_WRONLY);
900	    (void) lseek(fd, (off_t) 0, L_XTND);
901#endif /* O_APPEND */
902	}
903	else
904	    fd = 0;
905	if ((flags & F_APPEND) == 0 || fd == -1) {
906	    if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) {
907		if (flags & F_APPEND)
908		    stderror(ERR_SYSTEM, tmp, strerror(errno));
909		chkclob(tmp);
910	    }
911	    if ((fd = creat(tmp, 0666)) < 0)
912		stderror(ERR_SYSTEM, tmp, strerror(errno));
913#ifdef O_LARGEFILE
914	    /* allow input files larger than 2Gb  */
915	    (void) fcntl(fd, O_LARGEFILE, 0);
916#endif /* O_LARGEFILE */
917	}
918	(void) dmove(fd, 1);
919	is1atty = isatty(1);
920    }
921    else if (flags & F_PIPEOUT) {
922	(void) close(1);
923	(void) dup(pipeout[1]);
924	is1atty = 0;
925    }
926    else {
927	(void) close(1);
928	(void) dup(SHOUT);
929	is1atty = isoutatty;
930# if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS)
931	(void) close_on_exec(1, 0);
932# endif /* CLOSE_ON_EXEC && CLEX_DUPS */
933    }
934
935    (void) close(2);
936    if (flags & F_STDERR) {
937	(void) dup(1);
938	is2atty = is1atty;
939    }
940    else {
941	(void) dup(SHDIAG);
942	is2atty = isdiagatty;
943# if defined(CLOSE_ON_EXEC) && defined(CLEX_DUPS)
944	(void) close_on_exec(2, 0);
945# endif /* CLOSE_ON_EXEC && CLEX_DUPS */
946    }
947    didfds = 1;
948}
949
950void
951mypipe(pv)
952    register int *pv;
953{
954
955    if (pipe(pv) < 0)
956	goto oops;
957    pv[0] = dmove(pv[0], -1);
958    pv[1] = dmove(pv[1], -1);
959    if (pv[0] >= 0 && pv[1] >= 0)
960	return;
961oops:
962    stderror(ERR_PIPE);
963}
964
965static void
966chkclob(cp)
967    register char *cp;
968{
969    struct stat stb;
970
971    if (stat(cp, &stb) < 0)
972	return;
973    if (S_ISCHR(stb.st_mode))
974	return;
975    stderror(ERR_EXISTS, cp);
976}
977