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