Annotation of coherent/d/bin/sh/exec3.c, revision 1.1.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.