home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / csh / sh.sem.c < prev    next >
C/C++ Source or Header  |  1980-02-17  |  7KB  |  326 lines

  1. /* Copyright (c) 1979 Regents of the University of California */
  2. #include "sh.h"
  3.  
  4. /*
  5.  * C shell
  6.  */
  7.  
  8. execute(t, pipein, pipeout)
  9.     register struct command *t;
  10.     int *pipein, *pipeout;
  11. {
  12.     int pid, flags, pv[2];
  13.     register struct command *t1;
  14.     register char *cp;
  15.     bool forked = 0;
  16.     bool shudint;
  17.  
  18.     if (t == 0)
  19.         return;
  20.     switch (t->t_dtyp) {
  21.  
  22.     case TCOM:
  23.         cp = t->t_dcom[0];
  24.         if ((cp[0] & (QUOTE|TRIM)) == QUOTE)
  25.             strcpy(cp, cp + 1);
  26.         if ((t->t_dflg & FREDO) == 0)
  27.             Dfix(t);        /* $ " ' \ */
  28.         /* fall into... */
  29.  
  30.     case TPAR:
  31.         flags = t->t_dflg;
  32.         if (flags & FPOU)
  33.             mypipe(pipeout);
  34.         /*
  35.          * A child will be interruptible only under very
  36.          * certain conditions:
  37.          *    we must be monkeying with interrupts
  38.          *    the child must not be &'ed
  39.          *    we must not have had an "onintr -"
  40.          */
  41.         shudint = setintr && (flags & FINT) == 0 && (!gointr || !eq(gointr, "-"));
  42.  
  43.         /*
  44.          * Must do << early so parent will know
  45.          * where input pointer should be
  46.          */
  47.         if (flags & FHERE)
  48.             close(0), heredoc(t->t_dlef);
  49.  
  50.         /*
  51.          * If not executing commands then
  52.          * all we must do is read forward in the input to
  53.          * account for << redirection if present.
  54.          */
  55.         if (noexec) {
  56.             if (flags & FHERE)
  57.                 close(0);
  58.             return;
  59.         }
  60.  
  61.         set("status", "0");
  62.         pid = 0;
  63.  
  64.         /*
  65.          * Built-in functions
  66.          */
  67.         if (t->t_dtyp == TCOM && isbfunc(t->t_dcom[0])) {
  68.             /*
  69.              * If output is piped, or running & and we would
  70.              * eventually fork for non-builtin commands,
  71.              * then do it now, so we won't block.
  72.              */
  73.             if ((flags & (FPOU|FAND)) && (flags & FPAR) == 0)
  74.                 pid = dofork(shudint), forked++;
  75.  
  76.             /*
  77.              * If the builtin is actually executed (some, e.g.
  78.              * time and nice may refuse to execute here)
  79.              * then either exit (if we forked) or close i/o
  80.              * and continue execution (if we didn't).
  81.              */
  82.             if (pid == 0) {
  83.                 doio(t, pipein, pipeout);
  84.                 if (flags & FPOU) {
  85.                     close(pipeout[0]), close(pipeout[1]);
  86.                     pipeout[0] = pipeout[1] = -1;
  87.                 }
  88.                 if (setintr && forked) {
  89.                     if (shudint)
  90.                         signal(SIGINT, SIG_DFL), signal(SIGQUIT, SIG_DFL);
  91.                     signal(SIGTERM, parterm);
  92.                     if (flags & FINT)
  93.                         setintr = 0;
  94.                 }
  95.                 if (func(t, pipein, pipeout)) {
  96.                     if (forked)
  97.                         exitstat();
  98.                     if (didfds && !(t->t_dflg & FREDO))
  99.                         donefds();
  100.                     return;
  101.                 }
  102.             }
  103.         }
  104.  
  105.         /*
  106.          * Now, we must make a new process since either the
  107.          * command is non-builtin, a parenthesized list,
  108.          * or builtin such as time or nice which really
  109.          * requires a child.
  110.          */
  111.         if (!forked && (flags & FPAR) == 0)
  112.             pid = dofork(shudint);
  113.         if (pid != 0) {
  114.             /*
  115.              * The parent path (or nobody does this if
  116.              * (flags & FPAR), i.e. date in (set;date))
  117.              */
  118.             if (didfds == 0 && (flags & FPIN))
  119.                 close(pipein[0]), close(pipein[1]);
  120.             if (didfds && !(t->t_dflg & FREDO))
  121.                 donefds();
  122.             if (flags & FPRS)
  123.                 printf("%d\n", pid), set("child", putn(pid));
  124.             /*
  125.              * Unless output is piped or command is &
  126.              * wait for it.
  127.              */
  128.             if (t->t_dtyp == TCOM)
  129.                 cadd(pid, t->t_dcom[0]);
  130.             else
  131.                 cadd(pid, "()");
  132.             if ((flags & (FPOU|FAND)) == 0)
  133.                 pwait(pid);
  134.             return;
  135.         }
  136.  
  137.         /*
  138.          * Insure that this (child) shell doesn't muck on
  139.          */
  140.         child++;
  141.  
  142.         /*
  143.          * If havent yet, finally set up the file descriptors.
  144.          */
  145.         doio(t, pipein, pipeout);
  146.         if (flags & FPOU)
  147.             close(pipeout[0]), close(pipeout[1]);
  148.  
  149.         /*
  150.          * If mucking with interrupts fix interrupt, quit,
  151.          * and terminate handling ... in any case set setintr
  152.          * to 0 if we are not interruptible so that no further
  153.          * interrupt mucking occurs.
  154.          */
  155.         if (setintr) {
  156.             if (shudint)
  157.                 signal(SIGINT, SIG_DFL), signal(SIGQUIT, SIG_DFL);
  158.             signal(SIGTERM, parterm);
  159.             if (flags & FINT)
  160.                 setintr = 0;
  161.         }
  162.  
  163.         /*
  164.          * For () commands must put new 0,1,2 in FSH* and recurse
  165.          */
  166.         if (t->t_dtyp == TPAR) {
  167.             t1 = t->t_dspr;
  168.             t1->t_dflg |= flags & FINT;
  169.             OLDSTD = dcopy(0, FOLDSTD);
  170.             SHOUT = dcopy(1, FSHOUT);
  171.             SHDIAG = dcopy(2, FSHDIAG);
  172.             close(SHIN), SHIN = -1;
  173.             didcch = 0, didfds = 0;
  174.             execute(t1);
  175.             exitstat();
  176.         }
  177.         if (eq(t->t_dcom[0], "nice")) {
  178. /* sigh...
  179.             nice(20);
  180.             nice(-10);
  181. */
  182.             cp = t->t_dcom[1];
  183.             if (any(cp[0], "+-"))
  184.                 nice(getn(cp)), lshift(t->t_dcom, 2);
  185.             else
  186.                 nice(4), lshift(t->t_dcom, 1);
  187.             t->t_dflg = FPAR | FREDO;
  188.             execute(t);
  189.             exitstat();
  190.         }
  191.         if (eq(t->t_dcom[0], "nohup")) {
  192.             if (setintr == 0)
  193.                 signal(SIGHUP, SIG_IGN);
  194.             lshift(t->t_dcom, 1);
  195.             t->t_dflg = FPAR | FREDO;
  196.             execute(t);
  197.             exitstat();
  198.         }
  199.         doexec(t);
  200.         /* no return */
  201.  
  202.     case TFIL:
  203.         flags = t->t_dflg;
  204.         t1 = t->t_dcar;
  205.         t1->t_dflg |= FPOU | (flags & (FPIN|FINT|FPRS|FDIAG));
  206.         execute(t1, pipein, pv);
  207.         t1 = t->t_dcdr;
  208.         t1->t_dflg |= FPIN | (flags & (FPOU|FINT|FAND|FPRS|FPAR));
  209.         execute(t1, pv, pipeout);
  210.         return;
  211.  
  212.     case TLST:
  213.         flags = t->t_dflg & FINT;
  214.         if (t1 = t->t_dcar)
  215.             t1->t_dflg |= flags, execute(t1);
  216.         if (t1 = t->t_dcdr)
  217.             t1->t_dflg |= t->t_dflg & (FINT|FPAR), execute(t1);
  218.         return;
  219.  
  220.     case TOR:
  221.     case TAND:
  222.         flags = t->t_dflg & FINT;
  223.         if (t1 = t->t_dcar) {
  224.             t1->t_dflg |= flags, execute(t1);
  225.             if ((getn(value("status")) == 0) == (t->t_dtyp == TAND))
  226.                 return;
  227.         }
  228.         if (t1 = t->t_dcdr)
  229.             t1->t_dflg |= t->t_dflg & (FINT|FPAR), execute(t1);
  230.         return;
  231.     }
  232. }
  233.  
  234. doio(t, pipein, pipeout)
  235.     register struct command *t;
  236.     int *pipein, *pipeout;
  237. {
  238.     register char *cp;
  239.     register int flags = t->t_dflg;
  240.  
  241.     if (didfds || (flags & FREDO))
  242.         return;
  243.     if (flags & FHERE)
  244.         goto skipin;
  245.     close(0);
  246.     if (cp = t->t_dlef) {
  247.         cp = globone(Dfix1(cp));
  248.         xfree(cp);
  249.         if (open(cp, 0) < 0)
  250.             Perror(cp);
  251.     } else if (flags & FPIN)
  252.         dup(pipein[0]), close(pipein[0]), close(pipein[1]);
  253.     else if (flags & FINT)
  254.         close(0), open("/dev/null", 0);
  255.     else
  256.         dup(OLDSTD);
  257.  
  258. skipin:
  259.     close(1);
  260.     if (cp = t->t_drit) {
  261.         cp = globone(Dfix1(cp));
  262.         xfree(cp);
  263.         if ((flags & FCAT) && open(cp, 1) >= 0)
  264.             lseek(1, 0l, 2);
  265.         else {
  266.             if (!(flags & FANY) && adrof("noclobber")) {
  267.                 if (flags & FCAT)
  268.                     Perror(cp);
  269.                 chkclob(cp);
  270.             }
  271.             if (creat(cp, 0644) < 0)
  272.                 Perror(cp);
  273.         }
  274.     } else
  275.         dup((flags & FPOU) ? pipeout[1] : SHOUT);
  276.  
  277.     close(2);
  278.     dup((flags & FDIAG) ? 1 : SHDIAG);
  279.     didfds = 1;
  280. }
  281.  
  282. dofork(shudint)
  283.     bool shudint;
  284. {
  285.     register int pid, (*savint)();
  286.  
  287.     savint = signal(SIGINT, SIG_IGN);
  288.     pid = fork();
  289.     if (pid < 0) {
  290.         signal(SIGINT, savint);
  291.         error("No more processes");
  292.     }
  293.     if (pid == 0) {
  294.         child++;
  295.         signal(SIGINT, shudint ? SIG_DFL : savint);
  296.     } else
  297.         signal(SIGINT, savint);
  298.     return (pid);
  299. }
  300.  
  301. mypipe(pv)
  302.     register int *pv;
  303. {
  304.  
  305.     if (pipe(pv) < 0)
  306.         goto oops;
  307.     pv[0] = dmove(pv[0], -1);
  308.     pv[1] = dmove(pv[1], -1);
  309.     if (pv[0] >= 0 && pv[1] >= 0)
  310.         return;
  311. oops:
  312.     error("Can't make pipe");
  313. }
  314.  
  315. chkclob(cp)
  316.     register char *cp;
  317. {
  318.     struct stat stb;
  319.  
  320.     if (stat(cp, &stb) < 0)
  321.         return;
  322.     if ((stb.st_mode & S_IFMT) == S_IFCHR)
  323.         return;
  324.     error("%s: File exists", cp);
  325. }
  326.