Annotation of coherent/a/usr/bob/korn/exec.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * execute command tree
                      3:  */
                      4: 
                      5: static char *RCSid = "$Header: /newbits/usr/bin/korn/RCS/exec.c,v 1.2 91/08/01 12:40:11 bin Exp Locker: bin $";
                      6: 
                      7: #include <stddef.h>
                      8: #include <stdlib.h>
                      9: #include <stdio.h>
                     10: #include <string.h>
                     11: #include <errno.h>
                     12: #include <signal.h>
                     13: #include <setjmp.h>
                     14: #include <unistd.h>
                     15: #include <sys/fcntl.h>
                     16: #include "sh.h"
                     17: #include "lex.h"
                     18: #include "tree.h"
                     19: #include "table.h"
                     20: 
                     21: static int     comexec ARGS((struct op *t, char **vp, char **ap, int flags));
                     22: static void    iosetup ARGS((struct ioword *iop));
                     23: static void    echo ARGS((char **, char **));
                     24: static int     herein ARGS((char *name, int sub));
                     25: 
                     26: /*
                     27:  * execute command tree
                     28:  */
                     29: int
                     30: execute(t, flags)
                     31:        register struct op *t;
                     32:        Volatile int flags;     /* if XEXEC don't fork */
                     33: {
                     34:        int i;
                     35:        int Volatile rv = 0;
                     36:        int pv[2];
                     37:        register char **ap;
                     38:        char *s, *cp;
                     39:        struct ioword **iowp;
                     40: 
                     41:        if (t == NULL)
                     42:                return 0;
                     43: 
                     44:        if ((flags&XFORK) && !(flags&XEXEC) && t->type != TPIPE)
                     45:                return exchild(t, flags); /* run in sub-process */
                     46: 
                     47:        newenv(E_EXEC);
                     48:        if (trap)
                     49:                runtraps();
                     50:  
                     51:        if (t->ioact != NULL || t->type == TPIPE) {
                     52:                e.savefd = alloc(sizeofN(short, NUFILE), ATEMP);
                     53:                for (i = 0; i < NUFILE; i++)
                     54:                        e.savefd[i] = 0; /* not redirected */
                     55:        }
                     56: 
                     57:        /* do redirection, to be restored in quitenv() */
                     58:        if (t->ioact != NULL)
                     59:                for (iowp = t->ioact; *iowp != NULL; iowp++) {
                     60:                        if ((flags&XPIPEI) && (*iowp)->unit == 0 ||
                     61:                            (flags&XPIPEO) && (*iowp)->unit == 1)
                     62:                                errorf("attempt to redirect fd 0/1 in pipe\n");
                     63:                        iosetup(*iowp);
                     64:                }
                     65: 
                     66:        switch(t->type) {
                     67:          case TCOM:
                     68:                e.type = E_TCOM;
                     69:                rv = comexec(t, eval(t->vars, DOTILDE),
                     70:                             eval(t->args, DOBLANK|DOGLOB|DOTILDE), flags);
                     71:                break;
                     72: 
                     73:          case TPAREN:
                     74:                rv = execute(t->left, flags|XFORK);
                     75:                break;
                     76: 
                     77:          case TPIPE:
                     78:                flags |= XFORK;
                     79:                e.savefd[0] = savefd(0);
                     80:                e.savefd[1] = savefd(1);
                     81:                flags |= XPIPEO;
                     82:                (void) dup2(e.savefd[0], 0); /* stdin of first */
                     83:                while (t->type == TPIPE) {
                     84:                        openpipe(pv);
                     85:                        (void) dup2(pv[1], 1);  /* stdout of curr */
                     86:                        exchild(t->left, flags);
                     87:                        (void) dup2(pv[0], 0);  /* stdin of next */
                     88:                        closepipe(pv);
                     89:                        flags |= XPIPEI;
                     90:                        t = t->right;
                     91:                }
                     92:                flags &= ~ XPIPEO;
                     93:                (void) dup2(e.savefd[1], 1); /* stdout of last */
                     94:                exchild(t, flags);
                     95:                (void) dup2(e.savefd[0], 0); /* close pipe in */
                     96:                /*
                     97:                 * added background check to avoid waiting on unwanted pipelines
                     98:                 */
                     99:                if (!(flags & XBGND))
                    100:                        rv = waitlast();
                    101:                break;
                    102: 
                    103:          case TLIST:
                    104:                while (t->type == TLIST) {
                    105:                        execute(t->left, 0);
                    106:                        t = t->right;
                    107:                }
                    108:                rv = execute(t, 0);
                    109:                break;
                    110: 
                    111:          case TASYNC:
                    112:                rv = execute(t->left, flags|XBGND|XFORK);
                    113:                break;
                    114: 
                    115:          case TOR:
                    116:          case TAND:
                    117:                rv = execute(t->left, 0);
                    118:                if (t->right != NULL && (rv == 0) == (t->type == TAND))
                    119:                        rv = execute(t->right, 0);
                    120:                break;
                    121: 
                    122:          case TFOR:
                    123:                e.type = E_LOOP;
                    124:                ap = (t->vars != NULL) ?
                    125:                        eval(t->vars, DOBLANK|DOGLOB|DOTILDE) : e.loc->argv + 1;
                    126:                while ((i = setjmp(e.jbuf)))
                    127:                        if (i == LBREAK)
                    128:                                goto Break1;
                    129:                while (*ap != NULL) {
                    130:                        setstr(global(t->str), *ap++);
                    131:                        rv = execute(t->left, 0);
                    132:                }
                    133:          Break1:
                    134:                break;
                    135: 
                    136:          case TWHILE:
                    137:          case TUNTIL:
                    138:                e.type = E_LOOP;
                    139:                while ((i = setjmp(e.jbuf)))
                    140:                        if (i == LBREAK)
                    141:                                goto Break2;
                    142:                while ((execute(t->left, 0) == 0) == (t->type == TWHILE))
                    143:                        rv = execute(t->right, 0);
                    144:          Break2:
                    145:                break;
                    146: 
                    147:          case TIF:
                    148:          case TELIF:
                    149:                if (t->right == NULL)
                    150:                        break;  /* should be error */
                    151:                rv = execute(t->left, 0) == 0 ?
                    152:                        execute(t->right->left, 0) :
                    153:                        execute(t->right->right, 0);
                    154:                break;
                    155: 
                    156:          case TCASE:
                    157:                cp = evalstr(t->str, 0);
                    158:                for (t = t->left; t != NULL && t->type == TPAT; t = t->right)
                    159:                    for (ap = t->vars; *ap; ap++)
                    160:                        if ((s = evalstr(*ap, DOPAT)) && gmatch(cp, s))
                    161:                                goto Found;
                    162:                break;
                    163:          Found:
                    164:                rv = execute(t->left, 0);
                    165:                break;
                    166: 
                    167:          case TBRACE:
                    168:                rv = execute(t->left, 0);
                    169:                break;
                    170: 
                    171:          case TFUNCT:
                    172:                rv = define(t->str, t->left);
                    173:                break;
                    174: 
                    175:          case TTIME:
                    176:                rv = timex(t, flags);
                    177:                break;
                    178: 
                    179:          case TEXEC:           /* an eval'd TCOM */
                    180:                s = t->args[0];
                    181:                ap = makenv();
                    182: #if _MINIX || COHERENT                 /* no F_SETFD close-on-exec */
                    183:                for (i = 10; i < 20; i++)
                    184:                        close(i);
                    185: #endif
                    186:                execve(t->str, t->args, ap);
                    187:                if (errno == ENOEXEC) {
                    188:                        *t->args-- = t->str;
                    189:                        *t->args = s;
                    190:                        execve(SHELL, t->args, ap);
                    191:                        errorf("No shell\n");
                    192:                }
                    193:                errorf("%s: %s\n", s, strerror(errno));
                    194:        }
                    195: 
                    196:        quitenv();              /* restores IO */
                    197:        if (e.interactive) {    /* flush stdout, shlout */
                    198:                fflush(shf[1]);
                    199:                fflush(shf[2]);
                    200:        }
                    201:        if ((flags&XEXEC))
                    202:                exit(rv);       /* exit child */
                    203:        return rv;
                    204: }
                    205: 
                    206: /*
                    207:  * execute simple command
                    208:  */
                    209: 
                    210: static int
                    211: comexec(t, vp, ap, flags)
                    212:        struct op *t;
                    213:        register char **ap, **vp;
                    214:        int flags;
                    215: {
                    216:        int i;
                    217:        int rv = 0;
                    218:        register char *cp;
                    219:        register struct tbl *tp = NULL;
                    220:        register struct block *l;
                    221:        static struct op texec = {TEXEC};
                    222:        extern int c_exec(), c_builtin();
                    223: 
                    224:        if (flag[FXTRACE])
                    225:                echo(vp, ap);
                    226: 
                    227:        /* create new variable/function block */
                    228:        l = alloc(sizeof(struct block), ATEMP);
                    229:        l->next = e.loc; e.loc = l;
                    230:        newblock();
                    231: 
                    232:  Doexec:
                    233:        if ((cp = *ap) == NULL)
                    234:                cp = ":";
                    235:        tp = findcom(cp, 1);
                    236: 
                    237:        switch (tp->type) {
                    238:          case CSHELL:                  /* shell built-in */
                    239:                while (tp->val.f == c_builtin) {
                    240:                        if ((cp = *++ap) == NULL)
                    241:                                break;
                    242:                        tp = tsearch(&builtins, cp, hash(cp));
                    243:                        if (tp == NULL)
                    244:                                errorf("%s: not builtin\n", cp);
                    245:                }
                    246:                if (tp->val.f == c_exec) {
                    247:                        if (*++ap == NULL) {
                    248:                                e.savefd = NULL; /* don't restore redirection */
                    249:                                break;
                    250:                        }
                    251:                        flags |= XEXEC;
                    252:                        goto Doexec;
                    253:                }
                    254:                if ((tp->flag&TRACE))
                    255:                        e.loc = l->next; /* no local block */
                    256:                i = (tp->flag&TRACE) ? 0 : LOCAL;
                    257:                while (*vp != NULL)
                    258:                        (void) typeset(*vp++, i, 0);
                    259:                rv = (*tp->val.f)(ap);
                    260:                break;
                    261: 
                    262:        case CFUNC:                     /* function call */
                    263:                if (!(tp->flag&ISSET))
                    264:                        errorf("%s: undefined function", cp);
                    265:                l->argv = ap;
                    266:                for (i = 0; *ap++ != NULL; i++)
                    267:                        ;
                    268:                l->argc = i - 1;
                    269:                resetopts();
                    270:                while (*vp != NULL)
                    271:                        (void) typeset(*vp++, LOCAL, 0);
                    272:                e.type = E_FUNC;
                    273:                if (setjmp(e.jbuf))
                    274:                        rv = exstat; /* return # */
                    275:                else
                    276:                        rv = execute(tp->val.t, 0);
                    277:                break;
                    278: 
                    279:        case CEXEC:             /* executable command */
                    280:                if (!(tp->flag&ISSET)) {
                    281:                        shellf("%s: not found\n", cp);
                    282:                        rv = 1;
                    283:                        break;
                    284:                }
                    285: 
                    286:                /* set $_ to program's full path */
                    287:                setstr(typeset("_", LOCAL|EXPORT, 0), tp->val.s);
                    288:                while (*vp != NULL)
                    289:                        (void) typeset(*vp++, LOCAL|EXPORT, 0);
                    290: 
                    291:                if ((flags&XEXEC)) {
                    292:                        j_exit();
                    293: #if !COHERENT
                    294:                        signal(SIGINT, SIG_DFL);
                    295:                        signal(SIGQUIT, SIG_DFL);
                    296: #endif
                    297:                }
                    298: 
                    299:                /* to fork we set up a TEXEC node and call execute */
                    300:                texec.left = t; /* for tprint */
                    301:                texec.str = tp->val.s;
                    302:                texec.args = ap;
                    303:                rv = exchild(&texec, flags);
                    304:                break;
                    305:        }
                    306:        if (rv != 0 && flag[FERREXIT])
                    307:                leave(rv);
                    308:        return (exstat = rv);
                    309: }
                    310: 
                    311: int
                    312: shcomexec(wp)
                    313:        register char **wp;
                    314: {
                    315:        register struct tbl *tp;
                    316: 
                    317:        tp = tsearch(&builtins, *wp, hash(*wp));
                    318:        if (tp == NULL)
                    319:                errorf("%s: shcomexec botch\n", *wp);
                    320:        return (*tp->val.f)(wp);
                    321: }
                    322: 
                    323: /*
                    324:  * define function
                    325:  */
                    326: int
                    327: define(name, t)
                    328:        char    *name;
                    329:        struct op *t;
                    330: {
                    331:        register struct block *l;
                    332:        register struct tbl *tp;
                    333: 
                    334:        for (l = e.loc; l != NULL; l = l->next) {
                    335:                lastarea = &l->area;
                    336:                tp = tsearch(&l->funs, name, hash(name));
                    337:                if (tp != NULL && (tp->flag&DEFINED))
                    338:                        break;
                    339:                if (l->next == NULL) {
                    340:                        tp = tenter(&l->funs, name, hash(name));
                    341:                        tp->flag = DEFINED|FUNCT;
                    342:                        tp->type = CFUNC;
                    343:                }
                    344:        }
                    345: 
                    346:        if ((tp->flag&ALLOC))
                    347:                tfree(tp->val.t, lastarea);
                    348:        tp->flag &= ~(ISSET|ALLOC);
                    349: 
                    350:        if (t == NULL)          /* undefine */
                    351:                return 0;
                    352: 
                    353:        tp->val.t = tcopy(t, lastarea);
                    354:        tp->flag |= (ISSET|ALLOC);
                    355: 
                    356:        return 0;
                    357: }
                    358: 
                    359: /*
                    360:  * add builtin
                    361:  */
                    362: builtin(name, func)
                    363:        char *name;
                    364:        int (*func)();
                    365: {
                    366:        register struct tbl *tp;
                    367:        int flag = DEFINED;
                    368: 
                    369:        if (*name == '=') {             /* sets keyword variables */
                    370:                name++;
                    371:                flag |= TRACE;  /* command does variable assignment */
                    372:        }
                    373: 
                    374:        tp = tenter(&builtins, name, hash(name));
                    375:        tp->flag |= flag;
                    376:        tp->type = CSHELL;
                    377:        tp->val.f = func;
                    378: }
                    379: 
                    380: /*
                    381:  * find command
                    382:  * either function, hashed command, or built-in (in that order)
                    383:  */
                    384: struct tbl *
                    385: findcom(name, insert)
                    386:        char    *name;
                    387:        int     insert;                 /* insert if not found */
                    388: {
                    389:        register struct block *l = e.loc;
                    390:        unsigned int h = hash(name);
                    391:        register struct tbl *tp = NULL;
                    392:        static struct tbl temp;
                    393: 
                    394:        if (strchr(name, '/') != NULL) {
                    395:                tp = &temp;
                    396:                tp->type = CEXEC;
                    397:                tp->flag = 0;   /* make ~ISSET */
                    398:                goto Search;
                    399:        }
                    400:        for (l = e.loc; l != NULL; l = l->next) {
                    401:                tp = tsearch(&l->funs, name, h);
                    402:                if (tp != NULL && (tp->flag&DEFINED))
                    403:                        break;
                    404:        }
                    405:        if (tp == NULL)
                    406:                tp = tsearch(&commands, name, h);
                    407:        if (tp == NULL)
                    408:                tp = tsearch(&builtins, name, h);
                    409:        if (tp == NULL && insert) {
                    410:                tp = tenter(&commands, name, h);
                    411:                tp->type = CEXEC;
                    412:                tp->flag = DEFINED;
                    413:        }
                    414:   Search:
                    415:        if (tp->type == CEXEC && !(tp->flag&ISSET)) {
                    416:                if (!flag[FHASHALL]) {
                    417:                        tp = &temp;
                    418:                        tp->type = CEXEC;
                    419:                        tp->flag = 0;   /* make ~ISSET */
                    420:                }
                    421:                name = search(name, path, 1);
                    422:                if (name != NULL) {
                    423:                        tp->val.s = strsave(name,
                    424:                                            (tp == &temp) ? ATEMP : APERM);
                    425:                        tp->flag |= ISSET|ALLOC;
                    426:                }
                    427:        }
                    428:        return tp;
                    429: }
                    430: 
                    431: /*
                    432:  * flush executable commands with relative paths
                    433:  */
                    434: flushcom(all)
                    435:        int all;                /* just relative or all */
                    436: {
                    437:        register struct tbl *tp;
                    438: 
                    439:        for (twalk(&commands); (tp = tnext()) != NULL; )
                    440:                if ((tp->flag&ISSET) && (all || tp->val.s[0] != '/')) {
                    441:                        if ((tp->flag&ALLOC))
                    442:                                afree(tp->val.s, commands.areap);
                    443:                        tp->flag = DEFINED; /* make ~ISSET */
                    444:                }
                    445: }
                    446: 
                    447: /*
                    448:  * search for command with PATH
                    449:  */
                    450: char *
                    451: search(name, path, mode)
                    452:        char *name, *path;
                    453:        int mode;               /* 0: readable; 1: executable */
                    454: {
                    455:        register int i;
                    456:        register char *sp, *tp;
                    457:        int     colon = FALSE;
                    458: 
                    459:        if (strchr(name, '/'))
                    460:                return (eaccess(name, mode) == 0) ? name : NULL;
                    461: 
                    462:        sp = path;
                    463:        do {
                    464:                tp = line;
                    465:                colon = FALSE;
                    466:                for (; *sp != '\0'; tp++) {
                    467:                        if ((*tp = *sp++) == ':') {
                    468:                                colon = TRUE;
                    469:                                break;
                    470:                        }
                    471:                }
                    472:                if (tp != line)
                    473:                        *tp++ = '/';
                    474:                for (i = 0; (*tp++ = name[i++]) != '\0';)
                    475:                        ;
                    476:                i = eaccess(line, mode);
                    477:                if (i == 0)
                    478:                        return line;
                    479:                /* what should we do about EACCES? */
                    480:        } while (*sp != '\0' || colon);
                    481:        return NULL;
                    482: }
                    483: 
                    484: /*
                    485:  * set up redirection, saving old fd's in e.savefd
                    486:  */
                    487: static void
                    488: iosetup(iop)
                    489:        register struct ioword *iop;
                    490: {
                    491:        register int u = -1;
                    492:        char *cp, *msg;
                    493:        extern long lseek();
                    494: 
                    495:        if (iop->unit == 0 || iop->unit == 1 || iop->unit == 2)
                    496:                e.interactive = 0;
                    497:        e.savefd[iop->unit] = savefd(iop->unit);
                    498: 
                    499:        msg = iop->flag&(IOREAD|IOHERE)? "open": "create";
                    500:        cp = iop->name;
                    501:        if (!(iop->flag & IOHERE))
                    502:                cp = evalstr(cp, DOTILDE);
                    503:        if (iop->flag&IODUP)
                    504:                iop->flag &= ~(IOREAD|IOWRITE); /* todo: lex.c */
                    505: 
                    506:        switch (iop->flag) {
                    507:          case IOREAD:
                    508:                u = open(cp, 0);
                    509:                break;
                    510: 
                    511:          case IOHERE:
                    512:          case IOHERE|IOXHERE:
                    513:                u = herein(cp, iop->flag&IOXHERE);
                    514:                /* cp may have wrong name */
                    515:                break;
                    516: 
                    517:          case IOWRITE|IOCAT:
                    518:                if ((u = open(cp, 1)) >= 0) {
                    519:                        (void) lseek(u, (long)0, 2);
                    520:                        break;
                    521:                }
                    522:                /* FALLTHROUGH */
                    523:          case IOWRITE:
                    524:                u = creat(cp, 0666);
                    525:                break;
                    526: 
                    527:          case IODUP:
                    528:                if (*cp == '-')
                    529:                        close(iop->unit);
                    530:                else
                    531:                if (digit(*cp))
                    532:                        u = *cp - '0';
                    533:                else
                    534:                        errorf("%s: illegal >& argument\n", cp);
                    535:                break;
                    536:        }
                    537:        if (u < 0)
                    538:                errorf("%s: cannot %s\n", cp, msg);
                    539:        if (u != iop->unit) {
                    540:                (void) dup2(u, iop->unit);
                    541:                if (iop->flag != IODUP)
                    542:                        close(u);
                    543:        }
                    544: 
                    545:        fopenshf(iop->unit);
                    546: }
                    547: 
                    548: /*
                    549:  * open here document temp file.
                    550:  * if unquoted here, expand here temp file into second temp file.
                    551:  */
                    552: static int
                    553: herein(hname, sub)
                    554:        char *hname;
                    555:        int sub;
                    556: {
                    557:        int fd;
                    558:        FILE * Volatile f = NULL;
                    559: 
                    560:        f = fopen(hname, "r");
                    561:        if (f == NULL)
                    562:                return -1;
                    563:        setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
                    564: 
                    565:        if (sub) {
                    566:                char *cp;
                    567:                struct source *s;
                    568:                struct temp *h;
                    569: 
                    570:                newenv(E_ERRH);
                    571:                if (setjmp(e.jbuf)) {
                    572:                        if (f != NULL)
                    573:                                fclose(f);
                    574:                        quitenv();
                    575:                        return -1; /* todo: error()? */
                    576:                }
                    577: 
                    578:                /* set up yylex input from here file */
                    579:                s = pushs(SFILE);
                    580:                s->u.file = f;
                    581:                source = s;
                    582:                if (yylex(ONEWORD) != LWORD)
                    583:                        errorf("exec:herein error\n");
                    584:                cp = evalstr(yylval.cp, 0);
                    585: 
                    586:                /* write expanded input to another temp file */
                    587:                h = maketemp(ATEMP);
                    588:                h->next = e.temps; e.temps = h;
                    589:                if (h == NULL)
                    590:                        error();
                    591:                f = fopen(h->name, "w+");
                    592:                if (f == NULL)
                    593:                        error();
                    594:                setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
                    595:                fputs(cp, f);
                    596:                rewind(f);
                    597: 
                    598:                quitenv();
                    599:        }
                    600:        fd = dup(fileno(f));
                    601:        fclose(f);
                    602:        return fd;
                    603: }
                    604: 
                    605: static void
                    606: echo(vp, ap)
                    607:        register char **vp, **ap;
                    608: {
                    609:        shellf("+");
                    610:        while (*vp != NULL)
                    611:                shellf(" %s", *vp++);
                    612:        while (*ap != NULL)
                    613:                shellf(" %s", *ap++);
                    614:        shellf("\n");
                    615: }
                    616: 

unix.superglobalmegacorp.com

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