Annotation of coherent/a/usr/bob/korn/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: /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.