home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / tcsh / Source / sh.sem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  22.7 KB  |  911 lines

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