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