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