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