Annotation of coherent/d/bin/sh/exec3.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * sh/exec3.c
        !             3:  * Bourne shell.
        !             4:  * Builtin commands.
        !             5:  */
        !             6: 
        !             7: #include "sh.h"
        !             8: #include <sys/times.h>
        !             9: #include <sys/const.h>         /* HZ defined here */
        !            10: 
        !            11: #define HOUR   (60L*60L*HZ)
        !            12: #define MINUTE (60L*HZ)
        !            13: #define SECOND HZ
        !            14: 
        !            15: char   *cd();
        !            16: 
        !            17: extern s_colon();
        !            18: extern s_dot();
        !            19: extern s_break();
        !            20: #define s_continue     s_break
        !            21: extern s_cd();
        !            22: extern s_dirs();
        !            23: extern s_eval();
        !            24: extern s_exec();
        !            25: extern s_exit();
        !            26: extern s_export();
        !            27: extern s_login();
        !            28: #define s_newgrp       s_login
        !            29: extern s_popd();
        !            30: extern s_pushd();
        !            31: extern s_read();
        !            32: #define s_readonly     s_export
        !            33: extern s_set();
        !            34: extern s_shift();
        !            35: extern s_times();
        !            36: extern s_trap();
        !            37: extern s_umask();
        !            38: extern s_wait();
        !            39: #define SNULL  ((int (*)())0)
        !            40: 
        !            41: typedef struct {
        !            42:        int     i_hash;
        !            43:        char    *i_name;
        !            44:        int     (*i_func)();
        !            45: } INLINE;
        !            46: 
        !            47: INLINE inls[] = {
        !            48:        0,      ":",            s_colon,
        !            49:        0,      ".",            s_dot,
        !            50:        0,      "break",        s_break,
        !            51:        0,      "continue",     s_continue,
        !            52:        0,      "cd",           s_cd,
        !            53:        0,      "dirs",         s_dirs,
        !            54:        0,      "eval",         s_eval,
        !            55:        0,      "exec",         s_exec,
        !            56:        0,      "exit",         s_exit,
        !            57:        0,      "export",       s_export,
        !            58:        0,      "login",        s_login,
        !            59:        0,      "newgrp",       s_newgrp,
        !            60:        0,      "popd",         s_popd,
        !            61:        0,      "pushd",        s_pushd,
        !            62:        0,      "read",         s_read,
        !            63:        0,      "readonly",     s_readonly,
        !            64:        0,      "set",          s_set,
        !            65:        0,      "shift",        s_shift,
        !            66:        0,      "times",        s_times,
        !            67:        0,      "trap",         s_trap,
        !            68:        0,      "umask",        s_umask,
        !            69:        0,      "wait",         s_wait,
        !            70:        0,      NULL,           SNULL
        !            71: };
        !            72: 
        !            73: inline()
        !            74: {
        !            75:        register int (*s_func)();
        !            76:        register INLINE *ip;
        !            77:        register int ahash;
        !            78:        int pid, status;
        !            79: 
        !            80:        if (inls[0].i_hash==0)
        !            81:                for (ip=inls; ip->i_name!=NULL; ip++)
        !            82:                        ip->i_hash = ihash(ip->i_name);
        !            83:        if (nargv[0] == NULL)
        !            84:                return 0;
        !            85:        ahash = ihash(nargv[0]);
        !            86:        for (ip=inls; ip->i_name!=NULL; ip++)
        !            87:                if (ip->i_hash==ahash && strcmp(nargv[0], ip->i_name)==0)
        !            88:                        break;
        !            89:        if ((s_func=ip->i_func) == SNULL)
        !            90:                return 0;
        !            91:        if (*niovp != NULL && s_func != s_exec) {
        !            92:                /* Redirection with built-in command. */
        !            93:                /* Allowed only with eval, export, readonly, set, times. */
        !            94:                if (s_func != s_eval
        !            95:                 && s_func != s_export
        !            96:                 && s_func != s_set
        !            97:                 && s_func != s_times) {
        !            98:                        eredir();
        !            99:                        slret = 1;
        !           100:                        return 1;
        !           101:                }
        !           102:                if ((pid = clone()) == 0) {
        !           103:                        /* Perform redirection in child process. */
        !           104:                        if (redirect(niovp) < 0)
        !           105:                                slret = 1;
        !           106:                        else if (s_func == s_eval)
        !           107:                                slret = (*s_func)();
        !           108:                        else {
        !           109:                                /* Kludge stderr output to stdout. */
        !           110:                                dup2(1, 2);
        !           111:                                close(1);
        !           112:                                slret = (*s_func)();
        !           113:                        }
        !           114:                        exit(slret);
        !           115:                        /* NOTREACHED */
        !           116:                } else {
        !           117:                        /* Parent waits for child and takes its exit status. */
        !           118:                        while (wait(&status) != pid)
        !           119:                                ;
        !           120:                        slret = status >> 8;
        !           121:                }
        !           122:        } else
        !           123:                slret = (*s_func)();
        !           124:        return 1;
        !           125: }
        !           126: 
        !           127: ihash(cp)
        !           128: register char *cp;
        !           129: {
        !           130:        register int i;
        !           131:        for (i=0; *cp; i+=*cp++);
        !           132:        return i;
        !           133: }
        !           134: 
        !           135: /*
        !           136:  * Actual builtin functions.
        !           137:  */
        !           138: s_colon()
        !           139: {
        !           140:        return 0;
        !           141: }
        !           142: 
        !           143: s_dot()
        !           144: {
        !           145:        if (nargc==2) {
        !           146:                ffind(NULL);
        !           147:                if (ffind(vpath, nargv[1], 4))
        !           148:                        return session(SFILE, duplstr(strt, 0));
        !           149:                else {
        !           150:                        ecantfind(nargv[1]);
        !           151:                        return 1;
        !           152:                }
        !           153:        } else if (nargc==1)
        !           154:                return 0;
        !           155:        syntax();
        !           156:        return 1;
        !           157: }
        !           158: 
        !           159: s_break()
        !           160: {
        !           161:        register CON *cp;
        !           162:        register int t;
        !           163:        register int n;
        !           164:        int ret;
        !           165: 
        !           166:        ret = nargv[0][0]=='b' ? 2 : 1;
        !           167:        n = nargc>1 ? atoi(nargv[1]) : 1;
        !           168:        for (cp = sesp->s_con; cp; cp = cp->c_next) {
        !           169:                t = cp->c_node->n_type;
        !           170:                if ((t==NWHILE || t==NFOR || t==NUNTIL) && --n == 0) {
        !           171:                        sesp->s_con = cp;
        !           172:                        longjmp(cp->c_envl, ret);
        !           173:                        break;
        !           174:                }
        !           175:                freebuf(cp->c_bpp);
        !           176:        }
        !           177:        printe("%s out of bounds", ret==1 ? "Continue" : "Break");
        !           178: }
        !           179: 
        !           180: /* s_continue is overlaid with s_break */
        !           181: 
        !           182: s_cd()
        !           183: {
        !           184:        register char *dir;
        !           185: 
        !           186:        if ((dir = cd((nargc<2) ? vhome : nargv[1])) == NULL)
        !           187:                return -1;                      /* cd failed */
        !           188:        if (dstack[dstkp] != NULL)
        !           189:                sfree(dstack[dstkp]);
        !           190:        dstack[dstkp] = duplstr(dir, 1);        /* update dir stack */
        !           191:        return 0;
        !           192: }
        !           193: 
        !           194: s_dirs()
        !           195: {
        !           196:        register int i;
        !           197: 
        !           198:        for (i = dstkp; i >= 0; i--)
        !           199:                fprintf(stderr, "%s ", dstack[i]);
        !           200:        fputc('\n', stderr);
        !           201: }
        !           202: 
        !           203: s_eval()
        !           204: {
        !           205:        if (nargc>1)
        !           206:                return session(SARGV, ++nargv);
        !           207:        else
        !           208:                return 0;
        !           209: }
        !           210: 
        !           211: s_exec()
        !           212: {
        !           213:        if (redirect(niovp) < 0) {
        !           214:                if (nargc>1) {
        !           215:                        exit(1);
        !           216:                        NOTREACHED;
        !           217:                }
        !           218:                return 1;
        !           219:        }
        !           220:        if (nargc==1)
        !           221:                return 0;
        !           222:        if (no1flag)
        !           223:                cleanup(2, NULL);
        !           224:        dflttrp(ICMD);
        !           225:        ++nargv;
        !           226:        --nargc;
        !           227:        nenvp = envlvar(nenvp);
        !           228:        flexec();
        !           229:        exit(1);
        !           230:        NOTREACHED;
        !           231: }
        !           232: 
        !           233: s_exit()
        !           234: {
        !           235:        if (nargc > 1)
        !           236:                slret = atoi(nargv[1]);
        !           237:        reset(RUEXITS);
        !           238:        NOTREACHED;
        !           239: }
        !           240: 
        !           241: s_export()
        !           242: {
        !           243:        register int flag;
        !           244:        register char **varv;
        !           245: 
        !           246:        flag = nargv[0][0]=='e' ? VEXP : VRDO;
        !           247:        if (nargc < 2)
        !           248:                tellvar(flag);
        !           249:        else
        !           250:                for (varv=++nargv; *varv; )
        !           251:                        if (namevar(*varv))
        !           252:                                flagvar(*varv++, flag);
        !           253:                        else
        !           254:                                eillvar(*varv++);
        !           255:        return 0;
        !           256: }
        !           257: 
        !           258: s_login()
        !           259: {
        !           260:        register char *cmd;
        !           261: 
        !           262:        cmd = nargv[0][0]=='l' ? "/bin/login" : "/bin/newgrp";
        !           263:        execve(cmd, nargv, envlvar(nenvp));
        !           264:        ecantfind(cmd);
        !           265:        return 1;
        !           266: }
        !           267: 
        !           268: /* s_newgrp is overlaid with s_login */
        !           269: 
        !           270: s_popd()
        !           271: {
        !           272:        register int i, j, n, ret;
        !           273: 
        !           274:        if (nargc == 1)
        !           275:                return popd();
        !           276:        /*
        !           277:         * Kludge to pop one or more specific dir stack elements.
        !           278:         * Do args backwards so e.g. "popd 2 3 4" works as expected.
        !           279:         * Internal indices [0, dstkp] are user indices [dstkp, 0].
        !           280:         */
        !           281:        for (ret = 0, i = nargc-1; i > 0; i--) {
        !           282:                if ((n = atoi(nargv[i])) == 0)
        !           283:                        ret |= popd();
        !           284:                else if (n < 0 || n > dstkp) {
        !           285:                        printe("Illegal arg: %d", n);
        !           286:                        ret = -1;
        !           287:                        continue;
        !           288:                } else {
        !           289:                        j = dstkp - n;
        !           290:                        if (dstack[j] != NULL)
        !           291:                                sfree(dstack[j]);
        !           292:                        for ( ; j < dstkp; j++)
        !           293:                                dstack[j] = dstack[j+1];
        !           294:                        --dstkp;
        !           295:                }
        !           296:        }
        !           297:        return ret;
        !           298: }
        !           299: 
        !           300: s_pushd()
        !           301: {
        !           302:        register char *dir;
        !           303:        register int i, ret;
        !           304: 
        !           305:        if (nargc == 1) {
        !           306:                /* Exchange top two stack elements. */
        !           307:                if (dstkp == 0)
        !           308:                        return 1;               /* only one element on stack */
        !           309:                dir = dstack[dstkp-1];
        !           310:                dstack[dstkp-1] = dstack[dstkp];
        !           311:                dstack[dstkp] = dir;            /* exchange top two */
        !           312:                return ((cd(dir) == NULL) ? -1 : 0);    /* and cd accordingly */
        !           313:        }
        !           314:        /* Push one or more directories to stack. */
        !           315:        for (ret = 0, i = 1; i < nargc; i++)
        !           316:                ret |= pushd(nargv[i]);
        !           317:        return ret;
        !           318: }
        !           319: 
        !           320: s_read()
        !           321: {
        !           322:        SES s;
        !           323:        register int n, c;
        !           324:        register char **vp;
        !           325:        int eol;
        !           326: 
        !           327:        s.s_type = SSTR;
        !           328:        s.s_flag = 0;
        !           329:        s.s_ifp = stdin;
        !           330:        s.s_next = sesp;
        !           331:        sesp = &s;
        !           332:        for (eol=0, vp=++nargv, n=--nargc; n; n-=1, vp+=1) {
        !           333:                if (n==1 && ! eol) {
        !           334:                        strp = strt;
        !           335:                        c = collect('\n', 2);
        !           336:                        if (c == '\n')
        !           337:                                --strp;
        !           338:                        *strp = '\0';
        !           339:                } else if (! eol) {
        !           340:                        readflag = 1;
        !           341:                        c = yylex();
        !           342:                        readflag = 0;
        !           343:                } else
        !           344:                        *strt = '\0';
        !           345:                if (namevar(*vp))
        !           346:                        assnvar(*vp, duplstr(strt, 0));
        !           347:                else
        !           348:                        eillvar(*vp);
        !           349:                eol = c=='\n' || c==EOF;
        !           350:        }
        !           351:        sesp = s.s_next;
        !           352:        return c==EOF;
        !           353: }
        !           354: 
        !           355: /* s_readonly overlaid with s_export */
        !           356: 
        !           357: s_set()
        !           358: {
        !           359:        if (nargc < 2) {
        !           360:                tellvar(0);
        !           361:                return 0;
        !           362:        }
        !           363:        return set(nargc, nargv, 0);
        !           364: }
        !           365: 
        !           366: s_shift()
        !           367: {
        !           368:        register int n;
        !           369: 
        !           370:        n = nargc > 1 ? atoi(nargv[1]) : 1;
        !           371:        while (n > 0 && sargc > 0) {
        !           372:                n -= 1;
        !           373:                sargc -= 1;
        !           374:                sargp += 1;
        !           375:        }
        !           376:        return n!=0;
        !           377: }
        !           378: 
        !           379: s_times()
        !           380: {
        !           381: #if    _I386
        !           382: #define        tb_cutime       tms_cutime
        !           383: #define        tb_cstime       tms_cstime
        !           384:        struct  tms     tb;
        !           385: #else
        !           386:        struct tbuffer tb;
        !           387: 
        !           388: #endif
        !           389: 
        !           390:        times(&tb);
        !           391:        ptime(tb.tb_cutime);
        !           392:        ptime(tb.tb_cstime);
        !           393:        prints("\n");
        !           394:        return 0;
        !           395: }
        !           396: 
        !           397: s_trap()
        !           398: {
        !           399:        register char **vp;
        !           400:        register char *cp;
        !           401:        register int err;
        !           402: 
        !           403:        err = 0;
        !           404:        if (nargc==1)
        !           405:                return telltrp();
        !           406:        vp = ++nargv;
        !           407:        cp = *vp;
        !           408:        if (class(cp[0], MDIGI)
        !           409:         && (cp[1]=='\0' || (class(cp[1], MDIGI) && cp[2]=='\0')))
        !           410:                cp = NULL;
        !           411:        else
        !           412:                ++vp;
        !           413:        while (*vp) {
        !           414:                if (class(vp[0][0], MDIGI))
        !           415:                        err |= setstrp(atoi(*vp++), cp);
        !           416:                else {
        !           417:                        printe("Bad trap: %s", *vp++);
        !           418:                        err |= 1;
        !           419:                }
        !           420:        }
        !           421:        return err;
        !           422: }
        !           423: 
        !           424: s_umask()
        !           425: {
        !           426:        if (nargc < 2)
        !           427:                prints("%03o\n", ufmask);
        !           428:        else
        !           429:                umask(ufmask = atoi(nargv[1]));
        !           430:        return 0;
        !           431: }
        !           432: 
        !           433: s_wait()
        !           434: {
        !           435:        register int f;
        !           436: 
        !           437:        f = (nargc > 1) ? atoi(nargv[1]) : 0;
        !           438:        if (f > 0)
        !           439:                f = -f;
        !           440:        waitc(f);
        !           441:        return slret;
        !           442: }
        !           443: 
        !           444: /*
        !           445:  * Change to given directory.
        !           446:  * Update global variable CWD accordingly.
        !           447:  * Return NULL if bad, otherwise full pathname of the directory.
        !           448:  */
        !           449: char *
        !           450: cd(dir) register char *dir;
        !           451: {
        !           452:        if (chdir(dir) < 0) {
        !           453:                printe("%s: bad directory", dir);
        !           454:                return NULL;
        !           455:        }
        !           456:        if (*dir != '/') {
        !           457:                /*
        !           458:                 * Find an absolute pathname for the dstack and $CWD.
        !           459:                 * The directory now in dstack[dstkp] is "." if _getwd() failed
        !           460:                 * for any reason (e.g., the user lacks search permission
        !           461:                 * down the path to "/", or "." was rm'ed by another process).
        !           462:                 * Avoid _getwd() in this case, it can undo the chdir() above.
        !           463:                 */
        !           464:                if ((strcmp(dstack[dstkp], ".") == 0)
        !           465:                 || ((dir = _getwd()) == NULL))
        !           466:                        return NULL;
        !           467:        }
        !           468:        assnvar("CWD", dir);
        !           469:        return dir;
        !           470: }
        !           471: 
        !           472: /*
        !           473:  * Pop the directory stack and change to the previous stacked directory.
        !           474:  */
        !           475: popd()
        !           476: {
        !           477:        if (dstkp == 0) {
        !           478:                printe("Directory stack underflow");
        !           479:                return -1;
        !           480:        }
        !           481:        if (dstack[dstkp] != NULL)
        !           482:                sfree(dstack[dstkp]);
        !           483:        return (cd(dstack[--dstkp]) == NULL ? -1 : 0);
        !           484: }
        !           485: 
        !           486: /*
        !           487:  * Change to given directory and add it to the directory stack.
        !           488:  */
        !           489: pushd(dir) register char *dir;
        !           490: {
        !           491:        if ((dir = cd(dir)) == NULL)
        !           492:                return -1;                      /* cd failed */
        !           493:        if (++dstkp >= DSTACKN) {
        !           494:                --dstkp;
        !           495:                printe("Directory stack overflow");
        !           496:                return -1;
        !           497:        }
        !           498:        dstack[dstkp] = duplstr(dir, 1);
        !           499:        return 0;
        !           500: }
        !           501: 
        !           502: /*
        !           503:  * The set command.  This is also called from `main' to set
        !           504:  * options from the command line.  In this case `flag' is
        !           505:  * set.
        !           506:  */
        !           507: set(argc, argv, flag)
        !           508: register char *argv[];
        !           509: {
        !           510:        int n;
        !           511:        register char *cp;
        !           512: 
        !           513:        if (flag) {
        !           514:                cflag = 0;
        !           515:                iflag = 0;
        !           516:                sflag = 0;
        !           517:        }
        !           518:        n = 0;
        !           519:        if (argc > 0)
        !           520:                n = 1;
        !           521:        if (argc>1 && argv[1][0]=='-') {
        !           522:                register char *fp;
        !           523: 
        !           524:                n++;
        !           525:                for (cp = &argv[1][1]; *cp; cp++) {
        !           526:                        if ((fp=index(shfnams, *cp)) == NULL
        !           527:                         || (fp+=shflags-shfnams) == NULL
        !           528:                         || (fp != &lgnflag && fp > &xflag && flag == 0))
        !           529:                                printe("-%c: Bad option", *cp);
        !           530:                        else if (fp != &lgnflag)
        !           531:                                *fp = *cp;
        !           532:                }
        !           533:                if (cp == &argv[1][1]) {
        !           534:                        vflag = 0;
        !           535:                        xflag = 0;
        !           536:                }
        !           537:                if (flag == 0 && argc == 2)
        !           538:                        return errflag;
        !           539:        }
        !           540:        if (errflag)
        !           541:                return 1;
        !           542:        if (sargv != NULL)
        !           543:                vfree(sargv);
        !           544:        sargv = vdupl(argv);
        !           545:        sargc = argc - n;
        !           546:        sargp = sargv + n;
        !           547:        return 0;
        !           548: }
        !           549: 
        !           550: /*
        !           551:  * print the time as XmX.Xs
        !           552:  * as fixed by Randall.
        !           553:  */
        !           554: ptime(t)
        !           555: long t;
        !           556: {
        !           557:        register int ticks, tenths, seconds;
        !           558: 
        !           559:        prints("%Dm", t/MINUTE);
        !           560:        ticks = t%MINUTE;
        !           561:        seconds = ticks/SECOND;
        !           562:        tenths = (ticks%SECOND + SECOND/20)/(SECOND/10);
        !           563:        if (tenths == 10) {
        !           564:                tenths = 0;
        !           565:                seconds++;
        !           566:        }
        !           567:        prints("%d.%ds ", seconds, tenths);
        !           568: }
        !           569: 
        !           570: /* end of sh/exec3.c */

unix.superglobalmegacorp.com

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