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

unix.superglobalmegacorp.com

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