sh.sem.c revision 69408
177696Sbrian/* $Header: /src/pub/tcsh/sh.sem.c,v 3.51 2000/11/11 23:03:38 christos Exp $ */
236321Samurai/*
377696Sbrian * sh.sem.c: I/O redirections and job forking. A touchy issue!
477696Sbrian *	     Most stuff with builtins is incorrect
536321Samurai */
677696Sbrian/*-
777696Sbrian * Copyright (c) 1980, 1991 The Regents of the University of California.
877696Sbrian * All rights reserved.
977696Sbrian *
1077696Sbrian * Redistribution and use in source and binary forms, with or without
1177696Sbrian * modification, are permitted provided that the following conditions
1277696Sbrian * are met:
1377696Sbrian * 1. Redistributions of source code must retain the above copyright
1436321Samurai *    notice, this list of conditions and the following disclaimer.
1577696Sbrian * 2. Redistributions in binary form must reproduce the above copyright
1677696Sbrian *    notice, this list of conditions and the following disclaimer in the
1777696Sbrian *    documentation and/or other materials provided with the distribution.
1877696Sbrian * 3. All advertising materials mentioning features or use of this software
1977696Sbrian *    must display the following acknowledgement:
2077696Sbrian *	This product includes software developed by the University of
2177696Sbrian *	California, Berkeley and its contributors.
2277696Sbrian * 4. Neither the name of the University nor the names of its contributors
2377696Sbrian *    may be used to endorse or promote products derived from this software
2477696Sbrian *    without specific prior written permission.
2577696Sbrian *
2636321Samurai * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2799207Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2836321Samurai * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2936321Samurai * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3084195Sdillon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3184195Sdillon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3284195Sdillon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3384195Sdillon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3436321Samurai * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3536321Samurai * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3636321Samurai * SUCH DAMAGE.
3736321Samurai */
3836321Samurai#include "sh.h"
3936321Samurai
4036321SamuraiRCSID("$Id: sh.sem.c,v 3.51 2000/11/11 23:03:38 christos Exp $")
4136321Samurai
4236321Samurai#include "tc.h"
4336321Samurai#include "tw.h"
44145921Sglebius#ifdef WINNT_NATIVE
45145921Sglebius#include "nt.const.h"
46162674Spiso#endif /*WINNT_NATIVE*/
47162674Spiso
48162674Spiso#ifdef CLOSE_ON_EXEC
49145921Sglebius# ifndef SUNOS4
50162674Spiso#  ifndef CLEX_DUPS
51145921Sglebius#   define CLEX_DUPS
5299207Sbrian#  endif /* CLEX_DUPS */
53187304Spiso# endif /* !SUNOS4 */
54145921Sglebius#endif /* CLOSE_ON_EXEC */
55145921Sglebius
5636321Samurai#if defined(__sparc__) || defined(sparc)
5736321Samurai# if !defined(MACH) && SYSVREL == 0 && !defined(Lynx) && !defined(BSD4_4) && !defined(linux)
5836321Samurai#  include <vfork.h>
5936321Samurai# endif /* !MACH && SYSVREL == 0 && !Lynx && !BSD4_4 && !linux */
6036321Samurai#endif /* __sparc__ || sparc */
61145921Sglebius
62145921Sglebius#ifdef VFORK
63162674Spisostatic	sigret_t	vffree	__P((int));
64145921Sglebius#endif
6536321Samuraistatic	Char		*splicepipe	__P((struct command *, Char *));
66162674Spisostatic	void		 doio		__P((struct command *, int *, int *));
67145921Sglebiusstatic	void		 chkclob	__P((char *));
6836321Samurai
69162674Spiso/*
70162674Spiso * C shell
71162674Spiso */
72162674Spiso
73162674Spiso/*
74162674Spiso * For SVR4, there are problems with pipelines having the first process as
75162674Spiso * the group leader.  The problem occurs when the first process exits before
76162674Spiso * the others have a chance to setpgid().  This is because in SVR4 you can't
77162674Spiso * have a zombie as a group leader.  The solution I have used is to reverse
78162674Spiso * the order in which pipelines are started, making the last process the
79162674Spiso * group leader.  (Note I am not using 'pipeline' in the generic sense -- I
80162674Spiso * mean processes connected by '|'.)  I don't know yet if this causes other
81162674Spiso * problems.
82162674Spiso *
83162674Spiso * All the changes for this are in execute(), and are enclosed in
84162674Spiso * '#ifdef BACKPIPE'
85162674Spiso *
86162674Spiso * David Dawes (dawes@physics.su.oz.au) Oct 1991
87162674Spiso */
88162674Spiso
89162674Spiso/*VARARGS 1*/
90162674Spisovoid
91162674Spisoexecute(t, wanttty, pipein, pipeout)
92162674Spiso    register struct command *t;
93162674Spiso    int     wanttty;
94162674Spiso    int *pipein, *pipeout;
95162674Spiso{
96162674Spiso#ifdef VFORK
97162674Spiso    extern bool use_fork;	/* use fork() instead of vfork()? */
98162674Spiso#endif
99162674Spiso
100162674Spiso    bool    forked = 0;
101162674Spiso    struct biltins *bifunc;
102162674Spiso    int     pid = 0;
103162674Spiso    int     pv[2];
104162674Spiso#ifdef BSDSIGS
105162674Spiso    static sigmask_t csigmask;
106162674Spiso#endif /* BSDSIGS */
107162674Spiso#ifdef VFORK
108162674Spiso    static int onosigchld = 0;
109162674Spiso#endif /* VFORK */
110162674Spiso    static int nosigchld = 0;
111162674Spiso
112162674Spiso    (void) &wanttty;
113162674Spiso    (void) &forked;
114162674Spiso    (void) &bifunc;
115162674Spiso
116162674Spiso    if (t == 0)
117162674Spiso	return;
118162674Spiso
119162674Spiso#ifdef WINNT_NATIVE
120162674Spiso    {
121162674Spiso        if ((varval(STRNTslowexec) == STRNULL) &&
122162674Spiso            !t->t_dcdr && !t->t_dcar && !t->t_dflg && !didfds &&
123162674Spiso            (intty || intact) && (t->t_dtyp == NODE_COMMAND) &&
124162674Spiso	    !isbfunc(t)) {
125162674Spiso	    if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE)
126162674Spiso		(void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
127162674Spiso	    Dfix(t);
128162674Spiso            if (nt_try_fast_exec(t) == 0)
129162674Spiso                return;
130162674Spiso        }
131162674Spiso    }
132162674Spiso#endif /* WINNT_NATIVE */
133162674Spiso
134162674Spiso    /*
135162674Spiso     * Ed hutchins@sgi.com & Dominic dbg@sgi.com
136162674Spiso     * Sat Feb 25 03:13:11 PST 1995
137162674Spiso     * try implicit cd if we have a 1 word command
138162674Spiso     */
139162674Spiso    if (implicit_cd && (intty || intact) && t->t_dcom && t->t_dcom[0] &&
140162674Spiso	 t->t_dcom[0][0] && (blklen(t->t_dcom) == 1) && !noexec) {
141162674Spiso	Char sCName[MAXPATHLEN];
142162674Spiso	Char *pCN;
143162674Spiso	struct stat stbuf;
144162674Spiso	char *pathname;
145162674Spiso
146162674Spiso	dollar(sCName, t->t_dcom[0]);
147162674Spiso	pCN = sCName;
148162674Spiso	if (pCN[0] == '~') {
149162674Spiso	    Char sCPath[MAXPATHLEN];
150162674Spiso	    Char *pCP = sCPath;
151162674Spiso
152162674Spiso	    ++pCN;
153162674Spiso	    while (*pCN && *pCN != '/')
154162674Spiso		*pCP++ = *pCN++;
155162674Spiso	    *pCP = 0;
156162674Spiso	    if (sCPath[0])
157162674Spiso		gethdir(sCPath);
158162674Spiso	    else
159162674Spiso		(void) Strcpy(sCPath, varval(STRhome));
160162674Spiso	    catn(sCPath, pCN, MAXPATHLEN);
161162674Spiso	    (void) Strcpy(sCName, sCPath);
162162674Spiso	}
163162674Spiso
164162674Spiso	pathname = short2str(sCName);
165162674Spiso	/* if this is a dir, tack a "cd" on as the first arg */
166162674Spiso	if ((stat(pathname, &stbuf) != -1 && S_ISDIR(stbuf.st_mode))
167162674Spiso#ifdef WINNT_NATIVE
168162674Spiso	    || (pathname[0] && pathname[1] == ':' && pathname[2] == '\0')
169162674Spiso#endif /* WINNT_NATIVE */
170162674Spiso	) {
171162674Spiso	    Char *vCD[2];
172162674Spiso	    Char **ot_dcom = t->t_dcom;
173162674Spiso
174162674Spiso	    vCD[0] = Strsave(STRcd);
175162674Spiso	    vCD[1] = NULL;
176162674Spiso	    t->t_dcom = blkspl(vCD, ot_dcom);
177162674Spiso	    if (implicit_cd > 1) {
178162674Spiso		blkpr(t->t_dcom);
179162674Spiso		xputchar( '\n' );
180162674Spiso	    }
181162674Spiso	    xfree((ptr_t) ot_dcom);
182162674Spiso	}
183162674Spiso    }
184162674Spiso
185162674Spiso    /*
186162674Spiso     * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
187162674Spiso     * Don't check for wantty > 0...
188162674Spiso     */
189162674Spiso    if (t->t_dflg & F_AMPERSAND)
19036321Samurai	wanttty = 0;
191127094Sdes    switch (t->t_dtyp) {
192127094Sdes
193127094Sdes    case NODE_COMMAND:
194127094Sdes	if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE)
195127094Sdes	    (void) Strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
196127094Sdes	if ((t->t_dflg & F_REPEAT) == 0)
19736321Samurai	    Dfix(t);		/* $ " ' \ */
19836321Samurai	if (t->t_dcom[0] == 0) {
199127094Sdes	    return;
200127094Sdes	}
201127094Sdes	/*FALLTHROUGH*/
202127094Sdes
203127094Sdes    case NODE_PAREN:
204127094Sdes#ifdef BACKPIPE
205127094Sdes	if (t->t_dflg & F_PIPEIN)
206127094Sdes	    mypipe(pipein);
20736321Samurai#else /* !BACKPIPE */
20836321Samurai	if (t->t_dflg & F_PIPEOUT)
20936321Samurai	    mypipe(pipeout);
21036321Samurai#endif /* BACKPIPE */
21136321Samurai	/*
21236321Samurai	 * Must do << early so parent will know where input pointer should be.
21336321Samurai	 * If noexec then this is all we do.
21436321Samurai	 */
215127094Sdes	if (t->t_dflg & F_READ) {
216127094Sdes	    (void) close(0);
217127094Sdes	    heredoc(t->t_dlef);
218127094Sdes	    if (noexec)
219127094Sdes		(void) close(0);
220127094Sdes	}
221127094Sdes
22236321Samurai	set(STRstatus, Strsave(STR0), VAR_READWRITE);
22336321Samurai
22436321Samurai	/*
22536321Samurai	 * This mess is the necessary kludge to handle the prefix builtins:
22636321Samurai	 * nice, nohup, time.  These commands can also be used by themselves,
22736321Samurai	 * and this is not handled here. This will also work when loops are
22836321Samurai	 * parsed.
22936321Samurai	 */
23036321Samurai	while (t->t_dtyp == NODE_COMMAND)
231145961Sglebius	    if (eq(t->t_dcom[0], STRnice)) {
232127094Sdes		if (t->t_dcom[1]) {
233127094Sdes		    if (strchr("+-", t->t_dcom[1][0])) {
234127094Sdes			if (t->t_dcom[2]) {
23536321Samurai			    setname("nice");
23636321Samurai			    t->t_nice =
23736321Samurai				getn(t->t_dcom[1]);
238127094Sdes			    lshift(t->t_dcom, 2);
239127094Sdes			    t->t_dflg |= F_NICE;
240127094Sdes			}
241127094Sdes			else
242127094Sdes			    break;
243127094Sdes		    }
244127094Sdes		    else {
245127094Sdes			t->t_nice = 4;
246127094Sdes			lshift(t->t_dcom, 1);
247127094Sdes			t->t_dflg |= F_NICE;
248127094Sdes		    }
249127094Sdes		}
250127094Sdes		else
25136321Samurai		    break;
25299207Sbrian	    }
25336321Samurai	    else if (eq(t->t_dcom[0], STRnohup)) {
254127094Sdes		if (t->t_dcom[1]) {
25544616Sbrian		    t->t_dflg |= F_NOHUP;
25636321Samurai		    lshift(t->t_dcom, 1);
25736321Samurai		}
25836321Samurai		else
259127094Sdes		    break;
260127094Sdes	    }
261127094Sdes	    else if (eq(t->t_dcom[0], STRhup)) {
26236321Samurai		if (t->t_dcom[1]) {
26336321Samurai		    t->t_dflg |= F_HUP;
26436321Samurai		    lshift(t->t_dcom, 1);
265127094Sdes		}
26636321Samurai		else
26736321Samurai		    break;
26841759Sdillon	    }
26941759Sdillon	    else if (eq(t->t_dcom[0], STRtime)) {
270127094Sdes		if (t->t_dcom[1]) {
27141759Sdillon		    t->t_dflg |= F_TIME;
272127094Sdes		    lshift(t->t_dcom, 1);
27336321Samurai		}
27441759Sdillon		else
275127094Sdes		    break;
276127094Sdes	    }
27736321Samurai#ifdef F_VER
278127094Sdes	    else if (eq(t->t_dcom[0], STRver))
27936321Samurai		if (t->t_dcom[1] && t->t_dcom[2]) {
280127094Sdes		    setname("ver");
28136321Samurai		    t->t_systype = getv(t->t_dcom[1]);
28236321Samurai		    lshift(t->t_dcom, 2);
28336321Samurai		    t->t_dflg |= F_VER;
28499207Sbrian		}
285127094Sdes		else
286127094Sdes		    break;
28741759Sdillon#endif  /* F_VER */
28841759Sdillon	    else
28941759Sdillon		break;
29041759Sdillon
291145961Sglebius	/* is it a command */
29236321Samurai	if (t->t_dtyp == NODE_COMMAND) {
29336321Samurai	    /*
29436321Samurai	     * Check if we have a builtin function and remember which one.
295127094Sdes	     */
296127094Sdes	    bifunc = isbfunc(t);
297145961Sglebius 	    if (noexec && bifunc) {
298127094Sdes		/*
299127094Sdes		 * Continue for builtins that are part of the scripting language
30036321Samurai		 */
301127094Sdes		if (bifunc->bfunct != (bfunc_t)dobreak	&&
30236321Samurai		    bifunc->bfunct != (bfunc_t)docontin	&&
303127094Sdes		    bifunc->bfunct != (bfunc_t)doelse	&&
30436321Samurai		    bifunc->bfunct != (bfunc_t)doend	&&
305145961Sglebius		    bifunc->bfunct != (bfunc_t)doforeach&&
30636321Samurai		    bifunc->bfunct != (bfunc_t)dogoto	&&
30736321Samurai		    bifunc->bfunct != (bfunc_t)doif	&&
30836321Samurai		    bifunc->bfunct != (bfunc_t)dorepeat	&&
30936321Samurai		    bifunc->bfunct != (bfunc_t)doswbrk	&&
31036321Samurai		    bifunc->bfunct != (bfunc_t)doswitch	&&
311145961Sglebius		    bifunc->bfunct != (bfunc_t)dowhile	&&
31236321Samurai		    bifunc->bfunct != (bfunc_t)dozip)
313145928Sglebius		    break;
31436321Samurai	    }
315127094Sdes	}
31636321Samurai	else {			/* not a command */
31736321Samurai	    bifunc = NULL;
31841759Sdillon	    if (noexec)
319127094Sdes		break;
32041759Sdillon	}
321127094Sdes
322127094Sdes	/*
32336321Samurai	 * We fork only if we are timed, or are not the end of a parenthesized
32436321Samurai	 * list and not a simple builtin function. Simple meaning one that is
32599207Sbrian	 * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not
32636321Samurai	 * fork in some of these cases.
32736321Samurai	 */
32836321Samurai	/*
32936321Samurai	 * Prevent forking cd, pushd, popd, chdir cause this will cause the
33036321Samurai	 * shell not to change dir!
33136321Samurai	 */
33236321Samurai#ifdef BACKPIPE
33336321Samurai	/*
33436321Samurai	 * Can't have NOFORK for the tail of a pipe - because it is not the
33536321Samurai	 * last command spawned (even if it is at the end of a parenthesised
336162674Spiso	 * list).
337127094Sdes	 */
338127094Sdes	if (t->t_dflg & F_PIPEIN)
339127094Sdes	    t->t_dflg &= ~(F_NOFORK);
340131614Sdes#endif /* BACKPIPE */
341127094Sdes	if (bifunc && (bifunc->bfunct == (bfunc_t)dochngd ||
342127094Sdes		       bifunc->bfunct == (bfunc_t)dopushd ||
343127094Sdes		       bifunc->bfunct == (bfunc_t)dopopd))
344127094Sdes	    t->t_dflg &= ~(F_NICE);
345127094Sdes	if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 &&
346127094Sdes	     (!bifunc || t->t_dflg &
347127094Sdes	      (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP | F_HUP)))) ||
348127094Sdes	/*
34999207Sbrian	 * We have to fork for eval too.
350131614Sdes	 */
351131614Sdes	    (bifunc && (t->t_dflg & F_PIPEIN) != 0 &&
352131614Sdes	     bifunc->bfunct == (bfunc_t)doeval)) {
353127094Sdes#ifdef VFORK
354131699Sdes	    if (t->t_dtyp == NODE_PAREN ||
355127094Sdes		t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc)
35641759Sdillon#endif /* VFORK */
357131699Sdes	    {
358127094Sdes		forked++;
359127094Sdes		/*
360145961Sglebius		 * We need to block SIGCHLD here, so that if the process does
361127094Sdes		 * not die before we can set the process group
36236321Samurai		 */
363127094Sdes		if (wanttty >= 0 && !nosigchld) {
364127094Sdes#ifdef BSDSIGS
365127094Sdes		    csigmask = sigblock(sigmask(SIGCHLD));
366127094Sdes#else /* !BSDSIGS */
367127094Sdes		    (void) sighold(SIGCHLD);
368127094Sdes#endif /* BSDSIGS */
369127094Sdes
370127094Sdes		    nosigchld = 1;
371127094Sdes		}
372127094Sdes
373127094Sdes		pid = pfork(t, wanttty);
374127094Sdes		if (pid == 0 && nosigchld) {
375127094Sdes#ifdef BSDSIGS
376127094Sdes		    (void) sigsetmask(csigmask);
377127094Sdes#else /* !BSDSIGS */
378127094Sdes		    (void) sigrelse(SIGCHLD);
379127094Sdes#endif /* BSDSIGS */
38036321Samurai		    nosigchld = 0;
381127094Sdes		}
382127094Sdes		else if (pid != 0 && (t->t_dflg & F_AMPERSAND))
383145961Sglebius		    backpid = pid;
384127094Sdes	    }
38536321Samurai
386108533Sschweikh#ifdef VFORK
387127094Sdes	    else {
388127094Sdes		int     ochild, osetintr, ohaderr, odidfds;
389127094Sdes		int     oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp;
390127094Sdes		int     oisoutatty, oisdiagatty;
391127094Sdes
39236321Samurai# ifndef CLOSE_ON_EXEC
393127094Sdes		int     odidcch;
39436321Samurai# endif  /* !CLOSE_ON_EXEC */
39536321Samurai# ifdef BSDSIGS
39636321Samurai		sigmask_t omask, ocsigmask;
39736321Samurai# endif /* BSDSIGS */
39836321Samurai
39974778Sbrian		/*
40036321Samurai		 * Prepare for the vfork by saving everything that the child
401127094Sdes		 * corrupts before it exec's. Note that in some signal
402127094Sdes		 * implementations which keep the signal info in user space
403145961Sglebius		 * (e.g. Sun's) it will also be necessary to save and restore
404127094Sdes		 * the current sigvec's for the signals the child touches
40536321Samurai		 * before it exec's.
40636321Samurai		 */
407127094Sdes
40836321Samurai		/*
409127094Sdes		 * Sooooo true... If this is a Sun, save the sigvec's. (Skip
41036321Samurai		 * Gilbrech - 11/22/87)
41136321Samurai		 */
41236321Samurai# ifdef SAVESIGVEC
41336321Samurai		sigvec_t savesv[NSIGSAVED];
41436321Samurai		sigmask_t savesm;
415127094Sdes
416127094Sdes# endif /* SAVESIGVEC */
417127094Sdes		if (wanttty >= 0 && !nosigchld && !noexec) {
41836321Samurai# ifdef BSDSIGS
419127094Sdes		    csigmask = sigblock(sigmask(SIGCHLD));
42041759Sdillon# else /* !BSDSIGS */
42141759Sdillon		    (void) sighold(SIGCHLD);
422127094Sdes# endif  /* BSDSIGS */
42341759Sdillon		    nosigchld = 1;
424127094Sdes		}
42536321Samurai# ifdef BSDSIGS
42636321Samurai		omask = sigblock(sigmask(SIGCHLD)|sigmask(SIGINT));
427131614Sdes# else /* !BSDSIGS */
428131614Sdes		(void) sighold(SIGCHLD);
429127094Sdes		(void) sighold(SIGINT);
43036321Samurai# endif  /* BSDSIGS */
431127094Sdes		ochild = child;
43236321Samurai		osetintr = setintr;
43341759Sdillon		ohaderr = haderr;
43441759Sdillon		odidfds = didfds;
43541759Sdillon# ifndef CLOSE_ON_EXEC
43641759Sdillon		odidcch = didcch;
43736321Samurai# endif /* !CLOSE_ON_EXEC */
438127094Sdes		oSHIN = SHIN;
439127094Sdes		oSHOUT = SHOUT;
440127094Sdes		oSHDIAG = SHDIAG;
441127094Sdes		oOLDSTD = OLDSTD;
44236321Samurai		otpgrp = tpgrp;
443127094Sdes		oisoutatty = isoutatty;
444145961Sglebius		oisdiagatty = isdiagatty;
445127094Sdes# ifdef BSDSIGS
44644616Sbrian		ocsigmask = csigmask;
44736321Samurai# endif /* BSDSIGS */
44836321Samurai		onosigchld = nosigchld;
44936321Samurai		Vsav = Vdp = 0;
45036321Samurai		Vexpath = 0;
45136321Samurai		Vt = 0;
45236321Samurai# ifdef SAVESIGVEC
453127094Sdes		savesm = savesigvec(savesv);
45436321Samurai# endif /* SAVESIGVEC */
45536321Samurai		if (use_fork)
45636321Samurai		    pid = fork();
45736321Samurai		else
45836321Samurai		    pid = vfork();
45936321Samurai
46036321Samurai		if (pid < 0) {
46136321Samurai# ifdef BSDSIGS
46236321Samurai#  ifdef SAVESIGVEC
46336321Samurai		    restoresigvec(savesv, savesm);
46436321Samurai#  endif /* SAVESIGVEC */
465127094Sdes		    (void) sigsetmask(omask);
466127094Sdes# else /* !BSDSIGS */
467127094Sdes		    (void) sigrelse(SIGCHLD);
468127094Sdes		    (void) sigrelse(SIGINT);
469127094Sdes# endif  /* BSDSIGS */
47036321Samurai		    stderror(ERR_NOPROC);
47136321Samurai		}
47236321Samurai		forked++;
473127094Sdes		if (pid) {	/* parent */
474127094Sdes# ifdef SAVESIGVEC
475127094Sdes		    restoresigvec(savesv, savesm);
47636321Samurai# endif /* SAVESIGVEC */
477127094Sdes		    child = ochild;
47899207Sbrian		    setintr = osetintr;
479127094Sdes		    haderr = ohaderr;
48099207Sbrian		    didfds = odidfds;
481127094Sdes		    SHIN = oSHIN;
48236321Samurai# ifndef CLOSE_ON_EXEC
483127094Sdes		    didcch = odidcch;
48436321Samurai# endif /* !CLOSE_ON_EXEC */
48536321Samurai		    SHOUT = oSHOUT;
48641759Sdillon		    SHDIAG = oSHDIAG;
487127094Sdes		    OLDSTD = oOLDSTD;
48836321Samurai		    tpgrp = otpgrp;
48936321Samurai		    isoutatty = oisoutatty;
49036321Samurai		    isdiagatty = oisdiagatty;
49136321Samurai# ifdef BSDSIGS
492127094Sdes		    csigmask = ocsigmask;
49336321Samurai# endif /* BSDSIGS */
49436321Samurai		    nosigchld = onosigchld;
495145961Sglebius
49636321Samurai		    xfree((ptr_t) Vsav);
497127094Sdes		    Vsav = 0;
49836321Samurai		    xfree((ptr_t) Vdp);
499127094Sdes		    Vdp = 0;
50041759Sdillon		    xfree((ptr_t) Vexpath);
50141759Sdillon		    Vexpath = 0;
50241759Sdillon		    blkfree((Char **) Vt);
50341759Sdillon		    Vt = 0;
504145961Sglebius		    /* this is from pfork() */
505127094Sdes		    palloc(pid, t);
50636321Samurai# ifdef BSDSIGS
507127094Sdes		    (void) sigsetmask(omask);
508127094Sdes# else /* !BSDSIGS */
509127094Sdes		    (void) sigrelse(SIGCHLD);
510127094Sdes		    (void) sigrelse(SIGINT);
51136321Samurai# endif  /* BSDSIGS */
512127094Sdes		}
513127094Sdes		else {		/* child */
514127094Sdes		    /* this is from pfork() */
515127094Sdes		    int     pgrp;
516127094Sdes		    bool    ignint = 0;
517127094Sdes		    if (nosigchld) {
518127094Sdes# ifdef BSDSIGS
51936321Samurai			(void) sigsetmask(csigmask);
52036321Samurai# else /* !BSDSIGS */
521145961Sglebius			(void) sigrelse(SIGCHLD);
52236321Samurai# endif /* BSDSIGS */
52336321Samurai			nosigchld = 0;
52436321Samurai		    }
525145961Sglebius
526127094Sdes		    if (setintr)
52736321Samurai			ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
52836321Samurai				|| (gointr && eq(gointr, STRminus));
52936321Samurai		    pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
530127094Sdes		    child++;
531127094Sdes		    if (setintr) {
53236321Samurai			setintr = 0;
53341759Sdillon/*
53441759Sdillon * casts made right for SunOS 4.0 by Douglas C. Schmidt
53541759Sdillon * <schmidt%sunshine.ics.uci.edu@ROME.ICS.UCI.EDU>
536127094Sdes * (thanks! -- PWP)
53736321Samurai *
53836321Samurai * ignint ifs cleaned by Johan Widen <mcvax!osiris.sics.se!jw@uunet.UU.NET>
53936321Samurai * (thanks again)
54036321Samurai */
541127094Sdes			if (ignint) {
542127094Sdes			    (void) signal(SIGINT, SIG_IGN);
54336321Samurai			    (void) signal(SIGQUIT, SIG_IGN);
544127094Sdes			}
54599207Sbrian			else {
546127094Sdes			    (void) signal(SIGINT,  vffree);
54741759Sdillon			    (void) signal(SIGQUIT, SIG_DFL);
548127094Sdes			}
54936321Samurai# ifdef BSDJOBS
550127094Sdes			if (wanttty >= 0) {
55136321Samurai			    (void) signal(SIGTSTP, SIG_DFL);
55236321Samurai			    (void) signal(SIGTTIN, SIG_DFL);
55341759Sdillon			    (void) signal(SIGTTOU, SIG_DFL);
554127094Sdes			}
55541759Sdillon# endif /* BSDJOBS */
55636321Samurai
557127094Sdes			(void) signal(SIGTERM, parterm);
55836321Samurai		    }
55936321Samurai		    else if (tpgrp == -1 &&
56036321Samurai			     (t->t_dflg & F_NOINTERRUPT)) {
56136321Samurai			(void) signal(SIGINT, SIG_IGN);
56236321Samurai			(void) signal(SIGQUIT, SIG_IGN);
563145961Sglebius		    }
56436321Samurai
565127094Sdes		    pgetty(wanttty, pgrp);
56636321Samurai
567127094Sdes		    if (t->t_dflg & F_NOHUP)
56841759Sdillon			(void) signal(SIGHUP, SIG_IGN);
569127094Sdes		    if (t->t_dflg & F_HUP)
570145961Sglebius			(void) signal(SIGHUP, SIG_DFL);
571127094Sdes		    if (t->t_dflg & F_NICE) {
57236321Samurai			int nval = SIGN_EXTEND_CHAR(t->t_nice);
573127094Sdes# ifdef BSDNICE
574127094Sdes			(void) setpriority(PRIO_PROCESS, 0, nval);
575127094Sdes# else /* !BSDNICE */
576127094Sdes			(void) nice(nval);
57736321Samurai# endif /* BSDNICE */
578127094Sdes		    }
579127094Sdes# ifdef F_VER
580127094Sdes		    if (t->t_dflg & F_VER) {
581127094Sdes			tsetenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53);
582127094Sdes			dohash(NULL, NULL);
583127094Sdes		    }
584127094Sdes# endif /* F_VER */
58536321Samurai		}
58636321Samurai
58736321Samurai	    }
588127094Sdes#endif /* VFORK */
58936321Samurai	}
59036321Samurai	if (pid != 0) {
59141759Sdillon	    /*
592127094Sdes	     * It would be better if we could wait for the whole job when we
593127094Sdes	     * knew the last process had been started.  Pwait, in fact, does
59436321Samurai	     * wait for the whole job anyway, but this test doesn't really
59536321Samurai	     * express our intentions.
59636321Samurai	     */
597127094Sdes#ifdef BACKPIPE
598127094Sdes	    if (didfds == 0 && t->t_dflg & F_PIPEOUT) {
59936321Samurai		(void) close(pipeout[0]);
600127094Sdes		(void) close(pipeout[1]);
60199207Sbrian	    }
602127094Sdes	    if ((t->t_dflg & F_PIPEIN) != 0)
60341759Sdillon		break;
604127094Sdes#else /* !BACKPIPE */
60536321Samurai	    if (didfds == 0 && t->t_dflg & F_PIPEIN) {
606127094Sdes		(void) close(pipein[0]);
60736321Samurai		(void) close(pipein[1]);
60836321Samurai	    }
609131614Sdes	    if ((t->t_dflg & F_PIPEOUT) != 0)
610131614Sdes		break;
61141759Sdillon#endif /* BACKPIPE */
612127094Sdes
61341759Sdillon	    if (nosigchld) {
61436321Samurai#ifdef BSDSIGS
615127094Sdes		(void) sigsetmask(csigmask);
61636321Samurai#else /* !BSDSIGS */
61736321Samurai		(void) sigrelse(SIGCHLD);
61836321Samurai#endif /* BSDSIGS */
61936321Samurai		nosigchld = 0;
62036321Samurai	    }
621127094Sdes	    if ((t->t_dflg & F_AMPERSAND) == 0)
62241759Sdillon		pwait();
62341759Sdillon	    break;
62441759Sdillon	}
62541759Sdillon
62636321Samurai	doio(t, pipein, pipeout);
62736321Samurai#ifdef BACKPIPE
62836321Samurai	if (t->t_dflg & F_PIPEIN) {
62941759Sdillon	    (void) close(pipein[0]);
63041759Sdillon	    (void) close(pipein[1]);
63136321Samurai	}
632127094Sdes#else /* !BACKPIPE */
63336321Samurai	if (t->t_dflg & F_PIPEOUT) {
63436321Samurai	    (void) close(pipeout[0]);
635127094Sdes	    (void) close(pipeout[1]);
63699207Sbrian	}
637127094Sdes#endif /* BACKPIPE */
63841759Sdillon	/*
639127094Sdes	 * Perform a builtin function. If we are not forked, arrange for
64036321Samurai	 * possible stopping
641127094Sdes	 */
64236321Samurai	if (bifunc) {
64336321Samurai	    func(t, bifunc);
644131614Sdes	    if (forked)
645131614Sdes		exitstat();
64641759Sdillon	    break;
647127094Sdes	}
64841759Sdillon	if (t->t_dtyp != NODE_PAREN) {
64936321Samurai	    doexec(t);
650127094Sdes	    /* NOTREACHED */
65136321Samurai	}
65236321Samurai	/*
65336321Samurai	 * For () commands must put new 0,1,2 in FSH* and recurse
65436321Samurai	 */
65536321Samurai	OLDSTD = dcopy(0, FOLDSTD);
656127094Sdes	SHOUT = dcopy(1, FSHOUT);
65736321Samurai	isoutatty = isatty(SHOUT);
658127094Sdes	SHDIAG = dcopy(2, FSHDIAG);
659127094Sdes	isdiagatty = isatty(SHDIAG);
66041759Sdillon	(void) close(SHIN);
661127094Sdes	SHIN = -1;
66236321Samurai#ifndef CLOSE_ON_EXEC
66336321Samurai	didcch = 0;
66436321Samurai#endif /* !CLOSE_ON_EXEC */
665127094Sdes	didfds = 0;
666127094Sdes	wanttty = -1;
66736321Samurai	t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT;
668127094Sdes	execute(t->t_dspr, wanttty, NULL, NULL);
66941759Sdillon	exitstat();
670127094Sdes
67141759Sdillon    case NODE_PIPE:
672127094Sdes#ifdef BACKPIPE
67336321Samurai	t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg &
674127094Sdes			(F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT));
67536321Samurai	execute(t->t_dcdr, wanttty, pv, pipeout);
67636321Samurai	t->t_dcar->t_dflg |= F_PIPEOUT |
677131614Sdes	    (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT));
678131614Sdes	execute(t->t_dcar, wanttty, pipein, pv);
67941759Sdillon#else /* !BACKPIPE */
680127094Sdes	t->t_dcar->t_dflg |= F_PIPEOUT |
68141759Sdillon	    (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT));
68236321Samurai	execute(t->t_dcar, wanttty, pipein, pv);
683127094Sdes	t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg &
68436321Samurai			(F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT));
68536321Samurai	execute(t->t_dcdr, wanttty, pv, pipeout);
68636321Samurai#endif /* BACKPIPE */
68736321Samurai	break;
688127094Sdes
689127094Sdes    case NODE_LIST:
69041759Sdillon	if (t->t_dcar) {
691127094Sdes	    t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
69236321Samurai	    execute(t->t_dcar, wanttty, NULL, NULL);
69336321Samurai	    /*
694127094Sdes	     * In strange case of A&B make a new job after A
69541759Sdillon	     */
69699207Sbrian	    if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr &&
697127094Sdes		(t->t_dcdr->t_dflg & F_AMPERSAND) == 0)
69841759Sdillon		pendjob();
69999207Sbrian	}
700127094Sdes	if (t->t_dcdr) {
70136321Samurai	    t->t_dcdr->t_dflg |= t->t_dflg &
702127094Sdes		(F_NOFORK | F_NOINTERRUPT);
70336321Samurai	    execute(t->t_dcdr, wanttty, NULL, NULL);
704127094Sdes	}
70541759Sdillon	break;
70641759Sdillon
70741759Sdillon    case NODE_OR:
708145961Sglebius    case NODE_AND:
709127094Sdes	if (t->t_dcar) {
71036321Samurai	    t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT;
71136321Samurai	    execute(t->t_dcar, wanttty, NULL, NULL);
71236321Samurai	    if ((getn(varval(STRstatus)) == 0) !=
713127094Sdes		(t->t_dtyp == NODE_AND)) {
714127094Sdes		return;
715127094Sdes	    }
716127094Sdes	}
717127094Sdes	if (t->t_dcdr) {
718127094Sdes	    t->t_dcdr->t_dflg |= t->t_dflg &
719127094Sdes		(F_NOFORK | F_NOINTERRUPT);
720127094Sdes	    execute(t->t_dcdr, wanttty, NULL, NULL);
721127094Sdes	}
722127094Sdes	break;
723127094Sdes
724127094Sdes    default:
725127094Sdes	break;
726127094Sdes    }
727127094Sdes    /*
728127094Sdes     * Fall through for all breaks from switch
729127094Sdes     *
730127094Sdes     * If there will be no more executions of this command, flush all file
731127094Sdes     * descriptors. Places that turn on the F_REPEAT bit are responsible for
732127094Sdes     * doing donefds after the last re-execution
733127094Sdes     */
734127094Sdes    if (didfds && !(t->t_dflg & F_REPEAT))
735127094Sdes	donefds();
736127094Sdes}
737127094Sdes
738127094Sdes#ifdef VFORK
739127094Sdesstatic sigret_t
740127094Sdes/*ARGSUSED*/
741127094Sdesvffree(snum)
742127094Sdesint snum;
743127094Sdes{
744127094Sdes    register Char **v;
745127094Sdes
746127094Sdes    USE(snum);
747127094Sdes    if ((v = gargv) != 0) {
748127094Sdes	gargv = 0;
749127094Sdes	xfree((ptr_t) v);
750145961Sglebius    }
751127094Sdes
752127094Sdes    if ((v = pargv) != 0) {
753127094Sdes	pargv = 0;
754127094Sdes	xfree((ptr_t) v);
755145928Sglebius    }
75644616Sbrian
757127094Sdes    _exit(1);
75836321Samurai#ifndef SIGVOID
75936321Samurai    /*NOTREACHED*/
76036321Samurai    return(0);
761127094Sdes#endif /* SIGVOID */
76236321Samurai}
76336321Samurai#endif /* VFORK */
764162674Spiso
765127094Sdes/*
766127094Sdes * Expand and glob the words after an i/o redirection.
767127094Sdes * If more than one word is generated, then update the command vector.
768131614Sdes *
769127094Sdes * This is done differently in all the shells:
770127094Sdes * 1. in the bourne shell and ksh globbing is not performed
771127094Sdes * 2. Bash/csh say ambiguous
772127094Sdes * 3. zsh does i/o to/from all the files
77336321Samurai * 4. itcsh concatenates the words.
774127094Sdes *
775127094Sdes * I don't know what is best to do. I think that Ambiguous is better
776127094Sdes * than restructuring the command vector, because the user can get
777127094Sdes * unexpected results. In any case, the command vector restructuring
778127094Sdes * code is present and the user can choose it by setting noambiguous
77936321Samurai */
780131614Sdesstatic Char *
781131614Sdessplicepipe(t, cp)
782131614Sdes    register struct command *t;
78399207Sbrian    Char *cp;	/* word after < or > */
784127094Sdes{
785127094Sdes    Char *blk[2];
786127094Sdes
787127094Sdes    if (adrof(STRnoambiguous)) {
78836321Samurai	Char **pv;
789127094Sdes
790131699Sdes	blk[0] = Dfix1(cp); /* expand $ */
791127094Sdes	blk[1] = NULL;
792131699Sdes
793127094Sdes	gflag = 0, tglob(blk);
794127094Sdes	if (gflag) {
79536321Samurai	    pv = globall(blk);
796127094Sdes	    if (pv == NULL) {
797127094Sdes		setname(short2str(blk[0]));
79841759Sdillon		xfree((ptr_t) blk[0]);
799145961Sglebius		stderror(ERR_NAME | ERR_NOMATCH);
800127094Sdes	    }
801127094Sdes	    gargv = NULL;
802127094Sdes	    if (pv[1] != NULL) { /* we need to fix the command vector */
803127094Sdes		Char **av = blkspl(t->t_dcom, &pv[1]);
804127094Sdes		xfree((ptr_t) t->t_dcom);
805127094Sdes		t->t_dcom = av;
806127094Sdes	    }
807127094Sdes	    xfree((ptr_t) blk[0]);
808127094Sdes	    blk[0] = pv[0];
809127094Sdes	    xfree((ptr_t) pv);
810127094Sdes	}
811127094Sdes    }
812127094Sdes    else {
81336321Samurai	Char buf[BUFSIZE];
81436321Samurai
81536321Samurai	(void) Strcpy(buf, blk[1] = Dfix1(cp));
816127094Sdes	xfree((ptr_t) blk[1]);
817127094Sdes	blk[0] = globone(buf, G_ERROR);
818127094Sdes    }
819127094Sdes    return(blk[0]);
820127094Sdes}
821127094Sdes
822127094Sdes/*
82336321Samurai * Perform io redirection.
82436321Samurai * We may or maynot be forked here.
825127094Sdes */
826127094Sdesstatic void
827127094Sdesdoio(t, pipein, pipeout)
828127094Sdes    register struct command *t;
829127094Sdes    int    *pipein, *pipeout;
830127094Sdes{
831127094Sdes    register int fd;
83236321Samurai    register Char *cp;
83336321Samurai    register unsigned long flags = t->t_dflg;
834127094Sdes
835127094Sdes    if (didfds || (flags & F_REPEAT))
836127094Sdes	return;
837127094Sdes    if ((flags & F_READ) == 0) {/* F_READ already done */
838127094Sdes	if (t->t_dlef) {
839127094Sdes	    char    tmp[MAXPATHLEN+1];
840127094Sdes
84136321Samurai	    /*
84236321Samurai	     * so < /dev/std{in,out,err} work
843127094Sdes	     */
844127094Sdes	    (void) dcopy(SHIN, 0);
845127094Sdes	    (void) dcopy(SHOUT, 1);
846127094Sdes	    (void) dcopy(SHDIAG, 2);
847127094Sdes	    cp = splicepipe(t, t->t_dlef);
848127094Sdes	    (void) strncpy(tmp, short2str(cp), MAXPATHLEN);
849127094Sdes	    tmp[MAXPATHLEN] = '\0';
85036321Samurai	    xfree((ptr_t) cp);
851145961Sglebius	    if ((fd = open(tmp, O_RDONLY)) < 0)
852127094Sdes		stderror(ERR_SYSTEM, tmp, strerror(errno));
85336321Samurai#ifdef O_LARGEFILE
854127094Sdes	    /* allow input files larger than 2Gb  */
85536321Samurai	    (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