Annotation of coherent/a/usr/bob/korn/main.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * startup, main loop, enviroments and error handling
        !             3:  */
        !             4: 
        !             5: static char *RCSid = "$Header: /newbits/usr/bin/korn/RCS/main.c,v 1.2 91/08/01 12:41:00 bin Exp Locker: bin $";
        !             6: 
        !             7: #define TRACE_PRINT printf
        !             8: 
        !             9: #define        Extern                          /* define Externs in sh.h */
        !            10: 
        !            11: #include <stddef.h>
        !            12: #include <stdlib.h>
        !            13: #include <stdio.h>
        !            14: #include <string.h>
        !            15: #include <unistd.h>
        !            16: #include <sys/fcntl.h>
        !            17: #include <signal.h>
        !            18: #include <errno.h>
        !            19: #include <setjmp.h>
        !            20: #include "sh.h"
        !            21: #include "lex.h"
        !            22: #include "tree.h"
        !            23: #include "table.h"
        !            24: 
        !            25: /*
        !            26:  * global data
        !            27:  */
        !            28: 
        !            29: Area   aperm;
        !            30: 
        !            31: static void    reclaim ARGS((void));
        !            32: 
        !            33: /*
        !            34:  * shell initialization
        !            35:  */
        !            36: 
        !            37: static char    initifs [] = "IFS= \t\n"; /* must be R/W */
        !            38: 
        !            39: static Const   char   initsubs [] = 
        !            40:   "${SHELL:=/bin/sh} ${PATH:=/bin:/usr/bin:.} ${HOME:=/} ${PS1:=$ } ${PS2:=> }";
        !            41: 
        !            42: static Const   char *initcoms [] = {
        !            43:        "cd", ".", NULL,                /* set up $PWD */
        !            44:        "typeset", "-x", "SHELL", "PATH", "HOME", NULL,
        !            45:        "typeset", "-r", "PWD", "OLDPWD", NULL,
        !            46:        "typeset", "-i", "SECONDS=0", "OPTIND", NULL,
        !            47:        "alias",
        !            48:          "integer=typeset -i", "pwd=print -r \"$PWD\"",
        !            49:          "history=fc -l", "r=fc -s",
        !            50: #if !COHERENT
        !            51:          "nohup=nohup ",
        !            52: #endif
        !            53:          "login=exec login", "newgrp=exec newgrp",
        !            54:          "type=whence -v", "functions=typeset -f",
        !            55:          "echo=print", "true=:", "false=let", "[=\\[", NULL,
        !            56:        NULL
        !            57: };
        !            58: 
        !            59: main(argc, argv, envp)
        !            60:        int argc;
        !            61:        register char **argv;
        !            62:        char **envp;
        !            63: {
        !            64:        register int i;
        !            65:        register char *arg;
        !            66:        int cflag = 0, qflag = 0;
        !            67:        char *name;
        !            68:        register Source *s;
        !            69:        register struct block *l = &globals;
        !            70:        register char **wp0, **wp;
        !            71:        extern char ksh_version [];
        !            72: 
        !            73:        ainit(&aperm);          /* initialize permanent Area */
        !            74: 
        !            75:        /* set up base enviroment */
        !            76:        e.type = E_NONE;
        !            77:        ainit(&e.area);
        !            78:        e.loc = l;
        !            79:        e.savefd = NULL;
        !            80:        e.oenv = NULL;
        !            81: 
        !            82:        initctypes();
        !            83: 
        !            84:        /* open file streams for fd's 0,1,2 */
        !            85:        fopenshf(0);    fopenshf(1);    fopenshf(2);
        !            86: 
        !            87:        /* set up variable and command dictionaries */
        !            88:        newblock();             /* set up global l->vars and l->funs */
        !            89:        tinit(&commands, APERM);
        !            90:        tinit(&builtins, APERM);
        !            91:        tinit(&lexicals, APERM);
        !            92:        tinit(&homedirs, APERM);
        !            93: 
        !            94:        /* import enviroment */
        !            95:        if (envp != NULL)
        !            96:                for (wp = envp; *wp != NULL; wp++)
        !            97:                        import(*wp);
        !            98: 
        !            99:        typeset(initifs, 0, 0); /* for security */
        !           100:        typeset(ksh_version, 0, 0); /* RDONLY */
        !           101: 
        !           102:        /* define shell keywords */
        !           103:        keywords();
        !           104: 
        !           105:        /* define built-in commands */
        !           106:        for (i = 0; shbuiltins[i].name != NULL; i++)
        !           107:                builtin(shbuiltins[i].name, shbuiltins[i].func);
        !           108:        for (i = 0; kshbuiltins[i].name != NULL; i++)
        !           109:                builtin(kshbuiltins[i].name, kshbuiltins[i].func);
        !           110: 
        !           111:        /* assign default shell variable values */
        !           112:        substitute(initsubs, 0);
        !           113:        /* execute initialization statements */
        !           114:        for (wp0 = (char**) initcoms; *wp0 != NULL; wp0 = wp+1) {
        !           115:                /* copy because the alias initializers are readonly */
        !           116:                for (wp = wp0; *wp != NULL; wp++)
        !           117:                        *wp = strsave(*wp, ATEMP);
        !           118:                shcomexec(wp0);
        !           119:        }
        !           120:        afreeall(ATEMP);
        !           121: 
        !           122:        if (geteuid() == 0)
        !           123:                setstr(global("PS1"), "# ");
        !           124: 
        !           125:        s = pushs(SFILE);
        !           126:        s->u.file = stdin;
        !           127:        cflag = 0;
        !           128:        name = *argv++;
        !           129: 
        !           130:        /* what a bloody mess */
        !           131:        if (--argc >= 1) {
        !           132:                if (argv[0][0] == '-' && argv[0][1] != '\0') {
        !           133:                        for (arg = argv[0]+1; *arg; arg++)
        !           134:                                switch (*arg) {
        !           135:                                  case 'c':
        !           136:                                        cflag = 1;
        !           137:                                        if (--argc > 0) {
        !           138:                                                s->type = SSTRING;
        !           139:                                                s->str = *++argv;
        !           140:                                        }
        !           141:                                        break;
        !           142:        
        !           143:                                  case 'q':
        !           144:                                        qflag = 1;
        !           145:                                        break;
        !           146: 
        !           147:                                  default:
        !           148:                                        if (*arg>='a' && *arg<='z')
        !           149:                                                flag[FLAG(*arg)]++;
        !           150:                                }
        !           151:                } else {
        !           152:                        argv--;
        !           153:                        argc++;
        !           154:                }
        !           155:                if (s->type == SFILE && --argc > 0) {
        !           156:                        if ((s->u.file = fopen(*++argv, "r")) == NULL)
        !           157:                                errorf("%s: cannot open\n", *argv);
        !           158:                        s->file = *argv;
        !           159:                        fileno(s->u.file) = savefd(fileno(s->u.file));
        !           160:                        setvbuf(s->u.file, (char *)NULL, _IOFBF, BUFSIZ);
        !           161:                }
        !           162:        }
        !           163: 
        !           164:        if (s->type == SFILE) {
        !           165:                if (fileno(s->u.file) == 0)
        !           166:                        flag[FSTDIN] = 1;
        !           167:                if (isatty(0) && isatty(1) && !cflag)
        !           168:                        flag[FTALKING] = 1;
        !           169:                if (flag[FTALKING] && flag[FSTDIN])
        !           170:                        s->type = STTY;
        !           171:        }
        !           172:        if (s->type == STTY) {
        !           173:                TRACE_PRINT("main: about to call fcntl. The next step is .profile\n");
        !           174:                ttyfd = fcntl(0, F_DUPFD, FDBASE);
        !           175:                TRACE_PRINT("main: ttyfd = %d\n");
        !           176: #if !COHERENT
        !           177:                (void) fcntl(ttyfd, F_SETFD, FD_CLEXEC);
        !           178: #endif
        !           179: #if EDIT
        !           180:                x_init();
        !           181:                TRACE_PRINT("main: x_init done!\n");
        !           182: #endif
        !           183:        }
        !           184: 
        !           185:        /* initialize job control */
        !           186:        j_init();
        !           187:        TRACE_PRINT("main: j_int() done!\n");
        !           188:        if (!qflag)
        !           189:                ignoresig(SIGQUIT);
        !           190: 
        !           191:        if (name[0] == '-') {
        !           192:                flag[FTALKING] = 1;
        !           193: #if !COHERENT
        !           194:                (void) include("/etc/profile");
        !           195: #endif
        !           196:                (void) include(".profile");
        !           197:                TRACE_PRINT("main: .profile included!\n");
        !           198:        }
        !           199: 
        !           200:        /* include $ENV */
        !           201:        arg = substitute(strval(global("ENV")), DOTILDE);
        !           202:        if (*arg != '\0')
        !           203:                (void) include(arg);
        !           204: 
        !           205:        if (flag[FTALKING]) {
        !           206:                signal(SIGTERM, trapsig);
        !           207:                ignoresig(SIGINT);
        !           208:        } else
        !           209:                flag[FHASHALL] = 1;
        !           210: 
        !           211: #if JOBS                       /* todo: could go before includes? */
        !           212:        if (s->type == STTY) {
        !           213:                flag[FMONITOR] = 1;
        !           214:                TRACE_PRINT("main: about to call j_change()\n");
        !           215:                j_change();
        !           216:                TRACE_PRINT("main: j_change done!\n");
        !           217:        }
        !           218: #endif
        !           219: 
        !           220:        l->argv = argv;
        !           221:        l->argc = argc;
        !           222:        l->argv[0] = name;
        !           223:        TRACE_PRINT("main: resetting opts\n");
        !           224:        resetopts();
        !           225:        TRACE_PRINT("main: resetting opts done!\n");
        !           226: 
        !           227:        argc = shell(s);
        !           228:        leave(argc);
        !           229: }
        !           230: 
        !           231: int
        !           232: include(name)
        !           233:        register char *name;
        !           234: {
        !           235:        register FILE *f;
        !           236:        register Source *s;
        !           237: 
        !           238:        if (strcmp(name, "-") != 0) {
        !           239:                f = fopen(name, "r");
        !           240:                if (f == NULL)
        !           241:                        return 0;
        !           242:                /* todo: the savefd doesn't get popped */
        !           243:                TRACE_PRINT("include(): About to call savefd\n");
        !           244:                fileno(f) = savefd(fileno(f)); /* questionable */
        !           245:                setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
        !           246:        } else
        !           247:                f = stdin;
        !           248:        s = pushs(SFILE);
        !           249:        s->u.file = f;
        !           250:        s->file = name;
        !           251:        /*return*/ shell(s);
        !           252:        if (f != stdin)
        !           253:                fclose(f);
        !           254:        return 1;
        !           255: }
        !           256: 
        !           257: int
        !           258: command(comm)
        !           259:        register char *comm;
        !           260: {
        !           261:        register Source *s;
        !           262: 
        !           263:        s = pushs(SSTRING);
        !           264:        s->str = comm;
        !           265:        return shell(s);
        !           266: }
        !           267: 
        !           268: /*
        !           269:  * run the commands from the input source, returning status.
        !           270:  */
        !           271: int
        !           272: shell(s)
        !           273:        Source *s;              /* input source */
        !           274: {
        !           275:        struct op *t;
        !           276:        Volatile int attempts = 13;
        !           277: 
        !           278:        newenv(E_PARSE);
        !           279:        e.interactive = 1;
        !           280:        exstat = 0;
        !           281:        if (setjmp(e.jbuf)) {
        !           282:                /*shellf("<unwind>");*/
        !           283:                if (trap)       /* pending SIGINT */
        !           284:                        shellf("\n");
        !           285:                sigtraps[SIGINT].set = 0;
        !           286:        }
        !           287: 
        !           288:        while (1) {
        !           289:                if (trap){
        !           290:                        TRACE_PRINT("shell: About to runtraps()\n");
        !           291:                        runtraps();
        !           292:                        TRACE_PRINT("shell: runtraps() done!\n");
        !           293:                }
        !           294:                if (flag[FTALKING]){
        !           295:                        TRACE_PRINT("shell: about to signal (sigint, trapsig)\n");
        !           296:                        signal(SIGINT, trapsig);
        !           297:                        TRACE_PRINT("shell: trapsig done!\n");
        !           298:                }
        !           299:                if (s->next == NULL){
        !           300:                        TRACE_PRINT("shell: s->echo is NIL\n");
        !           301:                        s->echo = flag[FVERBOSE];
        !           302:                }       
        !           303:                j_notify();
        !           304: 
        !           305:                if (s->type == STTY)
        !           306:                        prompt = substitute(strval(global("PS1")), 0);
        !           307: 
        !           308:                t = compile(s);
        !           309:                if (t != NULL && t->type == TEOF)
        !           310:                        if (s->type == SEOF && flag[FIGNEOF] && --attempts > 0) {
        !           311:                                s->type = STTY;
        !           312:                                shellf("Use `exit'\n");
        !           313:                        } else{
        !           314:                                TRACE_PRINT("shell: t is not NIL. About to break!\n");
        !           315:                                break;
        !           316:                                }
        !           317:                flushshf(2);    /* flush -v output */
        !           318: 
        !           319:                if (!flag[FNOEXEC] || s->type == STTY){
        !           320:                        TRACE_PRINT("shell: about to execute()\n");
        !           321:                        execute(t, 0);
        !           322:                }
        !           323:                TRACE_PRINT("shell: about to reclaim()\n");
        !           324:                reclaim();
        !           325:        }
        !           326:   Error:
        !           327:        quitenv();
        !           328:        return exstat;
        !           329: }
        !           330: 
        !           331: void
        !           332: leave(rv)
        !           333:        int rv;
        !           334: {
        !           335:        if (e.type == E_TCOM && e.oenv != NULL) /* exec'd command */
        !           336:                unwind();
        !           337:        runtrap(&sigtraps[0]);
        !           338:        j_exit();
        !           339:        exit(rv);
        !           340:        /* NOTREACHED */
        !           341: }
        !           342: 
        !           343: error()
        !           344: {
        !           345:        if (flag[FERREXIT] || !flag[FTALKING])
        !           346:                leave(1);
        !           347:        unwind();
        !           348: }
        !           349: 
        !           350: /* return to closest error handler or shell(), exit if none found */
        !           351: unwind()
        !           352: {
        !           353:        while (1)
        !           354:                switch (e.type) {
        !           355:                  case E_NONE:
        !           356:                        leave(1);
        !           357:                        /* NOTREACHED */
        !           358:                  case E_PARSE:
        !           359:                        longjmp(e.jbuf, 1);
        !           360:                        /* NOTREACHED */
        !           361:                  case E_ERRH:
        !           362:                        longjmp(e.jbuf, 1);
        !           363:                        /* NOTREACHED */
        !           364:                  default:
        !           365:                        quitenv();
        !           366:                        break;
        !           367:                }
        !           368: }
        !           369: 
        !           370: newenv(type)
        !           371: {
        !           372:        register struct env *ep;
        !           373: 
        !           374:        ep = (struct env *) alloc(sizeof(*ep), ATEMP);
        !           375:        *ep = e;
        !           376:        ainit(&e.area);
        !           377:        e.type = type;
        !           378:        e.oenv = ep;
        !           379:        e.savefd = NULL;
        !           380:        e.temps = NULL;
        !           381: }
        !           382: 
        !           383: quitenv()
        !           384: {
        !           385:        register struct env *ep;
        !           386:        register int fd;
        !           387: 
        !           388:        if ((ep = e.oenv) == NULL)
        !           389:                exit(exstat);   /* exit child */
        !           390:        if (e.loc != ep->loc)
        !           391:                popblock();
        !           392:        if (e.savefd != NULL)
        !           393:                for (fd = 0; fd < NUFILE; fd++)
        !           394:                        restfd(fd, e.savefd[fd]);
        !           395:        reclaim();
        !           396:        e = *ep;
        !           397: }
        !           398: 
        !           399: /* remove temp files and free ATEMP Area */
        !           400: static void
        !           401: reclaim()
        !           402: {
        !           403:        register struct temp *tp;
        !           404: 
        !           405:        for (tp = e.temps; tp != NULL; tp = tp->next)
        !           406:                remove(tp->name);
        !           407:        e.temps = NULL;
        !           408:        afreeall(&e.area);
        !           409: }
        !           410: 
        !           411: void
        !           412: aerror(ap, msg)
        !           413:        Area *ap;
        !           414:        Const char *msg;
        !           415: {
        !           416:        errorf("alloc internal error: %s\n", msg);
        !           417: }
        !           418: 

unix.superglobalmegacorp.com

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