Annotation of coherent/g/usr/bin/ksh/exec.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * execute command tree
                      3:  */
                      4: 
                      5: static char *RCSid = "$Header: exec.c,v 3.1 88/11/03 09:15:46 egisin Exp $";
                      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 <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    0
                    188:                if (errno == ENOEXEC) {
                    189: #else
                    190:                if (errno == -1 || errno == ENOEXEC) {
                    191: #endif
                    192:                        *t->args-- = t->str;
                    193:                        *t->args = s;
                    194:                        execve(SHELL, t->args, ap);
                    195:                        errorf("No shell\n");
                    196:                }
                    197:                errorf("%s: %s\n", s, strerror(errno));
                    198:        }
                    199: 
                    200:        quitenv();              /* restores IO */
                    201:        if (e.interactive) {    /* flush stdout, shlout */
                    202:                fflush(shf[1]);
                    203:                fflush(shf[2]);
                    204:        }
                    205:        if ((flags&XEXEC))
                    206:                exit(rv);       /* exit child */
                    207:        return rv;
                    208: }
                    209: 
                    210: /*
                    211:  * execute simple command
                    212:  */
                    213: 
                    214: static int
                    215: comexec(t, vp, ap, flags)
                    216:        struct op *t;
                    217:        register char **ap, **vp;
                    218:        int flags;
                    219: {
                    220:        int i;
                    221:        int rv = 0;
                    222:        register char *cp;
                    223:        register struct tbl *tp = NULL;
                    224:        register struct block *l;
                    225:        static struct op texec = {TEXEC};
                    226:        extern int c_exec(), c_builtin();
                    227: 
                    228:        if (flag[FXTRACE])
                    229:                echo(vp, ap);
                    230: 
                    231:        /* create new variable/function block */
                    232:        l = alloc(sizeof(struct block), ATEMP);
                    233:        l->next = e.loc; e.loc = l;
                    234:        newblock();
                    235: 
                    236:  Doexec:
                    237:        if ((cp = *ap) == NULL)
                    238:                cp = ":";
                    239:        tp = findcom(cp, 1);
                    240: 
                    241:        switch (tp->type) {
                    242:          case CSHELL:                  /* shell built-in */
                    243:                while (tp->val.f == c_builtin) {
                    244:                        if ((cp = *++ap) == NULL)
                    245:                                break;
                    246:                        tp = tsearch(&builtins, cp, hash(cp));
                    247:                        if (tp == NULL)
                    248:                                errorf("%s: not builtin\n", cp);
                    249:                }
                    250:                if (tp->val.f == c_exec) {
                    251:                        if (*++ap == NULL) {
                    252:                                e.savefd = NULL; /* don't restore redirection */
                    253:                                break;
                    254:                        }
                    255:                        flags |= XEXEC;
                    256:                        goto Doexec;
                    257:                }
                    258:                if ((tp->flag&TRACE))
                    259:                        e.loc = l->next; /* no local block */
                    260:                i = (tp->flag&TRACE) ? 0 : LOCAL;
                    261:                while (*vp != NULL)
                    262:                        (void) typeset(*vp++, i, 0);
                    263:                rv = (*tp->val.f)(ap);
                    264:                break;
                    265: 
                    266:        case CFUNC:                     /* function call */
                    267:                if (!(tp->flag&ISSET))
                    268:                        errorf("%s: undefined function", cp);
                    269:                l->argv = ap;
                    270:                for (i = 0; *ap++ != NULL; i++)
                    271:                        ;
                    272:                l->argc = i - 1;
                    273:                resetopts();
                    274:                while (*vp != NULL)
                    275:                        (void) typeset(*vp++, LOCAL, 0);
                    276:                e.type = E_FUNC;
                    277:                if (setjmp(e.jbuf))
                    278:                        rv = exstat; /* return # */
                    279:                else
                    280:                        rv = execute(tp->val.t, 0);
                    281:                break;
                    282: 
                    283:        case CEXEC:             /* executable command */
                    284:                if (!(tp->flag&ISSET)) {
                    285:                        shellf("%s: not found\n", cp);
                    286:                        rv = 1;
                    287:                        break;
                    288:                }
                    289: 
                    290:                /* set $_ to program's full path */
                    291:                setstr(typeset("_", LOCAL|EXPORT, 0), tp->val.s);
                    292:                while (*vp != NULL)
                    293:                        (void) typeset(*vp++, LOCAL|EXPORT, 0);
                    294: 
                    295:                if ((flags&XEXEC)) {
                    296:                        j_exit();
                    297: #if !COHERENT
                    298:                        signal(SIGINT, SIG_DFL);
                    299:                        signal(SIGQUIT, SIG_DFL);
                    300: #endif
                    301:                }
                    302: 
                    303:                /* to fork we set up a TEXEC node and call execute */
                    304:                texec.left = t; /* for tprint */
                    305:                texec.str = tp->val.s;
                    306:                texec.args = ap;
                    307:                rv = exchild(&texec, flags);
                    308:                break;
                    309:        }
                    310:        if (rv != 0 && flag[FERREXIT])
                    311:                leave(rv);
                    312:        return (exstat = rv);
                    313: }
                    314: 
                    315: int
                    316: shcomexec(wp)
                    317:        register char **wp;
                    318: {
                    319:        register struct tbl *tp;
                    320: 
                    321:        tp = tsearch(&builtins, *wp, hash(*wp));
                    322:        if (tp == NULL)
                    323:                errorf("%s: shcomexec botch\n", *wp);
                    324:        return (*tp->val.f)(wp);
                    325: }
                    326: 
                    327: /*
                    328:  * define function
                    329:  */
                    330: int
                    331: define(name, t)
                    332:        char    *name;
                    333:        struct op *t;
                    334: {
                    335:        register struct block *l;
                    336:        register struct tbl *tp;
                    337: 
                    338:        for (l = e.loc; l != NULL; l = l->next) {
                    339:                lastarea = &l->area;
                    340:                tp = tsearch(&l->funs, name, hash(name));
                    341:                if (tp != NULL && (tp->flag&DEFINED))
                    342:                        break;
                    343:                if (l->next == NULL) {
                    344:                        tp = tenter(&l->funs, name, hash(name));
                    345:                        tp->flag = DEFINED|FUNCT;
                    346:                        tp->type = CFUNC;
                    347:                }
                    348:        }
                    349: 
                    350:        if ((tp->flag&ALLOC))
                    351:                tfree(tp->val.t, lastarea);
                    352:        tp->flag &= ~(ISSET|ALLOC);
                    353: 
                    354:        if (t == NULL)          /* undefine */
                    355:                return 0;
                    356: 
                    357:        tp->val.t = tcopy(t, lastarea);
                    358:        tp->flag |= (ISSET|ALLOC);
                    359: 
                    360:        return 0;
                    361: }
                    362: 
                    363: /*
                    364:  * add builtin
                    365:  */
                    366: builtin(name, func)
                    367:        char *name;
                    368:        int (*func)();
                    369: {
                    370:        register struct tbl *tp;
                    371:        int flag = DEFINED;
                    372: 
                    373:        if (*name == '=') {             /* sets keyword variables */
                    374:                name++;
                    375:                flag |= TRACE;  /* command does variable assignment */
                    376:        }
                    377: 
                    378:        tp = tenter(&builtins, name, hash(name));
                    379:        tp->flag |= flag;
                    380:        tp->type = CSHELL;
                    381:        tp->val.f = func;
                    382: }
                    383: 
                    384: /*
                    385:  * find command
                    386:  * either function, hashed command, or built-in (in that order)
                    387:  */
                    388: struct tbl *
                    389: findcom(name, insert)
                    390:        char    *name;
                    391:        int     insert;                 /* insert if not found */
                    392: {
                    393:        register struct block *l = e.loc;
                    394:        unsigned int h = hash(name);
                    395:        register struct tbl *tp = NULL;
                    396:        static struct tbl temp;
                    397: 
                    398:        if (strchr(name, '/') != NULL) {
                    399:                tp = &temp;
                    400:                tp->type = CEXEC;
                    401:                tp->flag = 0;   /* make ~ISSET */
                    402:                goto Search;
                    403:        }
                    404:        for (l = e.loc; l != NULL; l = l->next) {
                    405:                tp = tsearch(&l->funs, name, h);
                    406:                if (tp != NULL && (tp->flag&DEFINED))
                    407:                        break;
                    408:        }
                    409:        if (tp == NULL)
                    410:                tp = tsearch(&commands, name, h);
                    411:        if (tp == NULL)
                    412:                tp = tsearch(&builtins, name, h);
                    413:        if (tp == NULL && insert) {
                    414:                tp = tenter(&commands, name, h);
                    415:                tp->type = CEXEC;
                    416:                tp->flag = DEFINED;
                    417:        }
                    418:   Search:
                    419:        if (tp->type == CEXEC && !(tp->flag&ISSET)) {
                    420:                if (!flag[FHASHALL]) {
                    421:                        tp = &temp;
                    422:                        tp->type = CEXEC;
                    423:                        tp->flag = 0;   /* make ~ISSET */
                    424:                }
                    425:                name = search(name, path, 1);
                    426:                if (name != NULL) {
                    427:                        tp->val.s = strsave(name,
                    428:                                            (tp == &temp) ? ATEMP : APERM);
                    429:                        tp->flag |= ISSET|ALLOC;
                    430:                }
                    431:        }
                    432:        return tp;
                    433: }
                    434: 
                    435: /*
                    436:  * flush executable commands with relative paths
                    437:  */
                    438: flushcom(all)
                    439:        int all;                /* just relative or all */
                    440: {
                    441:        register struct tbl *tp;
                    442: 
                    443:        for (twalk(&commands); (tp = tnext()) != NULL; )
                    444:                if ((tp->flag&ISSET) && (all || tp->val.s[0] != '/')) {
                    445:                        if ((tp->flag&ALLOC))
                    446:                                afree(tp->val.s, commands.areap);
                    447:                        tp->flag = DEFINED; /* make ~ISSET */
                    448:                }
                    449: }
                    450: 
                    451: /*
                    452:  * search for command with PATH
                    453:  */
                    454: char *
                    455: search(name, path, mode)
                    456:        char *name, *path;
                    457:        int mode;               /* 0: readable; 1: executable */
                    458: {
                    459:        register int i;
                    460:        register char *sp, *tp;
                    461:        int     colon = FALSE;
                    462: 
                    463:        if (strchr(name, '/'))
                    464:                return (eaccess(name, mode) == 0) ? name : NULL;
                    465: 
                    466:        sp = path;
                    467:        do {
                    468:                tp = line;
                    469:                colon = FALSE;
                    470:                for (; *sp != '\0'; tp++) {
                    471:                        if ((*tp = *sp++) == ':') {
                    472:                                colon = TRUE;
                    473:                                break;
                    474:                        }
                    475:                }
                    476:                if (tp != line)
                    477:                        *tp++ = '/';
                    478:                for (i = 0; (*tp++ = name[i++]) != '\0';)
                    479:                        ;
                    480:                i = eaccess(line, mode);
                    481:                if (i == 0)
                    482:                        return line;
                    483:                /* what should we do about EACCES? */
                    484:        } while (*sp != '\0' || colon);
                    485:        return NULL;
                    486: }
                    487: 
                    488: /*
                    489:  * set up redirection, saving old fd's in e.savefd
                    490:  */
                    491: static void
                    492: iosetup(iop)
                    493:        register struct ioword *iop;
                    494: {
                    495:        register int u = -1;
                    496:        char *cp, *msg;
                    497:        extern long lseek();
                    498: 
                    499:        if (iop->unit == 0 || iop->unit == 1 || iop->unit == 2)
                    500:                e.interactive = 0;
                    501:        e.savefd[iop->unit] = savefd(iop->unit);
                    502: 
                    503:        msg = iop->flag&(IOREAD|IOHERE)? "open": "create";
                    504:        cp = iop->name;
                    505:        if (!(iop->flag & IOHERE))
                    506:                cp = evalstr(cp, DOTILDE);
                    507:        if (iop->flag&IODUP)
                    508:                iop->flag &= ~(IOREAD|IOWRITE); /* todo: lex.c */
                    509: 
                    510:        switch (iop->flag) {
                    511:          case IOREAD:
                    512:                u = open(cp, 0);
                    513:                break;
                    514: 
                    515:          case IOHERE:
                    516:          case IOHERE|IOXHERE:
                    517:                u = herein(cp, iop->flag&IOXHERE);
                    518:                /* cp may have wrong name */
                    519:                break;
                    520: 
                    521:          case IOWRITE|IOCAT:
                    522:                if ((u = open(cp, 1)) >= 0) {
                    523:                        (void) lseek(u, (long)0, 2);
                    524:                        break;
                    525:                }
                    526:                /* FALLTHROUGH */
                    527:          case IOWRITE:
                    528:                u = creat(cp, 0666);
                    529:                break;
                    530: 
                    531:          case IODUP:
                    532:                if (*cp == '-')
                    533:                        close(iop->unit);
                    534:                else
                    535:                if (digit(*cp))
                    536:                        u = *cp - '0';
                    537:                else
                    538:                        errorf("%s: illegal >& argument\n", cp);
                    539:                break;
                    540:        }
                    541:        if (u < 0)
                    542:                errorf("%s: cannot %s\n", cp, msg);
                    543:        if (u != iop->unit) {
                    544:                (void) dup2(u, iop->unit);
                    545:                if (iop->flag != IODUP)
                    546:                        close(u);
                    547:        }
                    548: 
                    549:        fopenshf(iop->unit);
                    550: }
                    551: 
                    552: /*
                    553:  * open here document temp file.
                    554:  * if unquoted here, expand here temp file into second temp file.
                    555:  */
                    556: static int
                    557: herein(hname, sub)
                    558:        char *hname;
                    559:        int sub;
                    560: {
                    561:        int fd;
                    562:        FILE * Volatile f = NULL;
                    563: 
                    564:        f = fopen(hname, "r");
                    565:        if (f == NULL)
                    566:                return -1;
                    567:        setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
                    568: 
                    569:        if (sub) {
                    570:                char *cp;
                    571:                struct source *s;
                    572:                struct temp *h;
                    573: 
                    574:                newenv(E_ERRH);
                    575:                if (setjmp(e.jbuf)) {
                    576:                        if (f != NULL)
                    577:                                fclose(f);
                    578:                        quitenv();
                    579:                        return -1; /* todo: error()? */
                    580:                }
                    581: 
                    582:                /* set up yylex input from here file */
                    583:                s = pushs(SFILE);
                    584:                s->u.file = f;
                    585:                source = s;
                    586:                if (yylex(ONEWORD) != LWORD)
                    587:                        errorf("exec:herein error\n");
                    588:                cp = evalstr(yylval.cp, 0);
                    589: 
                    590:                /* write expanded input to another temp file */
                    591:                h = maketemp(ATEMP);
                    592:                h->next = e.temps; e.temps = h;
                    593:                if (h == NULL)
                    594:                        error();
                    595:                f = fopen(h->name, "w+");
                    596:                if (f == NULL)
                    597:                        error();
                    598:                setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
                    599:                fputs(cp, f);
                    600:                rewind(f);
                    601: 
                    602:                quitenv();
                    603:        }
                    604:        fd = dup(fileno(f));
                    605:        fclose(f);
                    606:        return fd;
                    607: }
                    608: 
                    609: static void
                    610: echo(vp, ap)
                    611:        register char **vp, **ap;
                    612: {
                    613:        shellf("+");
                    614:        while (*vp != NULL)
                    615:                shellf(" %s", *vp++);
                    616:        while (*ap != NULL)
                    617:                shellf(" %s", *ap++);
                    618:        shellf("\n");
                    619: }
                    620: 

unix.superglobalmegacorp.com

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