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

unix.superglobalmegacorp.com

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