Annotation of coherent/g/usr/bin/ksh/exec.c, revision 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.