Annotation of coherent/b/bin/sh.420/main.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * sh/main.c
                      3:  * The Bourne shell.
                      4:  * Main program, initialization and miscellaneous routines.
                      5:  */
                      6: 
                      7: #include <assert.h>
                      8: #include <stdarg.h>
                      9: #include "sh.h"
                     10: #include <fcntl.h>
                     11: 
                     12: void           fakearg         ();
                     13: void           reset           ();
                     14: void           ecantopen       ();
                     15: void           panic           ();
                     16: void           printe          ();
                     17: void           syntax          ();
                     18: 
                     19: 
                     20: int
                     21: main(argc, argv, envp)
                     22: char *argv[];
                     23: char *envp[];
                     24: {
                     25: 
                     26:        sarg0 = argc > 0 ? argv [0] : "";
                     27:        fakearg (0, argc, argv, envp);
                     28: 
                     29:        if (argc > 0 && argv [0][0] == '-') {
                     30:                lgnflag = 1;
                     31:                umask (ufmask = 022);
                     32:        } else if (argc > 0 && argv [0][0] == '+') {
                     33:                lgnflag = 2;
                     34:                umask (ufmask = 022);
                     35:        } else
                     36:                umask (ufmask = umask (ufmask));
                     37: 
                     38:        /*
                     39:         * NIGEL: we must *force* stdin to be unbuffered to defeat some
                     40:         * excessive cleverness in the stdio library. Note that line-buffering
                     41:         * is a mode that only applies to output.
                     42:         */
                     43: 
                     44:        if (setvbuf (stdin, NULL, _IONBF, BUFSIZ) != 0)
                     45:                printe ("Cannot set stdin buffering\n");
                     46: 
                     47:        if (setjmp (restart) != 0) {
                     48:                /* reentry for shell command file execution */
                     49:                fakearg (1, nargc, nargv, nenvp);
                     50:                argc = nargc;
                     51:                argv = nargv;
                     52:                envp = nenvp;
                     53:                cmdflag ++;
                     54:                nllflag = 0;
                     55:        }
                     56: 
                     57:        shpid = getpid ();
                     58:        initvar (envp);
                     59: 
                     60:        if (set (argc, argv, 1))
                     61:                return 1;
                     62: 
                     63:        if (cflag) {
                     64:                if (sargp [0] == NULL) {
                     65:                        printe ("No string for -c?");
                     66:                        return 1;
                     67:                }
                     68:                -- sargc;
                     69:                session (SARGS, * sargp ++);
                     70:        } else if (! sflag && ! iflag && sargc != 0) {
                     71:                sarg0 = * sargp ++;
                     72:                --sargc;
                     73:                if (scmdp == NULL)
                     74:                        scmdp = sarg0;
                     75:                session (SFILE, scmdp);
                     76:        } else
                     77:                session (SSTR, stdin);
                     78: 
                     79:        cleanup_shell_fns ();
                     80:        unlink_temp (capture_temp ());
                     81:        return slret;
                     82: }
                     83: 
                     84: 
                     85: /*
                     86:  * Make the arg listing of ps come out right.
                     87:  *     f == 0, first entry, determine buffer limits.
                     88:  *     f != 0, later entry, fill buffer with lies.
                     89:  */
                     90: 
                     91: void
                     92: fakearg(f, argc, argv, envp)
                     93: int f, argc;
                     94: char **argv, **envp;
                     95: {
                     96:        static char *fbuf;
                     97:        static int nbuf;
                     98:        register int n;
                     99: 
                    100:        if (f == 0) {
                    101:                fbuf = argv [0];
                    102:                nbuf = 0;
                    103:                if (envp != NULL && envp [0] != NULL) {
                    104:                        while (envp [1] != NULL)
                    105:                                envp += 1;
                    106:                        nbuf = envp [0] - fbuf + strlen (envp [0]) - 1;
                    107:                } else if (argc > 0)
                    108:                        nbuf = argv [argc - 1] - fbuf +
                    109:                                strlen (argv [argc - 1]) - 1;
                    110:        } else {
                    111:                if (fbuf == NULL || nbuf == 0)
                    112:                        return;
                    113:                n = 0;
                    114:                fbuf [0] = 0;
                    115:                while (-- argc > 0) {
                    116:                        argv += 1;
                    117:                        n += strlen (argv [0]) + 1;
                    118:                        if (n >= nbuf)
                    119:                                break;
                    120:                        strcat (fbuf, argv [0]);
                    121:                        strcat (fbuf, " ");
                    122:                }
                    123:                strcat (fbuf, "\1");    /* non-ascii terminator */
                    124:        }
                    125: }
                    126: 
                    127: 
                    128: /*
                    129:  * Push a session of the indicated type. A non-zero return value is the
                    130:  * appropriate return value for the session, but offset by one.
                    131:  */
                    132: 
                    133: int
                    134: push_session (type, info, session)
                    135: int            type;
                    136: __VOID__      *        info;
                    137: SES          * session;
                    138: {
                    139:        session->s_next = sesp;
                    140:        sesp = session;
                    141:        session->s_bpp = savebuf ();
                    142: 
                    143:        switch (session->s_type = type) {
                    144:        case SARGS:
                    145:                session->s_strp = (char *) info;
                    146:                session->s_flag = 0;
                    147:                break;
                    148: 
                    149:        case SARGV:
                    150:                session->s_argv = (char **) info;
                    151:                if ((session->s_strp = session->s_argv [0]) == NULL)
                    152:                        return 1;
                    153:                session->s_flag = 0;
                    154:                break;
                    155: 
                    156:        case SFILE:
                    157:                session->s_strp = (char *) info;
                    158: 
                    159:                /*
                    160:                 * NIGEL: We should take steps to ensure that the file
                    161:                 * descriptors created for these input files lie above the
                    162:                 * range that can be redirected in scripts!
                    163:                 */
                    164: 
                    165:                if ((type = open (session->s_strp, O_RDONLY)) < 0) {
                    166:                        ecantopen (session->s_strp);
                    167:                        return 2;
                    168:                }
                    169:                if (type > 9) {
                    170:                        int             scan;
                    171:                        for (scan = 10 ; scan < FOPEN_MAX ; scan ++) {
                    172:                                if (fcntl (scan, F_GETFD) == -1) {
                    173:                                        /*
                    174:                                         * Move the new FD to the new place.
                    175:                                         */
                    176: 
                    177:                                        dup2 (type, scan);
                    178:                                        close (type);
                    179:                                        type = scan;
                    180: 
                    181:                                        break;
                    182:                                }
                    183:                        }
                    184:                }
                    185:                if ((session->s_ifp = fdopen (type, "r")) == NULL) {
                    186:                        ecantopen (session->s_strp);
                    187:                        return 2;
                    188:                }
                    189:                session->s_flag = isatty (fileno (session->s_ifp)) &&
                    190:                                          isatty (2);
                    191:                break;
                    192: 
                    193:        case SSTR:
                    194:                session->s_strp = NULL;
                    195:                session->s_ifp = (FILE *) info;
                    196:                session->s_flag = isatty (fileno (session->s_ifp)) &&
                    197:                                          isatty (2);
                    198:                break;
                    199:        }
                    200: 
                    201:        return 0;
                    202: }
                    203: 
                    204: 
                    205: /*
                    206:  * Pop the passed-in session, which must be the current session.
                    207:  */
                    208: 
                    209: void
                    210: pop_session (session)
                    211: SES          * session;
                    212: {
                    213:        assert (sesp == session);
                    214: 
                    215:        freebuf (session->s_bpp);
                    216: 
                    217:        if (session->s_type == SFILE)
                    218:                fclose (session->s_ifp);
                    219: 
                    220:        if (session->s_next == NULL) {
                    221:                sigintr (0);
                    222:                recover (IRDY);
                    223:        }
                    224: 
                    225:        sesp = session->s_next;
                    226: }
                    227: 
                    228: 
                    229: /*
                    230:  * Loop on input.
                    231:  */
                    232: 
                    233: int
                    234: session(t, p)
                    235: register char *p;
                    236: {
                    237:        SES s;
                    238:        register int rcode;
                    239: 
                    240:        if ((rcode = push_session (t, p, & s)) > 0)
                    241:                return rcode - 1;
                    242: 
                    243:        if (s.s_next == NULL) {         /* Initial entry */
                    244:                if (iflag)
                    245:                        s.s_flag = iflag;
                    246:                else
                    247:                        iflag = s.s_flag;
                    248:                dflttrp (IRDY);
                    249:        }
                    250: 
                    251:        /* Loop on input */
                    252:        for (;;) {
                    253:                unlink_temp (capture_temp ());
                    254: 
                    255:                rcode = setjmp (s.s_envl);
                    256:                switch (rcode) {
                    257:                case RSET:      /* initial setjmp call */
                    258:                        switch (lgnflag) {
                    259:                        case 1:         /* - sign invocation */
                    260:                                lgnflag = 0;
                    261:                                if (ffind ("/etc", "profile", 4))
                    262:                                        session (SFILE, duplstr (strt, 0));
                    263:                                recover (IPROF);
                    264:                                if (* vhome && ffind (vhome, ".profile", 4))
                    265:                                        session (SFILE, duplstr (strt, 0));
                    266:                                break;
                    267: 
                    268:                        case 2:         /* + sign invocation */
                    269:                                lgnflag = 0;
                    270:                                if (ffind ("/etc", "profile", 4))
                    271:                                        session (SFILE, duplstr (strt, 0));
                    272:                                recover (IPROF);
                    273:                                return exshell (findvar ("SHELL"));
                    274:                        }
                    275:                        checkmail ();
                    276:                        comflag = 1;
                    277:                        errflag = 0;
                    278:                        recover (IRDY);
                    279:                        freebuf (s.s_bpp);
                    280:                        s.s_bpp = savebuf ();
                    281:                        if (yyparse () != 0)
                    282:                                syntax ();
                    283: 
                    284:                case REOF:
                    285:                        recover (IRDY);
                    286:                        break;
                    287: 
                    288:                case RCMD:
                    289:                        recover (IRDY);
                    290:                        s.s_con = NULL;
                    291:                        command (s.s_node);
                    292:                        if (tflag && tflag ++ >= 2)
                    293:                                break;
                    294:                        continue;
                    295: 
                    296:                case RERR:
                    297:                        recover (IRDY);
                    298:                        if (! errflag)
                    299:                                syntax ();
                    300:                        if (! iflag || (tflag && tflag ++ >= 2))
                    301:                                break;
                    302:                        continue;
                    303: 
                    304:                case RINT:
                    305:                        if (s.s_next != NULL) {
                    306:                                sesp = s.s_next;
                    307:                                reset (RINT);
                    308:                                NOTREACHED;
                    309:                        }
                    310:                        prpflag = 2;
                    311:                        if (! iflag || (tflag && tflag ++ >= 2))
                    312:                                break;
                    313:                        continue;
                    314: 
                    315:                case RUEXITS:
                    316:                case RUABORT:
                    317:                        if (s.s_next != NULL) {
                    318:                                sesp = s.s_next;
                    319:                                reset (rcode);
                    320:                                NOTREACHED;
                    321:                        }
                    322:                        if (rcode == RUEXITS || ! iflag ||
                    323:                            (tflag && tflag ++ >= 2))
                    324:                                break;
                    325:                        continue;
                    326: 
                    327:                case RNOSBRK:
                    328:                case RSYSER:
                    329:                case RBRKCON:
                    330:                case RNOWAY:
                    331:                default:
                    332:                        if (s.s_next != NULL)
                    333:                                break;
                    334:                        if (! iflag || (tflag && tflag ++ >= 2))
                    335:                                break;
                    336:                        continue;
                    337:                }
                    338:                break;
                    339:        }
                    340: 
                    341:        pop_session (& s);
                    342:        return (slret);
                    343: }
                    344: 
                    345: 
                    346: void
                    347: reset (f)
                    348: {
                    349:        longjmp (sesp->s_envl, f);
                    350:        NOTREACHED;
                    351: }
                    352: 
                    353: 
                    354: /*
                    355:  * Global head of list of temporary files.
                    356:  */
                    357: 
                    358: static TEMP_FILE      *        temp_list;
                    359: 
                    360: ALLOC_COUNT (temp)
                    361: 
                    362: /*
                    363:  * Remember the name of a temporary file.
                    364:  */
                    365: 
                    366: void
                    367: remember_temp (filename)
                    368: char * filename;
                    369: {
                    370:        TEMP_FILE     * temp = (TEMP_FILE *) salloc (sizeof (* temp));
                    371: 
                    372:        temp->tf_name = duplstr (filename, 1);
                    373:        temp->tf_next = temp_list;
                    374:        temp_list = temp;
                    375: 
                    376:        ALLOC_ALLOC (temp)
                    377: }
                    378: 
                    379: 
                    380: /*
                    381:  * Return a pointer to the current global list of temporary files and clear
                    382:  * the global pointer to that list.
                    383:  */
                    384: 
                    385: TEMP_FILE *
                    386: capture_temp ()
                    387: {
                    388:        TEMP_FILE     * temp = temp_list;
                    389: 
                    390:        temp_list = NULL;
                    391:        return temp;
                    392: }
                    393: 
                    394: 
                    395: /*
                    396:  * Deallocate a list of temporary files.
                    397:  */
                    398: 
                    399: void
                    400: forget_temp (templist)
                    401: TEMP_FILE     *        templist;
                    402: {
                    403:        TEMP_FILE     * temp;
                    404: 
                    405:        while ((temp = templist) != NULL) {
                    406: 
                    407:                templist = temp->tf_next;
                    408: 
                    409:                ALLOC_FREE (temp);
                    410:                sfree (temp->tf_name);
                    411:                sfree (temp);
                    412:        }
                    413: }
                    414: 
                    415: 
                    416: /*
                    417:  * Walk over a list of temporary files, unlinking the files and deallocating
                    418:  * the list nodes.
                    419:  */
                    420: 
                    421: void
                    422: unlink_temp (templist)
                    423: TEMP_FILE     *        templist;
                    424: {
                    425:        TEMP_FILE     * temp;
                    426: 
                    427:        while ((temp = templist) != NULL) {
                    428: 
                    429:                templist = temp->tf_next;
                    430:                unlink (temp->tf_name);
                    431: 
                    432:                ALLOC_FREE (temp)
                    433:                sfree (temp->tf_name);
                    434:                sfree (temp);
                    435:        }
                    436: }
                    437: 
                    438: 
                    439: /*
                    440:  * Make a temp file name.
                    441:  */
                    442: 
                    443: char *
                    444: shtmp ()
                    445: {
                    446:        static char tmpfile [] = "/tmp/shXXXXXXX";
                    447:        static int tmpflag = 0;
                    448: 
                    449:        tmpflag ++;
                    450:        sprintf (tmpfile + 6, "%05d%c%c", shpid, tmpflag % 26 + 'a',
                    451:                 (tmpflag / 26) % 26 + 'a');
                    452:        return tmpfile;
                    453: }
                    454: 
                    455: 
                    456: /*
                    457:  * Print formatted.
                    458:  */
                    459: 
                    460: void
                    461: prints (format /* , ... */)
                    462: char * format;
                    463: {
                    464:        va_list         args;
                    465: 
                    466:        va_start (args, format);
                    467:        vfprintf (stderr, format, args);
                    468:        va_end (args);
                    469: }
                    470: 
                    471: 
                    472: /*
                    473:  * Make a core dump in /tmp and longjmp back to session -
                    474:  *     there's a possibility we'll die horribly.
                    475:  */
                    476: 
                    477: void
                    478: panic (i)
                    479: int i;
                    480: {
                    481: #ifdef PARANOID
                    482:        register int f;
                    483: 
                    484:        if ((f = fork ()) == 0) {
                    485:                abort ();
                    486:                NOTREACHED;
                    487:        }
                    488:        waitc (f);
                    489: #endif
                    490:        printe ("Internal shell assertion %d failed", i);
                    491:        reset (RNOWAY);
                    492:        NOTREACHED;
                    493: }
                    494: 
                    495: 
                    496: /*
                    497:  * Print out an error message.
                    498:  */
                    499: 
                    500: void
                    501: printe (format /* , ... */)
                    502: char * format;
                    503: {
                    504:        errflag += 1;
                    505:        if (! noeflag) {
                    506:                va_list         args;
                    507: 
                    508:                va_start (args, format);
                    509:                vfprintf (stderr, format, args);
                    510:                va_end (args);
                    511:                fprintf (stderr, "\n");
                    512:        }
                    513: }
                    514: 
                    515: /*
                    516:  * Some familiar errors.
                    517:  */
                    518: 
                    519: void   ecantopen(s) char *s; { printe ("Cannot open %s", s); }
                    520: void   ecantfind(s) char *s; { printe ("Cannot find %s", s); }
                    521: void   e2big(s) char *s; { printe ("File to big to execute: %s", s); }
                    522: void   ecantmake(s) char *s; { printe ("Cannot create %s", s); }
                    523: void   emisschar(c) { printe ("Missing `%c'", c); }
                    524: void   ecantfdop() { printe ("Fdopen failed"); }
                    525: void   enotdef(s) char *s; { printe ("Cannot find variable %s", s); }
                    526: void   eillvar(s) char *s; { printe ("Illegal variable name: %s", s); }
                    527: void   eredir() { printe ("Illegal redirection"); }
                    528: void   etoolong(s) char *s; {
                    529:        printe ("Argument too long %s: %.*s", s, STRSIZE, strt);
                    530: }
                    531: void   eredirundo() {
                    532:   printe ("Unable to preserve redirection state when redirecting builtin");
                    533: }
                    534: 
                    535: 
                    536: /*
                    537:  * Don't print out an error message.
                    538:  */
                    539: 
                    540: void
                    541: yyerror()
                    542: {
                    543: }
                    544: 
                    545: 
                    546: /*
                    547:  * print out the prompt given the prompt to write
                    548:  */
                    549: 
                    550: void
                    551: prompt(vps)
                    552: char *vps;
                    553: {
                    554:        prints ("%s", vps);
                    555: #if RSX
                    556:        fflush (stdout);
                    557: #endif
                    558: }
                    559: 
                    560: 
                    561: /*
                    562:  * Syntax error message - print line number and file if
                    563:  *     not interactive.
                    564:  */
                    565: 
                    566: void
                    567: syntax()
                    568: {
                    569:        if (sesp->s_type == SFILE) {
                    570:                if (feof (sesp->s_ifp))
                    571:                        printe ("%s: Syntax error at EOF", sesp->s_strp);
                    572:                else
                    573:                        printe ("%s: Syntax error in line %d", sesp->s_strp,
                    574:                                yyline);
                    575:        } else
                    576:                printe ("Syntax error");
                    577: }

unix.superglobalmegacorp.com

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