Annotation of coherent/e/bin/ksh/main.c, revision 1.1

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

unix.superglobalmegacorp.com

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