]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcsh/sh.sem.c
This commit was generated by cvs2svn to compensate for changes in r80260,
[FreeBSD/FreeBSD.git] / contrib / tcsh / sh.sem.c
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
40 RCSID("$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
63 static  sigret_t        vffree  __P((int));
64 #endif 
65 static  Char            *splicepipe     __P((struct command *, Char *));
66 static  void             doio           __P((struct command *, int *, int *));
67 static  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*/
90 void
91 execute(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
739 static sigret_t
740 /*ARGSUSED*/
741 vffree(snum)
742 int 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  */
780 static Char *
781 splicepipe(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  */
826 static void
827 doio(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
950 void
951 mypipe(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;
961 oops:
962     stderror(ERR_PIPE);
963 }
964
965 static void
966 chkclob(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 }