Annotation of coherent/b/bin/sh_B4_420/exec3.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * sh/exec3.c
                      3:  * Bourne shell.
                      4:  * Builtin commands and shell functions.
                      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: NODE   *copy_node();
                     16: char   *cd();
                     17: 
                     18: extern s_colon();
                     19: extern s_dot();
                     20: extern s_break();
                     21: #define s_continue     s_break
                     22: extern s_cd();
                     23: extern s_dirs();
                     24: extern s_eval();
                     25: extern s_exec();
                     26: extern s_exit();
                     27: extern s_export();
                     28: extern s_login();
                     29: #define s_newgrp       s_login
                     30: extern s_popd();
                     31: extern s_pushd();
                     32: extern s_read();
                     33: #define s_readonly     s_export
                     34: extern s_set();
                     35: extern s_shift();
                     36: extern s_times();
                     37: extern s_trap();
                     38: extern s_umask();
                     39: extern s_wait();
                     40: #define SNULL  ((int (*)())0)
                     41: 
                     42: /* Built-in functions. */
                     43: typedef struct {
                     44:        int     i_hash;
                     45:        char    *i_name;
                     46:        int     (*i_func)();
                     47: } INLINE;
                     48: 
                     49: INLINE inls[] = {
                     50:        0,      ":",            s_colon,
                     51:        0,      ".",            s_dot,
                     52:        0,      "break",        s_break,
                     53:        0,      "continue",     s_continue,
                     54:        0,      "cd",           s_cd,
                     55:        0,      "dirs",         s_dirs,
                     56:        0,      "eval",         s_eval,
                     57:        0,      "exec",         s_exec,
                     58:        0,      "exit",         s_exit,
                     59:        0,      "export",       s_export,
                     60:        0,      "login",        s_login,
                     61:        0,      "newgrp",       s_newgrp,
                     62:        0,      "popd",         s_popd,
                     63:        0,      "pushd",        s_pushd,
                     64:        0,      "read",         s_read,
                     65:        0,      "readonly",     s_readonly,
                     66:        0,      "set",          s_set,
                     67:        0,      "shift",        s_shift,
                     68:        0,      "times",        s_times,
                     69:        0,      "trap",         s_trap,
                     70:        0,      "umask",        s_umask,
                     71:        0,      "wait",         s_wait,
                     72:        0,      NULL,           SNULL
                     73: };
                     74: 
                     75: inline()
                     76: {
                     77:        register int (*s_func)();
                     78:        register INLINE *ip;
                     79:        register int ahash;
                     80: 
                     81:        if (inls[0].i_hash==0)
                     82:                for (ip=inls; ip->i_name!=NULL; ip++)
                     83:                        ip->i_hash = ihash(ip->i_name);
                     84:        if (nargv[0] == NULL)
                     85:                return 0;
                     86:        ahash = ihash(nargv[0]);
                     87:        for (ip=inls; ip->i_name!=NULL; ip++)
                     88:                if (ip->i_hash==ahash && strcmp(nargv[0], ip->i_name)==0)
                     89:                        break;
                     90:        if ((s_func=ip->i_func) == SNULL)
                     91:                return 0;
                     92:        /*
                     93:         * Process exec specially, because it has unique semantics for
                     94:         * redirection (among other things). Redirection of builtins is done
                     95:         * using the "undo" facility because builtins must execute in the
                     96:         * top-level environment. The original code here permitted a small
                     97:         * subset of builtins to be redirected, but executed them in a
                     98:         * subshell, giving bogus semantics (eg, it permitted "export" to be
                     99:         * redirected, but in a subshell it had no effect).
                    100:         */
                    101:        if (s_func == s_exec)
                    102:                slret = (* s_func) ();
                    103:        else {
                    104:                REDIR_UNDO    * undo = NULL;
                    105: 
                    106:                if (redirect (niovp, & undo) < 0)
                    107:                        slret = 1;
                    108:                else 
                    109:                        slret = (* s_func) ();
                    110: 
                    111:                /*
                    112:                 * NB: The rationale for the following kludge is not clear,
                    113:                 * but with the ability to properly redirect builtins and
                    114:                 * execute the in the top-level context, it no longer works.
                    115:                 * It could be added back in, but since it conflicts with
                    116:                 * POSIX.2 anyway, why bother.
                    117:                 */
                    118: #if 0
                    119:                if (s_func == s_eval)
                    120:                        slret = (*s_func)();
                    121:                else {
                    122:                        /* Kludge stderr output to stdout. */
                    123:                        dup2(1, 2);
                    124:                        close(1);
                    125:                        slret = (*s_func)();
                    126:                }
                    127: #endif
                    128: 
                    129:                redirundo (& undo);
                    130:        }
                    131:        return 1;
                    132: }
                    133: 
                    134: ihash(cp)
                    135: register char *cp;
                    136: {
                    137:        register int i;
                    138:        for (i=0; *cp; i+=*cp++);
                    139:        return i;
                    140: }
                    141: 
                    142: 
                    143: /*
                    144:  * Actual builtin functions.
                    145:  */
                    146: s_colon()
                    147: {
                    148:        return 0;
                    149: }
                    150: 
                    151: s_dot()
                    152: {
                    153:        if (nargc==2) {
                    154:                ffind(NULL);
                    155:                if (ffind(vpath, nargv[1], 4))
                    156:                        return session(SFILE, duplstr(strt, 0));
                    157:                else {
                    158:                        ecantfind(nargv[1]);
                    159:                        return 1;
                    160:                }
                    161:        } else if (nargc==1)
                    162:                return 0;
                    163:        syntax();
                    164:        return 1;
                    165: }
                    166: 
                    167: s_break()
                    168: {
                    169:        register CON *cp;
                    170:        register int t;
                    171:        register int n;
                    172:        int ret;
                    173: 
                    174:        ret = nargv[0][0]=='b' ? 2 : 1;
                    175:        n = nargc>1 ? atoi(nargv[1]) : 1;
                    176:        for (cp = sesp->s_con; cp; cp = cp->c_next) {
                    177:                t = cp->c_node->n_type;
                    178:                if ((t==NWHILE || t==NFOR || t==NUNTIL) && --n == 0) {
                    179:                        sesp->s_con = cp;
                    180:                        longjmp(cp->c_envl, ret);
                    181:                        break;
                    182:                }
                    183:                freebuf(cp->c_bpp);
                    184:        }
                    185:        printe("%s out of bounds", ret==1 ? "Continue" : "Break");
                    186: }
                    187: 
                    188: /* s_continue is overlaid with s_break */
                    189: 
                    190: s_cd()
                    191: {
                    192:        register char *dir;
                    193: 
                    194:        if ((dir = cd((nargc<2) ? vhome : nargv[1])) == NULL)
                    195:                return -1;                      /* cd failed */
                    196:        if (dstack[dstkp] != NULL)
                    197:                sfree(dstack[dstkp]);
                    198:        dstack[dstkp] = duplstr(dir, 1);        /* update dir stack */
                    199:        return 0;
                    200: }
                    201: 
                    202: s_dirs()
                    203: {
                    204:        register int i;
                    205: 
                    206:        for (i = dstkp; i >= 0; i--)
                    207:                printf (stdout, "%s ", dstack[i]);
                    208:        fputc('\n', stderr);
                    209: }
                    210: 
                    211: s_eval()
                    212: {
                    213:        if (nargc>1)
                    214:                return session(SARGV, ++nargv);
                    215:        else
                    216:                return 0;
                    217: }
                    218: 
                    219: s_exec()
                    220: {
                    221:        if (redirect (niovp, NULL) < 0) {
                    222:                if (nargc>1) {
                    223:                        exit(1);
                    224:                        NOTREACHED;
                    225:                }
                    226:                return 1;
                    227:        }
                    228:        if (nargc==1)
                    229:                return 0;
                    230:        if (no1flag) {
                    231:                cleanup_shell_fns ();
                    232:                unlink_temp (capture_temp ());
                    233:        }
                    234:        dflttrp(ICMD);
                    235:        ++nargv;
                    236:        --nargc;
                    237:        nenvp = envlvar(nenvp);
                    238:        flexec();
                    239:        exit(1);
                    240:        NOTREACHED;
                    241: }
                    242: 
                    243: s_exit()
                    244: {
                    245:        if (nargc > 1)
                    246:                slret = atoi(nargv[1]);
                    247:        reset(RUEXITS);
                    248:        NOTREACHED;
                    249: }
                    250: 
                    251: s_export()
                    252: {
                    253:        register int flag;
                    254:        register char **varv;
                    255: 
                    256:        flag = nargv[0][0]=='e' ? VEXP : VRDO;
                    257:        if (nargc < 2)
                    258:                tellvar(flag);
                    259:        else
                    260:                for (varv=++nargv; *varv; )
                    261:                        if (namevar(*varv))
                    262:                                flagvar(*varv++, flag);
                    263:                        else
                    264:                                eillvar(*varv++);
                    265:        return 0;
                    266: }
                    267: 
                    268: s_login()
                    269: {
                    270:        register char *cmd;
                    271: 
                    272:        cmd = nargv[0][0]=='l' ? "/bin/login" : "/bin/newgrp";
                    273:        execve(cmd, nargv, envlvar(nenvp));
                    274:        ecantfind(cmd);
                    275:        return 1;
                    276: }
                    277: 
                    278: /* s_newgrp is overlaid with s_login */
                    279: 
                    280: s_popd()
                    281: {
                    282:        register int i, j, n, ret;
                    283: 
                    284:        if (nargc == 1)
                    285:                return popd();
                    286:        /*
                    287:         * Kludge to pop one or more specific dir stack elements.
                    288:         * Do args backwards so e.g. "popd 2 3 4" works as expected.
                    289:         * Internal indices [0, dstkp] are user indices [dstkp, 0].
                    290:         */
                    291:        for (ret = 0, i = nargc-1; i > 0; i--) {
                    292:                if ((n = atoi(nargv[i])) == 0)
                    293:                        ret |= popd();
                    294:                else if (n < 0 || n > dstkp) {
                    295:                        printe("Illegal arg: %d", n);
                    296:                        ret = -1;
                    297:                        continue;
                    298:                } else {
                    299:                        j = dstkp - n;
                    300:                        if (dstack[j] != NULL)
                    301:                                sfree(dstack[j]);
                    302:                        for ( ; j < dstkp; j++)
                    303:                                dstack[j] = dstack[j+1];
                    304:                        --dstkp;
                    305:                }
                    306:        }
                    307:        return ret;
                    308: }
                    309: 
                    310: s_pushd()
                    311: {
                    312:        register char *dir;
                    313:        register int i, ret;
                    314: 
                    315:        if (nargc == 1) {
                    316:                /* Exchange top two stack elements. */
                    317:                if (dstkp == 0)
                    318:                        return 1;               /* only one element on stack */
                    319:                dir = dstack[dstkp-1];
                    320:                dstack[dstkp-1] = dstack[dstkp];
                    321:                dstack[dstkp] = dir;            /* exchange top two */
                    322:                return ((cd(dir) == NULL) ? -1 : 0);    /* and cd accordingly */
                    323:        }
                    324:        /* Push one or more directories to stack. */
                    325:        for (ret = 0, i = 1; i < nargc; i++)
                    326:                ret |= pushd(nargv[i]);
                    327:        return ret;
                    328: }
                    329: 
                    330: /*
                    331:  * NB: For s_read (), wrap up the temporary-space global bullshit. Later we
                    332:  * can add parameters to this stuff to get the effect of string streams.
                    333:  */
                    334: 
                    335: #define        temp_string_begin()     ((void) (strp = strt))
                    336: #define        temp_string_max()       STRSIZE
                    337: #define        temp_string_add(c) \
                    338:                (strp < strt + temp_string_max () ? (void) (* strp ++ = c) : \
                    339:                 (void) etoolong ())
                    340: #define        temp_string_end()       (strt)
                    341: #define        temp_string_end_copy()  (duplstr (temp_string_end (), 1))
                    342: #define        temp_string_temp_copy() (duplstr (temp_string_end (), 0))
                    343: #define        temp_mark()             (0)
                    344: #define        temp_release(x)         ((void) x)
                    345: 
                    346: typedef        int             temp_mark_type;
                    347: 
                    348: #define        ARGS(x)         x
                    349: void temp_string_begin ARGS (()) {
                    350:        temp_string_begin ();
                    351: }
                    352: int temp_string_max ARGS (()) {
                    353:        return temp_string_max ();
                    354: }
                    355: void temp_string_add ARGS ((c)) int c; {
                    356:        temp_string_add (c);
                    357: }
                    358: char * temp_string_end ARGS (()) {
                    359:        return temp_string_end ();
                    360: }
                    361: char * temp_string_end_copy ARGS (()) {
                    362:        return temp_string_end_copy ();
                    363: }
                    364: char * temp_string_temp_copy ARGS (()) {
                    365:        return temp_string_temp_copy ();
                    366: }
                    367: temp_mark_type temp_mark ARGS (()) {
                    368:        return temp_mark ();
                    369: }
                    370: void temp_release ARGS ((m)) temp_mark_type m; {
                    371:        temp_release (m);
                    372: }
                    373: 
                    374: /*
                    375:  * NB: Originally, this code used yylex () to break the input up into words.
                    376:  * This was a bad idea, because this caused the IFS variable to have no
                    377:  * useful effect. Now we just read using <stdio.h> functions, because the
                    378:  * extra machinery for session-management doesn't seem to buy anything.
                    379:  */
                    380: 
                    381: s_read()
                    382: {
                    383:        char         ** argp = nargv + 1;
                    384:        char         ** arg_end = argp + (nargc - 1);
                    385:        char          * delimiters;
                    386:        int             ch;
                    387: 
                    388:        while (argp < arg_end)
                    389:                if (! namevar (* argp ++))
                    390:                        eillvar (argp - 1);
                    391: 
                    392:        delimiters = vifs == NULL ? " \t" : vifs;
                    393: 
                    394:        argp = nargv + 1;
                    395:        while (argp < arg_end)  {
                    396:                temp_mark_type  mark;
                    397:                enum    {
                    398:                        EAT_WS,
                    399:                        WORD
                    400:                } state = EAT_WS;
                    401: 
                    402:                mark = temp_mark ();
                    403:                temp_string_begin ();
                    404: 
                    405:                if (argp + 1 == arg_end)
                    406:                        delimiters = "";
                    407: 
                    408:                while ((ch = getc (stdin)) != EOF && ch != '\n') {
                    409: 
                    410:                        if (strchr (delimiters, ch) != NULL) {
                    411: 
                    412:                                if (state == EAT_WS)
                    413:                                        continue;
                    414:                                break;
                    415:                        }
                    416: 
                    417:                        temp_string_add (ch);
                    418:                        state = WORD;
                    419:                }
                    420:                temp_string_add (0);
                    421: 
                    422:                assnvar (* argp ++, temp_string_temp_copy ());
                    423:                temp_release (mark);
                    424: 
                    425:                if (ch == EOF || ch == '\n')
                    426:                        break;
                    427:        }
                    428: 
                    429:        while (argp < arg_end)
                    430:                assnvar (* argp ++, "");
                    431: 
                    432:        return ch == EOF;
                    433: }
                    434: 
                    435: 
                    436: /* s_readonly overlaid with s_export */
                    437: 
                    438: s_set()
                    439: {
                    440:        if (nargc < 2) {
                    441:                tellvar(0);
                    442:                return 0;
                    443:        }
                    444:        return set(nargc, nargv, 0);
                    445: }
                    446: 
                    447: s_shift()
                    448: {
                    449:        register int n;
                    450: 
                    451:        n = nargc > 1 ? atoi(nargv[1]) : 1;
                    452:        while (n > 0 && sargc > 0) {
                    453:                n -= 1;
                    454:                sargc -= 1;
                    455:                sargp += 1;
                    456:        }
                    457:        return n!=0;
                    458: }
                    459: 
                    460: s_times()
                    461: {
                    462: #if    _I386
                    463: #define        tb_cutime       tms_cutime
                    464: #define        tb_cstime       tms_cstime
                    465:        struct  tms     tb;
                    466: #else
                    467:        struct tbuffer tb;
                    468: 
                    469: #endif
                    470: 
                    471:        times(&tb);
                    472:        ptime(tb.tb_cutime);
                    473:        ptime(tb.tb_cstime);
                    474:        puts ("\n");
                    475:        return 0;
                    476: }
                    477: 
                    478: s_trap()
                    479: {
                    480:        register char **vp;
                    481:        register char *cp;
                    482:        register int err;
                    483: 
                    484:        err = 0;
                    485:        if (nargc==1)
                    486:                return telltrp();
                    487:        vp = ++nargv;
                    488:        cp = *vp;
                    489:        if (class(cp[0], MDIGI)
                    490:         && (cp[1]=='\0' || (class(cp[1], MDIGI) && cp[2]=='\0')))
                    491:                cp = NULL;
                    492:        else
                    493:                ++vp;
                    494:        while (*vp) {
                    495:                if (class(vp[0][0], MDIGI))
                    496:                        err |= setstrp(atoi(*vp++), cp);
                    497:                else {
                    498:                        printe("Bad trap: %s", *vp++);
                    499:                        err |= 1;
                    500:                }
                    501:        }
                    502:        return err;
                    503: }
                    504: 
                    505: s_umask()
                    506: {
                    507:        if (nargc < 2)
                    508:                printf ("%03o\n", ufmask);
                    509:        else
                    510:                umask(ufmask = atoi(nargv[1]));
                    511:        return 0;
                    512: }
                    513: 
                    514: s_wait()
                    515: {
                    516:        register int f;
                    517: 
                    518:        f = (nargc > 1) ? atoi(nargv[1]) : 0;
                    519:        if (f > 0)
                    520:                f = -f;
                    521:        waitc(f);
                    522:        return slret;
                    523: }
                    524: 
                    525: /*
                    526:  * Change to given directory.
                    527:  * Update global variable CWD accordingly.
                    528:  * Return NULL if bad, otherwise full pathname of the directory.
                    529:  */
                    530: char *
                    531: cd(dir) register char *dir;
                    532: {
                    533:        if (chdir(dir) < 0) {
                    534:                printe("%s: bad directory", dir);
                    535:                return NULL;
                    536:        }
                    537:        if (*dir != '/') {
                    538:                /*
                    539:                 * Find an absolute pathname for the dstack and $CWD.
                    540:                 * The directory now in dstack[dstkp] is "." if _getwd() failed
                    541:                 * for any reason (e.g., the user lacks search permission
                    542:                 * down the path to "/", or "." was rm'ed by another process).
                    543:                 * Avoid _getwd() in this case, it can undo the chdir() above.
                    544:                 */
                    545:                if ((strcmp(dstack[dstkp], ".") == 0)
                    546:                 || ((dir = _getwd()) == NULL))
                    547:                        return NULL;
                    548:        }
                    549:        assnvar("CWD", dir);
                    550:        return dir;
                    551: }
                    552: 
                    553: /*
                    554:  * Pop the directory stack and change to the previous stacked directory.
                    555:  */
                    556: popd()
                    557: {
                    558:        if (dstkp == 0) {
                    559:                printe("Directory stack underflow");
                    560:                return -1;
                    561:        }
                    562:        if (dstack[dstkp] != NULL)
                    563:                sfree(dstack[dstkp]);
                    564:        return (cd(dstack[--dstkp]) == NULL ? -1 : 0);
                    565: }
                    566: 
                    567: /*
                    568:  * Change to given directory and add it to the directory stack.
                    569:  */
                    570: pushd(dir) register char *dir;
                    571: {
                    572:        if ((dir = cd(dir)) == NULL)
                    573:                return -1;                      /* cd failed */
                    574:        if (++dstkp >= DSTACKN) {
                    575:                --dstkp;
                    576:                printe("Directory stack overflow");
                    577:                return -1;
                    578:        }
                    579:        dstack[dstkp] = duplstr(dir, 1);
                    580:        return 0;
                    581: }
                    582: 
                    583: /*
                    584:  * The set command.  This is also called from `main' to set
                    585:  * options from the command line.  In this case `flag' is
                    586:  * set.
                    587:  */
                    588: set(argc, argv, flag)
                    589: register char *argv[];
                    590: {
                    591:        int n;
                    592:        register char *cp;
                    593: 
                    594:        if (flag) {
                    595:                cflag = 0;
                    596:                iflag = 0;
                    597:                sflag = 0;
                    598:        }
                    599:        n = 0;
                    600:        if (argc > 0)
                    601:                n = 1;
                    602:        if (argc>1 && argv[1][0]=='-') {
                    603:                register char *fp;
                    604: 
                    605:                n++;
                    606:                for (cp = &argv[1][1]; *cp; cp++) {
                    607:                        if ((fp=index(shfnams, *cp)) == NULL
                    608:                         || (fp+=shflags-shfnams) == NULL
                    609:                         || (fp != &lgnflag && fp > &xflag && flag == 0))
                    610:                                printe("-%c: Bad option", *cp);
                    611:                        else if (fp != &lgnflag)
                    612:                                *fp = *cp;
                    613:                }
                    614:                if (cp == &argv[1][1]) {
                    615:                        vflag = 0;
                    616:                        xflag = 0;
                    617:                }
                    618:                if (flag == 0 && argc == 2)
                    619:                        return errflag;
                    620:        }
                    621:        if (errflag)
                    622:                return 1;
                    623:        if (sargv != NULL)
                    624:                vfree(sargv);
                    625:        sargv = vdupl(argv);
                    626:        sargc = argc - n;
                    627:        sargp = sargv + n;
                    628:        return 0;
                    629: }
                    630: 
                    631: /*
                    632:  * print the time as XmX.Xs
                    633:  * as fixed by Randall.
                    634:  */
                    635: ptime(t)
                    636: long t;
                    637: {
                    638:        register int ticks, tenths, seconds;
                    639: 
                    640:        printf ("%ldm", t/MINUTE);
                    641:        ticks = t%MINUTE;
                    642:        seconds = ticks/SECOND;
                    643:        tenths = (ticks%SECOND + SECOND/20)/(SECOND/10);
                    644:        if (tenths == 10) {
                    645:                tenths = 0;
                    646:                seconds++;
                    647:        }
                    648:        printf ("%d.%ds ", seconds, tenths);
                    649: }
                    650: 
                    651: /* User-defined shell functions. */
                    652: 
                    653: /*
                    654:  * Lookup a shell function name.
                    655:  * The hashing is probably irrelevant.
                    656:  */
                    657: SHFUNC *
                    658: lookup_sh_fn(name) char *name;
                    659: {
                    660:        register SHFUNC *fnp;
                    661:        register int ahash;
                    662: 
                    663:        ahash = ihash(name);
                    664:        for (fnp=sh_fnp; fnp != NULL; fnp = fnp->fn_link)
                    665:                if (fnp->fn_hash==ahash && strcmp(name, fnp->fn_name)==0)
                    666:                        return fnp;
                    667:        return NULL;
                    668: }
                    669: 
                    670: 
                    671: /*
                    672:  * When a subshell is created, the functions are available in the subshell
                    673:  * but we don't want to lose the here-documents.
                    674:  */
                    675: 
                    676: void subshell_shell_fns ()
                    677: {
                    678:        SHFUNC        * scan;
                    679: 
                    680:        scan = sh_fnp;
                    681: 
                    682:        while (scan != NULL) {
                    683:                forget_temp (scan->fn_temp);
                    684:                scan->fn_temp = NULL;
                    685:                scan = scan->fn_link;
                    686:        }
                    687: }
                    688: 
                    689: 
                    690: /*
                    691:  * Unset a shell function, freeing the function body and detaching any
                    692:  * temporary files.
                    693:  */
                    694: 
                    695: void cleanup_shell_fn (fnp)
                    696: SHFUNC       * fnp;
                    697: {
                    698:        free_node (fnp->fn_body);
                    699:        unlink_temp (fnp->fn_temp);
                    700: }
                    701: 
                    702: 
                    703: /*
                    704:  * Before final exit, clean up all shell functions. Freeing the memory of
                    705:  * the function bodies is a waste of time here, so we leave that alone.
                    706:  */
                    707: 
                    708: void cleanup_shell_fns ()
                    709: {
                    710:        SHFUNC        * scan;
                    711:        SHFUNC        * next;
                    712: 
                    713:        for (scan = sh_fnp ; scan != NULL ; scan = next) {
                    714:                next = scan->fn_link;
                    715:                unlink_temp (scan->fn_temp);
                    716: #if 0
                    717:                cleanup_shell_fn (scan);
                    718:                sfree (scan->fn_name);
                    719:                sfree (scan);
                    720: #endif
                    721:        }
                    722: 
                    723:        sh_fnp = NULL;
                    724: }
                    725: 
                    726: 
                    727: /*
                    728:  * Define a shell function.
                    729:  */
                    730: def_shell_fn(np) register NODE *np;
                    731: {
                    732:        register char *name;
                    733:        register SHFUNC *fnp;
                    734: 
                    735:        name = np->n_strp;
                    736:        if ((fnp = lookup_sh_fn(name)) != NULL)
                    737:                cleanup_shell_fn (fnp); /* redeclared, free old body */
                    738:        else {
                    739:                fnp = salloc(sizeof *fnp);      /* allocate new function */
                    740:                fnp->fn_link = sh_fnp;          /* add it to list */
                    741:                sh_fnp = fnp;
                    742:                fnp->fn_hash = ihash(name);     /* and set member info */ 
                    743:                fnp->fn_name = duplstr(name, 1);
                    744:        }
                    745:        fnp->fn_temp = capture_temp ();
                    746:        fnp->fn_body = copy_node(np->n_next);   /* and copy function body */
                    747: }
                    748: 
                    749: /*
                    750:  * Look for a shell function, execute it if found.
                    751:  */
                    752: int
                    753: sh_fn()
                    754: {
                    755:        register SHFUNC *fnp;
                    756:        CON *ocon;
                    757:        int oargc;
                    758:        char *oarg0;
                    759:        char **oargv, **oargp;
                    760: 
                    761:        if (nargv[0] == NULL)
                    762:                return 0;
                    763:        if ((fnp = lookup_sh_fn(nargv[0])) == NULL)
                    764:                return 0;
                    765: 
                    766:        /* Set up sargc, sarg0, sargv, sargp here for $1 etc. to work. */
                    767:        oarg0 = sarg0;
                    768:        oargc = sargc;
                    769:        oargv = sargv;
                    770:        oargp = sargp;
                    771:        sarg0 = nargv[0];
                    772:        sargc = nargc - 1;
                    773:        sargp = sargv = vdupl(nargv+1);
                    774:        ocon = sesp->s_con;
                    775:        sesp->s_con = NULL;
                    776: 
                    777:        ++in_sh_fn;
                    778:        slret = command(fnp->fn_body);          /* execute it */
                    779:        --in_sh_fn;
                    780:        ret_done = 0;
                    781:        vfree(sargv);
                    782: 
                    783:        sesp->s_con = ocon;
                    784:        sarg0 = oarg0;
                    785:        sargc = oargc;
                    786:        sargv = oargv;
                    787:        sargp = oargp;
                    788:        return 1;
                    789: }
                    790: 
                    791: /*
                    792:  * Recursively allocate a fresh copy of a NODE.
                    793:  * Examines type to decide if node uses strp or auxp.
                    794:  * Watch out for nodes which contain loops: NFOR2, NWHILE, NUNTIL.
                    795:  */
                    796: NODE *
                    797: copy_node(np) NODE *np;
                    798: {
                    799:        register NODE *newnp;
                    800:        int flag;
                    801: 
                    802: #if    0
                    803:        printf("copy_node(%x)", np);
                    804:        if (np != NULL)
                    805:                printf(" type=%d", np->n_type);
                    806:        printf("\n");
                    807: #endif
                    808:        if (np == NULL)
                    809:                return NULL;
                    810:        flag = 0;
                    811:        newnp = salloc(sizeof *np);                     /* allocate new NODE */
                    812:        newnp->n_type = np->n_type;
                    813:        switch(np->n_type) {
                    814: 
                    815:        /* The following cases use the strp member. */
                    816:        case NRET:
                    817:        case NFOR:
                    818:        case NARGS:
                    819:        case NASSG:
                    820:        case NCASE:
                    821:        case NCASE3:
                    822:        case NIORS:
                    823:        case NFUNC:
                    824:                newnp->n_strp = duplstr(np->n_strp, 1);
                    825:                break;
                    826: 
                    827:        /* The following cases use the auxp member. */
                    828:        case NWHILE:
                    829:        case NUNTIL:
                    830:        case NFOR2:
                    831:                flag++;
                    832:                np->n_next->n_next = NULL;      /* zap the loop for recursion */
                    833:                /* fall through... */
                    834:        case NNULL:
                    835:        case NCOMS:
                    836:        case NCTRL:
                    837:        case NBRAC:
                    838:        case NPARN:
                    839:        case NIF:
                    840:        case NELSE:
                    841:        case NCASE2:
                    842:        case NLIST:
                    843:        case NANDF:
                    844:        case NORF:
                    845:        case NBACK:
                    846:        case NPIPE:
                    847:                newnp->n_auxp = copy_node(np->n_auxp);
                    848:                break;
                    849: 
                    850:        case NRPIPE:
                    851:        case NWPIPE:
                    852:        default:
                    853:                /* ??? */
                    854:                printf("type=%d\n", np->n_type);
                    855:                panic(9);
                    856:        }
                    857:        newnp->n_next = copy_node(np->n_next);
                    858:        if (flag)
                    859:                newnp->n_next->n_next = newnp;          /* restore loop */
                    860:        return newnp;
                    861: }
                    862: 
                    863: /*
                    864:  * Undo the above.
                    865:  */
                    866: free_node(np) register NODE *np;
                    867: {
                    868:        if (np == NULL)
                    869:                return;
                    870:        switch(np->n_type) {
                    871: 
                    872:        /* strp */
                    873:        case NRET:
                    874:        case NFOR:
                    875:        case NARGS:
                    876:        case NASSG:
                    877:        case NCASE:
                    878:        case NCASE3:
                    879:        case NIORS:
                    880:        case NFUNC:
                    881:                sfree(np->n_strp);
                    882:                break;
                    883: 
                    884:        /* auxp */
                    885:        case NWHILE:
                    886:        case NUNTIL:
                    887:        case NFOR2:
                    888:                np->n_next->n_next = NULL;      /* zap the loop for recursion */
                    889:                /* fall through... */
                    890:        case NNULL:
                    891:        case NCOMS:
                    892:        case NCTRL:
                    893:        case NBRAC:
                    894:        case NPARN:
                    895:        case NIF:
                    896:        case NELSE:
                    897:        case NCASE2:
                    898:        case NLIST:
                    899:        case NANDF:
                    900:        case NORF:
                    901:        case NBACK:
                    902:        case NPIPE:
                    903:                free_node(np->n_auxp);
                    904:                break;
                    905: 
                    906:        case NRPIPE:
                    907:        case NWPIPE:
                    908:        default:
                    909:                /* ??? */
                    910:                printf("type=%d\n", np->n_type);
                    911:                panic(10);
                    912:        }
                    913:        free_node(np->n_next);
                    914:        sfree(np);
                    915: }
                    916: 
                    917: /* 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.