Annotation of coherent/e/bin/ksh/main.c, revision 1.1.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.