Annotation of 43BSD/bin/csh/sh.sem.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley Software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char *sccsid = "@(#)sh.sem.c    5.4 (Berkeley) 5/13/86";
                      9: #endif
                     10: 
                     11: #include "sh.h"
                     12: #include "sh.proc.h"
                     13: #include <sys/ioctl.h>
                     14: 
                     15: /*
                     16:  * C shell
                     17:  */
                     18: 
                     19: /*VARARGS 1*/
                     20: execute(t, wanttty, pipein, pipeout)
                     21:        register struct command *t;
                     22:        int wanttty, *pipein, *pipeout;
                     23: {
                     24:        bool forked = 0;
                     25:        struct biltins *bifunc;
                     26:        int pid = 0;
                     27:        int pv[2];
                     28: 
                     29:        if (t == 0)
                     30:                return;
                     31:        if ((t->t_dflg & FAND) && wanttty > 0)
                     32:                wanttty = 0;
                     33:        switch (t->t_dtyp) {
                     34: 
                     35:        case TCOM:
                     36:                if ((t->t_dcom[0][0] & (QUOTE|TRIM)) == QUOTE)
                     37:                        (void) strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
                     38:                if ((t->t_dflg & FREDO) == 0)
                     39:                        Dfix(t);                /* $ " ' \ */
                     40:                if (t->t_dcom[0] == 0)
                     41:                        return;
                     42:                /* fall into... */
                     43: 
                     44:        case TPAR:
                     45:                if (t->t_dflg & FPOU)
                     46:                        mypipe(pipeout);
                     47:                /*
                     48:                 * Must do << early so parent will know
                     49:                 * where input pointer should be.
                     50:                 * If noexec then this is all we do.
                     51:                 */
                     52:                if (t->t_dflg & FHERE) {
                     53:                        (void) close(0);
                     54:                        heredoc(t->t_dlef);
                     55:                        if (noexec)
                     56:                                (void) close(0);
                     57:                }
                     58:                if (noexec)
                     59:                        break;
                     60: 
                     61:                set("status", "0");
                     62: 
                     63:                /*
                     64:                 * This mess is the necessary kludge to handle the prefix
                     65:                 * builtins: nice, nohup, time.  These commands can also
                     66:                 * be used by themselves, and this is not handled here.
                     67:                 * This will also work when loops are parsed.
                     68:                 */
                     69:                while (t->t_dtyp == TCOM)
                     70:                        if (eq(t->t_dcom[0], "nice"))
                     71:                                if (t->t_dcom[1])
                     72:                                        if (any(t->t_dcom[1][0], "+-"))
                     73:                                                if (t->t_dcom[2]) {
                     74:                                                        setname("nice");
                     75:                                                        t->t_nice = getn(t->t_dcom[1]);
                     76:                                                        lshift(t->t_dcom, 2);
                     77:                                                        t->t_dflg |= FNICE;
                     78:                                                } else
                     79:                                                        break;
                     80:                                        else {
                     81:                                                t->t_nice = 4;
                     82:                                                lshift(t->t_dcom, 1);
                     83:                                                t->t_dflg |= FNICE;
                     84:                                        }
                     85:                                else
                     86:                                        break;
                     87:                        else if (eq(t->t_dcom[0], "nohup"))
                     88:                                if (t->t_dcom[1]) {
                     89:                                        t->t_dflg |= FNOHUP;
                     90:                                        lshift(t->t_dcom, 1);
                     91:                                } else
                     92:                                        break;
                     93:                        else if (eq(t->t_dcom[0], "time"))
                     94:                                if (t->t_dcom[1]) {
                     95:                                        t->t_dflg |= FTIME;
                     96:                                        lshift(t->t_dcom, 1);
                     97:                                } else
                     98:                                        break;
                     99:                        else
                    100:                                break;
                    101:                /*
                    102:                 * Check if we have a builtin function and remember which one.
                    103:                 */
                    104:                bifunc = t->t_dtyp == TCOM ? isbfunc(t) : (struct biltins *) 0;
                    105: 
                    106:                /*
                    107:                 * We fork only if we are timed, or are not the end of
                    108:                 * a parenthesized list and not a simple builtin function.
                    109:                 * Simple meaning one that is not pipedout, niced, nohupped,
                    110:                 * or &'d.
                    111:                 * It would be nice(?) to not fork in some of these cases.
                    112:                 */
                    113:                if (((t->t_dflg & FTIME) || (t->t_dflg & FPAR) == 0 &&
                    114:                     (!bifunc || t->t_dflg & (FPOU|FAND|FNICE|FNOHUP))))
                    115: #ifdef VFORK
                    116:                    if (t->t_dtyp == TPAR || t->t_dflg&(FREDO|FAND) || bifunc)
                    117: #endif
                    118:                        { forked++; pid = pfork(t, wanttty); }
                    119: #ifdef VFORK
                    120:                    else {
                    121:                        int vffree();
                    122:                        int ochild, osetintr, ohaderr, odidfds;
                    123:                        int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp;
                    124:                        int omask;
                    125: 
                    126:                        /* 
                    127:                         * Prepare for the vfork by saving everything
                    128:                         * that the child corrupts before it exec's.
                    129:                         * Note that in some signal implementations
                    130:                         * which keep the signal info in user space
                    131:                         * (e.g. Sun's) it will also be necessary to
                    132:                         * save and restore the current sigvec's for
                    133:                         * the signals the child touches before it
                    134:                         * exec's.
                    135:                         */
                    136:                        omask = sigblock(sigmask(SIGCHLD));
                    137:                        ochild = child; osetintr = setintr;
                    138:                        ohaderr = haderr; odidfds = didfds;
                    139:                        oSHIN = SHIN; oSHOUT = SHOUT;
                    140:                        oSHDIAG = SHDIAG; oOLDSTD = OLDSTD; otpgrp = tpgrp;
                    141:                        Vsav = Vdp = 0; Vav = 0;
                    142:                        pid = vfork();
                    143:                        if (pid < 0) {
                    144:                                (void) sigsetmask(omask);
                    145:                                error("No more processes");
                    146:                        }
                    147:                        forked++;
                    148:                        if (pid) {      /* parent */
                    149:                                child = ochild; setintr = osetintr;
                    150:                                haderr = ohaderr; didfds = odidfds;
                    151:                                SHIN = oSHIN;
                    152:                                SHOUT = oSHOUT; SHDIAG = oSHDIAG;
                    153:                                OLDSTD = oOLDSTD; tpgrp = otpgrp;
                    154:                                xfree(Vsav); Vsav = 0;
                    155:                                xfree(Vdp); Vdp = 0;
                    156:                                xfree((char *)Vav); Vav = 0;
                    157:                                /* this is from pfork() */
                    158:                                palloc(pid, t);
                    159:                                (void) sigsetmask(omask);
                    160:                        } else {        /* child */
                    161:                                /* this is from pfork() */
                    162:                                int pgrp;
                    163:                                bool ignint = 0;
                    164: 
                    165:                                if (setintr)
                    166:                                        ignint =
                    167:                                            (tpgrp == -1 && (t->t_dflg&FINT))
                    168:                                            || gointr && eq(gointr, "-");
                    169:                                pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
                    170:                                child++;
                    171:                                if (setintr) {
                    172:                                        setintr = 0;
                    173: #ifdef notdef
                    174:                                        (void) signal(SIGCHLD, SIG_DFL);
                    175: #endif
                    176:                                        (void) signal(SIGINT, ignint ?
                    177:                                                SIG_IGN : vffree);
                    178:                                        (void) signal(SIGQUIT, ignint ?
                    179:                                                SIG_IGN : SIG_DFL);
                    180:                                        if (wanttty >= 0) {
                    181:                                                (void) signal(SIGTSTP, SIG_DFL);
                    182:                                                (void) signal(SIGTTIN, SIG_DFL);
                    183:                                                (void) signal(SIGTTOU, SIG_DFL);
                    184:                                        }
                    185:                                        (void) signal(SIGTERM, parterm);
                    186:                                } else if (tpgrp == -1 && (t->t_dflg&FINT)) {
                    187:                                        (void) signal(SIGINT, SIG_IGN);
                    188:                                        (void) signal(SIGQUIT, SIG_IGN);
                    189:                                }
                    190:                                if (wanttty > 0)
                    191:                                        (void) ioctl(FSHTTY, TIOCSPGRP,
                    192:                                                (char *)&pgrp);
                    193:                                if (wanttty >= 0 && tpgrp >= 0)
                    194:                                        (void) setpgrp(0, pgrp);
                    195:                                if (tpgrp > 0)
                    196:                                        tpgrp = 0;
                    197:                                if (t->t_dflg & FNOHUP)
                    198:                                        (void) signal(SIGHUP, SIG_IGN);
                    199:                                if (t->t_dflg & FNICE)
                    200:                                        (void) setpriority(PRIO_PROCESS,
                    201:                                                0, t->t_nice);
                    202:                        }
                    203: 
                    204:                    }
                    205: #endif
                    206:                if (pid != 0) {
                    207:                        /*
                    208:                         * It would be better if we could wait for the
                    209:                         * whole job when we knew the last process
                    210:                         * had been started.  Pwait, in fact, does
                    211:                         * wait for the whole job anyway, but this test
                    212:                         * doesn't really express our intentions.
                    213:                         */
                    214:                        if (didfds==0 && t->t_dflg&FPIN) {
                    215:                                (void) close(pipein[0]);
                    216:                                (void) close(pipein[1]);
                    217:                        }
                    218:                        if ((t->t_dflg & (FPOU|FAND)) == 0)
                    219:                                pwait();
                    220:                        break;
                    221:                }
                    222:                doio(t, pipein, pipeout);
                    223:                if (t->t_dflg & FPOU) {
                    224:                        (void) close(pipeout[0]);
                    225:                        (void) close(pipeout[1]);
                    226:                }
                    227: 
                    228:                /*
                    229:                 * Perform a builtin function.
                    230:                 * If we are not forked, arrange for possible stopping
                    231:                 */
                    232:                if (bifunc) {
                    233:                        func(t, bifunc);
                    234:                        if (forked)
                    235:                                exitstat();
                    236:                        break;
                    237:                }
                    238:                if (t->t_dtyp != TPAR) {
                    239:                        doexec(t);
                    240:                        /*NOTREACHED*/
                    241:                }
                    242:                /*
                    243:                 * For () commands must put new 0,1,2 in FSH* and recurse
                    244:                 */
                    245:                OLDSTD = dcopy(0, FOLDSTD);
                    246:                SHOUT = dcopy(1, FSHOUT);
                    247:                SHDIAG = dcopy(2, FSHDIAG);
                    248:                (void) close(SHIN);
                    249:                SHIN = -1;
                    250:                didfds = 0;
                    251:                wanttty = -1;
                    252:                t->t_dspr->t_dflg |= t->t_dflg & FINT;
                    253:                execute(t->t_dspr, wanttty);
                    254:                exitstat();
                    255: 
                    256:        case TFIL:
                    257:                t->t_dcar->t_dflg |= FPOU |
                    258:                    (t->t_dflg & (FPIN|FAND|FDIAG|FINT));
                    259:                execute(t->t_dcar, wanttty, pipein, pv);
                    260:                t->t_dcdr->t_dflg |= FPIN |
                    261:                    (t->t_dflg & (FPOU|FAND|FPAR|FINT));
                    262:                if (wanttty > 0)
                    263:                        wanttty = 0;            /* got tty already */
                    264:                execute(t->t_dcdr, wanttty, pv, pipeout);
                    265:                break;
                    266: 
                    267:        case TLST:
                    268:                if (t->t_dcar) {
                    269:                        t->t_dcar->t_dflg |= t->t_dflg & FINT;
                    270:                        execute(t->t_dcar, wanttty);
                    271:                        /*
                    272:                         * In strange case of A&B make a new job after A
                    273:                         */
                    274:                        if (t->t_dcar->t_dflg&FAND && t->t_dcdr &&
                    275:                            (t->t_dcdr->t_dflg&FAND) == 0)
                    276:                                pendjob();
                    277:                }
                    278:                if (t->t_dcdr) {
                    279:                        t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
                    280:                        execute(t->t_dcdr, wanttty);
                    281:                }
                    282:                break;
                    283: 
                    284:        case TOR:
                    285:        case TAND:
                    286:                if (t->t_dcar) {
                    287:                        t->t_dcar->t_dflg |= t->t_dflg & FINT;
                    288:                        execute(t->t_dcar, wanttty);
                    289:                        if ((getn(value("status")) == 0) != (t->t_dtyp == TAND))
                    290:                                return;
                    291:                }
                    292:                if (t->t_dcdr) {
                    293:                        t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
                    294:                        execute(t->t_dcdr, wanttty);
                    295:                }
                    296:                break;
                    297:        }
                    298:        /*
                    299:         * Fall through for all breaks from switch
                    300:         *
                    301:         * If there will be no more executions of this
                    302:         * command, flush all file descriptors.
                    303:         * Places that turn on the FREDO bit are responsible
                    304:         * for doing donefds after the last re-execution
                    305:         */
                    306:        if (didfds && !(t->t_dflg & FREDO))
                    307:                donefds();
                    308: }
                    309: 
                    310: #ifdef VFORK
                    311: vffree()
                    312: {
                    313:        register char **v;
                    314: 
                    315:        if (v = gargv)
                    316:                gargv = 0, xfree((char *)v);
                    317:        if (v = pargv)
                    318:                pargv = 0, xfree((char *)v);
                    319:        _exit(1);
                    320: }
                    321: #endif
                    322: 
                    323: /*
                    324:  * Perform io redirection.
                    325:  * We may or maynot be forked here.
                    326:  */
                    327: doio(t, pipein, pipeout)
                    328:        register struct command *t;
                    329:        int *pipein, *pipeout;
                    330: {
                    331:        register char *cp;
                    332:        register int flags = t->t_dflg;
                    333: 
                    334:        if (didfds || (flags & FREDO))
                    335:                return;
                    336:        if ((flags & FHERE) == 0) {     /* FHERE already done */
                    337:                (void) close(0);
                    338:                if (cp = t->t_dlef) {
                    339:                        cp = globone(Dfix1(cp));
                    340:                        xfree(cp);
                    341:                        if (open(cp, 0) < 0)
                    342:                                Perror(cp);
                    343:                } else if (flags & FPIN) {
                    344:                        (void) dup(pipein[0]);
                    345:                        (void) close(pipein[0]);
                    346:                        (void) close(pipein[1]);
                    347:                } else if ((flags & FINT) && tpgrp == -1) {
                    348:                        (void) close(0);
                    349:                        (void) open("/dev/null", 0);
                    350:                } else
                    351:                        (void) dup(OLDSTD);
                    352:        }
                    353:        (void) close(1);
                    354:        if (cp = t->t_drit) {
                    355:                cp = globone(Dfix1(cp));
                    356:                xfree(cp);
                    357:                if ((flags & FCAT) && open(cp, 1) >= 0)
                    358:                        (void) lseek(1, (off_t)0, 2);
                    359:                else {
                    360:                        if (!(flags & FANY) && adrof("noclobber")) {
                    361:                                if (flags & FCAT)
                    362:                                        Perror(cp);
                    363:                                chkclob(cp);
                    364:                        }
                    365:                        if (creat(cp, 0666) < 0)
                    366:                                Perror(cp);
                    367:                }
                    368:        } else if (flags & FPOU)
                    369:                (void) dup(pipeout[1]);
                    370:        else
                    371:                (void) dup(SHOUT);
                    372: 
                    373:        (void) close(2);
                    374:        if (flags & FDIAG)
                    375:                (void) dup(1);
                    376:        else
                    377:                (void) dup(SHDIAG);
                    378:        didfds = 1;
                    379: }
                    380: 
                    381: mypipe(pv)
                    382:        register int *pv;
                    383: {
                    384: 
                    385:        if (pipe(pv) < 0)
                    386:                goto oops;
                    387:        pv[0] = dmove(pv[0], -1);
                    388:        pv[1] = dmove(pv[1], -1);
                    389:        if (pv[0] >= 0 && pv[1] >= 0)
                    390:                return;
                    391: oops:
                    392:        error("Can't make pipe");
                    393: }
                    394: 
                    395: chkclob(cp)
                    396:        register char *cp;
                    397: {
                    398:        struct stat stb;
                    399: 
                    400:        if (stat(cp, &stb) < 0)
                    401:                return;
                    402:        if ((stb.st_mode & S_IFMT) == S_IFCHR)
                    403:                return;
                    404:        error("%s: File exists", cp);
                    405: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.