X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/2b84abb596f52ab2068d52108adc96838ad4340a..31cef89cb428866f787983e68246030321893df4:/usr/src/cmd/csh/sh.sem.c diff --git a/usr/src/cmd/csh/sh.sem.c b/usr/src/cmd/csh/sh.sem.c index 591214436c..f29027afa9 100644 --- a/usr/src/cmd/csh/sh.sem.c +++ b/usr/src/cmd/csh/sh.sem.c @@ -1,286 +1,280 @@ -/* Copyright (c) 1979 Regents of the University of California */ +static char *sccsid = "@(#)sh.sem.c 4.1 10/9/80"; + #include "sh.h" +#include "sh.proc.h" +#include /* * C shell */ -execute(t, pipein, pipeout) +/*VARARGS 1*/ +execute(t, wanttty, pipein, pipeout) register struct command *t; - int *pipein, *pipeout; + int wanttty, *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 + struct biltins *bifunc; + int pid = 0; + int pv[2]; if (t == 0) return; + if ((t->t_dflg & FAND) && wanttty > 0) + wanttty = 0; switch (t->t_dtyp) { case TCOM: - cp = t->t_dcom[0]; - if ((cp[0] & (QUOTE|TRIM)) == QUOTE) - strcpy(cp, cp + 1); + if ((t->t_dcom[0][0] & (QUOTE|TRIM)) == QUOTE) + strcpy(t->t_dcom[0], t->t_dcom[0] + 1); if ((t->t_dflg & FREDO) == 0) Dfix(t); /* $ " ' \ */ + if (t->t_dcom[0] == 0) + return; /* fall into... */ case TPAR: - flags = t->t_dflg; - if (flags & FPOU) + if (t->t_dflg & 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 + * where input pointer should be. + * If noexec then this is all we do. */ - 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) + if (t->t_dflg & FHERE) { + close(0); + heredoc(t->t_dlef); + if (noexec) close(0); - return; } + if (noexec) + break; set("status", "0"); - pid = 0; /* - * Built-in functions + * This mess is the necessary kludge to handle the prefix + * builtins: nice, nohup, time. These commands can also + * be used by themselves, and this is not handled here. + * This will also work when loops are parsed. */ - 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; - } - } - } + while (t->t_dtyp == TCOM) + if (eq(t->t_dcom[0], "nice")) + if (t->t_dcom[1]) + if (any(t->t_dcom[1][0], "+-")) + if (t->t_dcom[2]) { + setname("nice"); + t->t_nice = getn(t->t_dcom[1]); + lshift(t->t_dcom, 2); + t->t_dflg |= FNICE; + } else + break; + else { + t->t_nice = 4; + lshift(t->t_dcom, 1); + t->t_dflg |= FNICE; + } + else + break; + else if (eq(t->t_dcom[0], "nohup")) + if (t->t_dcom[1]) { + t->t_dflg |= FNOHUP; + lshift(t->t_dcom, 1); + } else + break; + else if (eq(t->t_dcom[0], "time")) + if (t->t_dcom[1]) { + t->t_dflg |= FTIME; + lshift(t->t_dcom, 1); + } else + break; + else + break; + /* + * Check if we have a builtin function and remember which one. + */ + bifunc = t->t_dtyp == TCOM ? isbfunc(t) : (struct biltins *) 0; /* - * 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. + * We fork only if we are timed, or are not the end of + * a parenthesized list and not a simple builtin function. + * Simple meaning one that is not pipedout, niced, nohupped, + * or &'d. + * It would be nice(?) to not fork in some of these cases. */ - if (!forked && (flags & FPAR) == 0) + if (((t->t_dflg & FTIME) || (t->t_dflg & FPAR) == 0 && + (!bifunc || t->t_dflg & (FPOU|FAND|FNICE|FNOHUP)))) #ifdef VFORK - if (t->t_dtyp == TPAR || (flags&FREDO) || - eq(t->t_dcom[0], "nice") || eq(t->t_dcom[0], "nohup")) + if (t->t_dtyp == TPAR || t->t_dflg&(FREDO|FAND) || bifunc) #endif - pid = dofork(shudint, shudhup); + { forked++; pid = pfork(t, wanttty); } #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); + else { + int vffree(); + int ochild, osetintr, ohaderr, odidfds, odidcch; + int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp; + + sighold(SIGCHLD); + ochild = child; osetintr = setintr; + ohaderr = haderr; odidfds = didfds; odidcch = didcch; + oSHIN = SHIN; oSHOUT = SHOUT; + oSHDIAG = SHDIAG; oOLDSTD = OLDSTD; otpgrp = tpgrp; + Vsav = Vdp = 0; Vav = 0; + pid = vfork(); + if (pid < 0) { + sigrelse(SIGCHLD); + error("No more processes"); + } + forked++; + if (pid) { + child = ochild; setintr = osetintr; + haderr = ohaderr; didfds = odidfds; + didcch = odidcch; SHIN = oSHIN; + SHOUT = oSHOUT; SHDIAG = oSHDIAG; + OLDSTD = oOLDSTD; tpgrp = otpgrp; + xfree(Vsav); Vsav = 0; + xfree(Vdp); Vdp = 0; + xfree(Vav); Vav = 0; + /* this is from pfork() */ + palloc(pid, t); + sigrelse(SIGCHLD); + } else { + /* this is from pfork() */ + int pgrp; + bool ignint = 0; + + if (setintr) + ignint = + (tpgrp == -1 && (t->t_dflg&FINT)) + || gointr && eq(gointr, "-"); + pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); + child++; + if (setintr) { + setintr = 0; + sigsys(SIGCHLD, SIG_DFL); + sigsys(SIGINT, ignint ? SIG_IGN : vffree); + sigsys(SIGQUIT, ignint ? SIG_IGN : SIG_DFL); + if (wanttty >= 0) { + sigsys(SIGTSTP, SIG_DFL); + sigsys(SIGTTIN, SIG_DFL); + sigsys(SIGTTOU, SIG_DFL); + } + sigsys(SIGTERM, parterm); + } else if (tpgrp == -1 && (t->t_dflg&FINT)) { + sigsys(SIGINT, SIG_IGN); + sigsys(SIGQUIT, SIG_IGN); } + if (wanttty > 0) + ioctl(FSHTTY, TIOCSPGRP, &pgrp); + if (wanttty >= 0 && tpgrp >= 0) + setpgrp(0, pgrp); + if (tpgrp > 0) + tpgrp = 0; + if (t->t_dflg & FNOHUP) + sigsys(SIGHUP, SIG_IGN); + if (t->t_dflg & FNICE) + nice(t->t_nice); } + + } #endif if (pid != 0) { /* - * The parent path (or nobody does this if - * (flags & FPAR), i.e. date in (set;date)) + * It would be better if we could wait for the + * whole job when we knew the last process + * had been started. Pwait, in fact, does + * wait for the whole job anyway, but this test + * doesn't really express our intentions. */ - if (didfds == 0 && (flags & FPIN)) + if (didfds==0 && t->t_dflg&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; + if ((t->t_dflg & (FPOU|FAND)) == 0) + pwait(); + break; } - - /* - * 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) + if (t->t_dflg & 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. + * Perform a builtin function. + * If we are not forked, arrange for possible stopping */ - 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; + if (bifunc) { + func(t, bifunc); + if (forked) + exitstat(); + break; + } + if (t->t_dtyp != TPAR) { + doexec(t); + /*NOTREACHED*/ } - /* * 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 */ + OLDSTD = dcopy(0, FOLDSTD); + SHOUT = dcopy(1, FSHOUT); + SHDIAG = dcopy(2, FSHDIAG); + close(SHIN), SHIN = -1; + didcch = 0, didfds = 0; + wanttty = -1; + t->t_dspr->t_dflg |= t->t_dflg & FINT; + execute(t->t_dspr, wanttty); + exitstat(); 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; + t->t_dcar->t_dflg |= FPOU | + (t->t_dflg & (FPIN|FAND|FDIAG|FINT)); + execute(t->t_dcar, wanttty, pipein, pv); + t->t_dcdr->t_dflg |= FPIN | + (t->t_dflg & (FPOU|FAND|FPAR|FINT)); + if (wanttty > 0) + wanttty = 0; /* got tty already */ + execute(t->t_dcdr, wanttty, pv, pipeout); + break; 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; + if (t->t_dcar) { + t->t_dcar->t_dflg |= t->t_dflg & FINT; + execute(t->t_dcar, wanttty); + /* + * In strange case of A&B make a new job after A + */ + if (t->t_dcar->t_dflg&FAND && t->t_dcdr && + (t->t_dcdr->t_dflg&FAND) == 0) + pendjob(); + } + if (t->t_dcdr) { + t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT); + execute(t->t_dcdr, wanttty); + } + break; 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)) + if (t->t_dcar) { + t->t_dcar->t_dflg |= t->t_dflg & FINT; + execute(t->t_dcar, wanttty); + 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; + if (t->t_dcdr) { + t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT); + execute(t->t_dcdr, wanttty); + } + break; } + /* + * Fall through for all breaks from switch + * + * If there will be no more executions of this + * command, flush all file descriptors. + * Places that turn on the FREDO bit are responsible + * for doing donefds after the last re-execution + */ + if (didfds && !(t->t_dflg & FREDO)) + donefds(); } #ifdef VFORK @@ -296,37 +290,36 @@ vffree() } #endif +/* + * Perform io redirection. + * We may or maynot be forked here. + */ 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: + if ((flags & FHERE) == 0) { /* FHERE already done */ + close(0); + if (cp = t->t_dlef) { + cp = globone(Dfix1(cp)); + 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) && tpgrp == -1) + close(0), open("/dev/null", 0); + else + dup(OLDSTD); + } close(1); if (cp = t->t_drit) { - cp = globone(dp = Dfix1(cp)); - xfree(dp); + cp = globone(Dfix1(cp)); xfree(cp); if ((flags & FCAT) && open(cp, 1) >= 0) lseek(1, 0l, 2); @@ -336,43 +329,19 @@ skipin: 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); + } else if (flags & FPOU) + dup(pipeout[1]); + else + dup(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; {