BSD 3 development
authorBill Joy <wnj@ucbvax.Berkeley.EDU>
Wed, 28 Nov 1979 04:33:42 +0000 (20:33 -0800)
committerBill Joy <wnj@ucbvax.Berkeley.EDU>
Wed, 28 Nov 1979 04:33:42 +0000 (20:33 -0800)
Work on file usr/src/cmd/csh/sh.sem.c

Synthesized-from: 3bsd

usr/src/cmd/csh/sh.sem.c [new file with mode: 0644]

diff --git a/usr/src/cmd/csh/sh.sem.c b/usr/src/cmd/csh/sh.sem.c
new file mode 100644 (file)
index 0000000..5912144
--- /dev/null
@@ -0,0 +1,400 @@
+/* Copyright (c) 1979 Regents of the University of California */
+#include "sh.h"
+
+/*
+ * C shell
+ */
+
+execute(t, pipein, pipeout)
+       register struct command *t;
+       int *pipein, *pipeout;
+{
+       int pid, flags, pv[2];
+       register struct command *t1;
+       register char *cp;
+       bool forked = 0;
+       bool shudint, shudhup;
+#ifdef VFORK
+       int (*savint)(), vffree();
+       int ochild, osetintr, ohaderr, otimflg, odidfds, odidcch;
+       int oSHIN, oSHOUT, oSHDIAG, oOLDSTD;
+       int isvfork = 0;
+#endif
+
+       if (t == 0)
+               return;
+       switch (t->t_dtyp) {
+
+       case TCOM:
+               cp = t->t_dcom[0];
+               if ((cp[0] & (QUOTE|TRIM)) == QUOTE)
+                       strcpy(cp, cp + 1);
+               if ((t->t_dflg & FREDO) == 0)
+                       Dfix(t);                /* $ " ' \ */
+               /* fall into... */
+
+       case TPAR:
+               flags = t->t_dflg;
+               if (flags & FPOU)
+                       mypipe(pipeout);
+               /*
+                * A child will be interruptible only under very
+                * certain conditions:
+                *      we must be monkeying with interrupts
+                *      the child must not be &'ed
+                *      we must not have had an "onintr -"
+                */
+               shudint = setintr && (flags & FINT) == 0 && (!gointr || !eq(gointr, "-"));
+               shudhup = (flags & FAND) == 0;
+
+               /*
+                * Must do << early so parent will know
+                * where input pointer should be
+                */
+               if (flags & FHERE)
+                       close(0), heredoc(t->t_dlef);
+
+               /*
+                * If not executing commands then
+                * all we must do is read forward in the input to
+                * account for << redirection if present.
+                */
+               if (noexec) {
+                       if (flags & FHERE)
+                               close(0);
+                       return;
+               }
+
+               set("status", "0");
+               pid = 0;
+
+               /*
+                * Built-in functions
+                */
+               if (t->t_dtyp == TCOM && isbfunc(t->t_dcom[0])) {
+                       /*
+                        * If output is piped, or running & and we would
+                        * eventually fork for non-builtin commands,
+                        * then do it now, so we won't block.
+                        */
+                       if ((flags & (FPOU|FAND)) && (flags & FPAR) == 0)
+                               pid = dofork(shudint, shudhup), forked++;
+
+                       /*
+                        * If the builtin is actually executed (some, e.g.
+                        * time and nice may refuse to execute here)
+                        * then either exit (if we forked) or close i/o
+                        * and continue execution (if we didn't).
+                        */
+                       if (pid == 0) {
+                               doio(t, pipein, pipeout);
+                               if (flags & FPOU) {
+                                       close(pipeout[0]), close(pipeout[1]);
+                                       pipeout[0] = pipeout[1] = -1;
+                               }
+                               if (setintr && forked) {
+                                       if (shudint)
+                                               signal(SIGINT, SIG_DFL), signal(SIGQUIT, SIG_DFL);
+                                       signal(SIGTERM, parterm);
+                                       if (flags & FINT)
+                                               setintr = 0;
+                               }
+                               if (func(t, pipein, pipeout)) {
+                                       if (forked)
+                                               exitstat();
+                                       if (didfds && !(t->t_dflg & FREDO))
+                                               donefds();
+                                       return;
+                               }
+                       }
+               }
+
+               /*
+                * Now, we must make a new process since either the
+                * command is non-builtin, a parenthesized list,
+                * or builtin such as time or nice which really
+                * requires a child.
+                */
+               if (!forked && (flags & FPAR) == 0)
+#ifdef VFORK
+                       if (t->t_dtyp == TPAR || (flags&FREDO) ||
+                           eq(t->t_dcom[0], "nice") || eq(t->t_dcom[0], "nohup"))
+#endif
+                               pid = dofork(shudint, shudhup);
+#ifdef VFORK
+                       else {
+                               savint = signal(SIGINT, SIG_IGN);
+                               ochild = child; osetintr = setintr;
+                               ohaderr = haderr; otimflg = timflg;
+                               odidfds = didfds; odidcch = didcch;
+                               oSHIN = SHIN; oSHOUT = SHOUT;
+                               oSHDIAG = SHDIAG; oOLDSTD = OLDSTD;
+                               Vsav = Vdp = 0; Vav = 0;
+                               isvfork++;
+                               pid = vfork();
+                               if (pid < 0) {
+                                       signal(SIGINT, savint);
+                                       error("No more processes");
+                               }
+                               if (pid == 0) {
+                                       child++;
+                                       signal(SIGINT, shudint ? SIG_DFL : savint);
+                                       if (!shudhup)
+                                               signal(SIGHUP, SIG_IGN);
+                               } else {
+                                       child = ochild; setintr = osetintr;
+                                       haderr = ohaderr; timflg = otimflg;
+                                       didfds = odidfds; didcch = odidcch;
+                                       SHIN = oSHIN; SHOUT = oSHOUT;
+                                       SHDIAG = oSHDIAG; OLDSTD = oOLDSTD;
+                                       xfree(Vsav), Vsav = 0;
+                                       xfree(Vdp), Vdp = 0;
+                                       xfree(Vav), Vav = 0;
+                                       signal(SIGINT, savint);
+                               }
+                       }
+#endif
+               if (pid != 0) {
+                       /*
+                        * The parent path (or nobody does this if
+                        * (flags & FPAR), i.e. date in (set;date))
+                        */
+                       if (didfds == 0 && (flags & FPIN))
+                               close(pipein[0]), close(pipein[1]);
+                       if (didfds && !(t->t_dflg & FREDO))
+                               donefds();
+                       if (flags & FPRS)
+                               printf("%d\n", pid), set("child", putn(pid));
+                       /*
+                        * Unless output is piped or command is &
+                        * wait for it.
+                        */
+                       if (t->t_dtyp == TCOM)
+                               cadd(pid, t->t_dcom[0]);
+                       else
+                               cadd(pid, "()");
+                       if ((flags & (FPOU|FAND)) == 0)
+                               pwait(pid);
+                       return;
+               }
+
+               /*
+                * Insure that this (child) shell doesn't muck on
+                */
+               child++;
+
+               /*
+                * If havent yet, finally set up the file descriptors.
+                */
+               doio(t, pipein, pipeout);
+               if (flags & FPOU)
+                       close(pipeout[0]), close(pipeout[1]);
+
+               /*
+                * If mucking with interrupts fix interrupt, quit,
+                * and terminate handling ... in any case set setintr
+                * to 0 if we are not interruptible so that no further
+                * interrupt mucking occurs.
+                */
+               if (setintr) {
+                       if (shudint) {
+                               signal(SIGQUIT, SIG_DFL);
+#ifdef VFORK
+                               if (isvfork)
+                                       signal(SIGINT, vffree);
+                               else
+#endif
+                                       signal(SIGINT, SIG_DFL);
+                       }
+                       signal(SIGTERM, parterm);
+                       if (flags & FINT)
+                               setintr = 0;
+               }
+
+               /*
+                * For () commands must put new 0,1,2 in FSH* and recurse
+                */
+               if (t->t_dtyp == TPAR) {
+                       t1 = t->t_dspr;
+                       t1->t_dflg |= flags & FINT;
+                       OLDSTD = dcopy(0, FOLDSTD);
+                       SHOUT = dcopy(1, FSHOUT);
+                       SHDIAG = dcopy(2, FSHDIAG);
+                       close(SHIN), SHIN = -1;
+                       didcch = 0, didfds = 0;
+                       execute(t1);
+                       exitstat();
+               }
+               if (eq(t->t_dcom[0], "nice")) {
+/* sigh...
+                       nice(20);
+                       nice(-10);
+*/
+                       cp = t->t_dcom[1];
+                       if (any(cp[0], "+-"))
+                               nice(getn(cp)), lshift(t->t_dcom, 2);
+                       else
+                               nice(4), lshift(t->t_dcom, 1);
+                       t->t_dflg = FPAR | FREDO;
+                       execute(t);
+                       exitstat();
+               }
+               if (eq(t->t_dcom[0], "nohup")) {
+                       if (setintr == 0)
+                               signal(SIGHUP, SIG_IGN);
+                       signal(SIGTERM, SIG_IGN);
+                       lshift(t->t_dcom, 1);
+                       t->t_dflg = FPAR | FREDO;
+                       execute(t);
+                       exitstat();
+               }
+               doexec(t);
+               /* no return */
+
+       case TFIL:
+               flags = t->t_dflg;
+               t1 = t->t_dcar;
+               t1->t_dflg |= FPOU | (flags & (FPIN|FINT|FPRS|FDIAG));
+               execute(t1, pipein, pv);
+               t1 = t->t_dcdr;
+               t1->t_dflg |= FPIN | (flags & (FPOU|FINT|FAND|FPRS|FPAR));
+               execute(t1, pv, pipeout);
+               return;
+
+       case TLST:
+               flags = t->t_dflg & FINT;
+               if (t1 = t->t_dcar)
+                       t1->t_dflg |= flags, execute(t1);
+               if (t1 = t->t_dcdr)
+                       t1->t_dflg |= t->t_dflg & (FINT|FPAR), execute(t1);
+               return;
+
+       case TOR:
+       case TAND:
+               flags = t->t_dflg & FINT;
+               if (t1 = t->t_dcar) {
+                       t1->t_dflg |= flags, execute(t1);
+                       if ((getn(value("status")) == 0) == (t->t_dtyp == TAND))
+                               return;
+               }
+               if (t1 = t->t_dcdr)
+                       t1->t_dflg |= t->t_dflg & (FINT|FPAR), execute(t1);
+               return;
+       }
+}
+
+#ifdef VFORK
+vffree()
+{
+       register char **v;
+
+       if (v = gargv)
+               gargv = 0, xfree(gargv);
+       if (v = pargv)
+               pargv = 0, xfree(pargv);
+       _exit(1);
+}
+#endif
+
+doio(t, pipein, pipeout)
+       register struct command *t;
+       int *pipein, *pipeout;
+{
+       register char *cp;
+       register int flags = t->t_dflg;
+       char *dp;
+
+       if (didfds || (flags & FREDO))
+               return;
+       if (flags & FHERE)
+               goto skipin;
+       close(0);
+       if (cp = t->t_dlef) {
+               cp = globone(dp = Dfix1(cp));
+               xfree(dp);
+               xfree(cp);
+               if (open(cp, 0) < 0)
+                       Perror(cp);
+       } else if (flags & FPIN)
+               dup(pipein[0]), close(pipein[0]), close(pipein[1]);
+       else if (flags & FINT)
+               close(0), open("/dev/null", 0);
+       else
+               dup(OLDSTD);
+
+skipin:
+       close(1);
+       if (cp = t->t_drit) {
+               cp = globone(dp = Dfix1(cp));
+               xfree(dp);
+               xfree(cp);
+               if ((flags & FCAT) && open(cp, 1) >= 0)
+                       lseek(1, 0l, 2);
+               else {
+                       if (!(flags & FANY) && adrof("noclobber")) {
+                               if (flags & FCAT)
+                                       Perror(cp);
+                               chkclob(cp);
+                       }
+#ifdef V6
+                       if (creat(cp, 0644) < 0)
+                               Perror(cp);
+#else
+                       if (creat(cp, 0666) < 0)
+                               Perror(cp);
+#endif
+               }
+       } else
+               dup((flags & FPOU) ? pipeout[1] : SHOUT);
+
+       close(2);
+       dup((flags & FDIAG) ? 1 : SHDIAG);
+       didfds = 1;
+}
+
+dofork(shudint, shudhup)
+       bool shudint, shudhup;
+{
+       register int pid, (*savint)();
+
+       savint = signal(SIGINT, SIG_IGN);
+       pid = fork();
+       if (pid < 0) {
+               signal(SIGINT, savint);
+               error("No more processes");
+       }
+       if (pid == 0) {
+               child++;
+               signal(SIGINT, shudint ? SIG_DFL : savint);
+               if (!shudhup)
+                       signal(SIGHUP, SIG_IGN);
+       } else
+               signal(SIGINT, savint);
+       return (pid);
+}
+
+mypipe(pv)
+       register int *pv;
+{
+
+       if (pipe(pv) < 0)
+               goto oops;
+       pv[0] = dmove(pv[0], -1);
+       pv[1] = dmove(pv[1], -1);
+       if (pv[0] >= 0 && pv[1] >= 0)
+               return;
+oops:
+       error("Can't make pipe");
+}
+
+chkclob(cp)
+       register char *cp;
+{
+       struct stat stb;
+
+       if (stat(cp, &stb) < 0)
+               return;
+       if ((stb.st_mode & S_IFMT) == S_IFCHR)
+               return;
+       error("%s: File exists", cp);
+}