[BACK]Return to lex.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mail

Annotation of src/usr.bin/mail/lex.c, Revision 1.1

1.1     ! deraadt     1: /*
        !             2:  * Copyright (c) 1980, 1993
        !             3:  *     The Regents of the University of California.  All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  * 3. All advertising materials mentioning features or use of this software
        !            14:  *    must display the following acknowledgement:
        !            15:  *     This product includes software developed by the University of
        !            16:  *     California, Berkeley and its contributors.
        !            17:  * 4. Neither the name of the University nor the names of its contributors
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            31:  * SUCH DAMAGE.
        !            32:  */
        !            33:
        !            34: #ifndef lint
        !            35: static char sccsid[] = "from: @(#)lex.c        8.1 (Berkeley) 6/6/93";
        !            36: static char rcsid[] = "$Id: lex.c,v 1.5 1994/11/28 20:03:33 jtc Exp $";
        !            37: #endif /* not lint */
        !            38:
        !            39: #include "rcv.h"
        !            40: #include <errno.h>
        !            41: #include <fcntl.h>
        !            42: #include "extern.h"
        !            43:
        !            44: /*
        !            45:  * Mail -- a mail program
        !            46:  *
        !            47:  * Lexical processing of commands.
        !            48:  */
        !            49:
        !            50: char   *prompt = "& ";
        !            51:
        !            52: /*
        !            53:  * Set up editing on the given file name.
        !            54:  * If the first character of name is %, we are considered to be
        !            55:  * editing the file, otherwise we are reading our mail which has
        !            56:  * signficance for mbox and so forth.
        !            57:  */
        !            58: int
        !            59: setfile(name)
        !            60:        char *name;
        !            61: {
        !            62:        FILE *ibuf;
        !            63:        int i;
        !            64:        struct stat stb;
        !            65:        char isedit = *name != '%';
        !            66:        char *who = name[1] ? name + 1 : myname;
        !            67:        static int shudclob;
        !            68:        extern char *tempMesg;
        !            69:        extern int errno;
        !            70:
        !            71:        if ((name = expand(name)) == NOSTR)
        !            72:                return -1;
        !            73:
        !            74:        if ((ibuf = Fopen(name, "r")) == NULL) {
        !            75:                if (!isedit && errno == ENOENT)
        !            76:                        goto nomail;
        !            77:                perror(name);
        !            78:                return(-1);
        !            79:        }
        !            80:
        !            81:        if (fstat(fileno(ibuf), &stb) < 0) {
        !            82:                perror("fstat");
        !            83:                Fclose(ibuf);
        !            84:                return (-1);
        !            85:        }
        !            86:
        !            87:        switch (stb.st_mode & S_IFMT) {
        !            88:        case S_IFDIR:
        !            89:                Fclose(ibuf);
        !            90:                errno = EISDIR;
        !            91:                perror(name);
        !            92:                return (-1);
        !            93:
        !            94:        case S_IFREG:
        !            95:                break;
        !            96:
        !            97:        default:
        !            98:                Fclose(ibuf);
        !            99:                errno = EINVAL;
        !           100:                perror(name);
        !           101:                return (-1);
        !           102:        }
        !           103:
        !           104:        /*
        !           105:         * Looks like all will be well.  We must now relinquish our
        !           106:         * hold on the current set of stuff.  Must hold signals
        !           107:         * while we are reading the new file, else we will ruin
        !           108:         * the message[] data structure.
        !           109:         */
        !           110:
        !           111:        holdsigs();
        !           112:        if (shudclob)
        !           113:                quit();
        !           114:
        !           115:        /*
        !           116:         * Copy the messages into /tmp
        !           117:         * and set pointers.
        !           118:         */
        !           119:
        !           120:        readonly = 0;
        !           121:        if ((i = open(name, 1)) < 0)
        !           122:                readonly++;
        !           123:        else
        !           124:                close(i);
        !           125:        if (shudclob) {
        !           126:                fclose(itf);
        !           127:                fclose(otf);
        !           128:        }
        !           129:        shudclob = 1;
        !           130:        edit = isedit;
        !           131:        strcpy(prevfile, mailname);
        !           132:        if (name != mailname)
        !           133:                strcpy(mailname, name);
        !           134:        mailsize = fsize(ibuf);
        !           135:        if ((otf = fopen(tempMesg, "w")) == NULL) {
        !           136:                perror(tempMesg);
        !           137:                exit(1);
        !           138:        }
        !           139:        (void) fcntl(fileno(otf), F_SETFD, 1);
        !           140:        if ((itf = fopen(tempMesg, "r")) == NULL) {
        !           141:                perror(tempMesg);
        !           142:                exit(1);
        !           143:        }
        !           144:        (void) fcntl(fileno(itf), F_SETFD, 1);
        !           145:        rm(tempMesg);
        !           146:        setptr(ibuf);
        !           147:        setmsize(msgCount);
        !           148:        Fclose(ibuf);
        !           149:        relsesigs();
        !           150:        sawcom = 0;
        !           151:        if (!edit && msgCount == 0) {
        !           152: nomail:
        !           153:                fprintf(stderr, "No mail for %s\n", who);
        !           154:                return -1;
        !           155:        }
        !           156:        return(0);
        !           157: }
        !           158:
        !           159: int    *msgvec;
        !           160: int    reset_on_stop;                  /* do a reset() if stopped */
        !           161:
        !           162: /*
        !           163:  * Interpret user commands one by one.  If standard input is not a tty,
        !           164:  * print no prompt.
        !           165:  */
        !           166: void
        !           167: commands()
        !           168: {
        !           169:        int eofloop = 0;
        !           170:        register int n;
        !           171:        char linebuf[LINESIZE];
        !           172:        void intr(), stop(), hangup();
        !           173:
        !           174:        if (!sourcing) {
        !           175:                if (signal(SIGINT, SIG_IGN) != SIG_IGN)
        !           176:                        signal(SIGINT, intr);
        !           177:                if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
        !           178:                        signal(SIGHUP, hangup);
        !           179:                signal(SIGTSTP, stop);
        !           180:                signal(SIGTTOU, stop);
        !           181:                signal(SIGTTIN, stop);
        !           182:        }
        !           183:        setexit();
        !           184:        for (;;) {
        !           185:                /*
        !           186:                 * Print the prompt, if needed.  Clear out
        !           187:                 * string space, and flush the output.
        !           188:                 */
        !           189:                if (!sourcing && value("interactive") != NOSTR) {
        !           190:                        reset_on_stop = 1;
        !           191:                        printf(prompt);
        !           192:                }
        !           193:                fflush(stdout);
        !           194:                sreset();
        !           195:                /*
        !           196:                 * Read a line of commands from the current input
        !           197:                 * and handle end of file specially.
        !           198:                 */
        !           199:                n = 0;
        !           200:                for (;;) {
        !           201:                        if (readline(input, &linebuf[n], LINESIZE - n) < 0) {
        !           202:                                if (n == 0)
        !           203:                                        n = -1;
        !           204:                                break;
        !           205:                        }
        !           206:                        if ((n = strlen(linebuf)) == 0)
        !           207:                                break;
        !           208:                        n--;
        !           209:                        if (linebuf[n] != '\\')
        !           210:                                break;
        !           211:                        linebuf[n++] = ' ';
        !           212:                }
        !           213:                reset_on_stop = 0;
        !           214:                if (n < 0) {
        !           215:                                /* eof */
        !           216:                        if (loading)
        !           217:                                break;
        !           218:                        if (sourcing) {
        !           219:                                unstack();
        !           220:                                continue;
        !           221:                        }
        !           222:                        if (value("interactive") != NOSTR &&
        !           223:                            value("ignoreeof") != NOSTR &&
        !           224:                            ++eofloop < 25) {
        !           225:                                printf("Use \"quit\" to quit.\n");
        !           226:                                continue;
        !           227:                        }
        !           228:                        break;
        !           229:                }
        !           230:                eofloop = 0;
        !           231:                if (execute(linebuf, 0))
        !           232:                        break;
        !           233:        }
        !           234: }
        !           235:
        !           236: /*
        !           237:  * Execute a single command.
        !           238:  * Command functions return 0 for success, 1 for error, and -1
        !           239:  * for abort.  A 1 or -1 aborts a load or source.  A -1 aborts
        !           240:  * the interactive command loop.
        !           241:  * Contxt is non-zero if called while composing mail.
        !           242:  */
        !           243: int
        !           244: execute(linebuf, contxt)
        !           245:        char linebuf[];
        !           246:        int contxt;
        !           247: {
        !           248:        char word[LINESIZE];
        !           249:        char *arglist[MAXARGC];
        !           250:        struct cmd *com;
        !           251:        register char *cp, *cp2;
        !           252:        register int c;
        !           253:        int muvec[2];
        !           254:        int e = 1;
        !           255:
        !           256:        /*
        !           257:         * Strip the white space away from the beginning
        !           258:         * of the command, then scan out a word, which
        !           259:         * consists of anything except digits and white space.
        !           260:         *
        !           261:         * Handle ! escapes differently to get the correct
        !           262:         * lexical conventions.
        !           263:         */
        !           264:
        !           265:        for (cp = linebuf; isspace(*cp); cp++)
        !           266:                ;
        !           267:        if (*cp == '!') {
        !           268:                if (sourcing) {
        !           269:                        printf("Can't \"!\" while sourcing\n");
        !           270:                        goto out;
        !           271:                }
        !           272:                shell(cp+1);
        !           273:                return(0);
        !           274:        }
        !           275:        cp2 = word;
        !           276:        while (*cp && index(" \t0123456789$^.:/-+*'\"", *cp) == NOSTR)
        !           277:                *cp2++ = *cp++;
        !           278:        *cp2 = '\0';
        !           279:
        !           280:        /*
        !           281:         * Look up the command; if not found, bitch.
        !           282:         * Normally, a blank command would map to the
        !           283:         * first command in the table; while sourcing,
        !           284:         * however, we ignore blank lines to eliminate
        !           285:         * confusion.
        !           286:         */
        !           287:
        !           288:        if (sourcing && *word == '\0')
        !           289:                return(0);
        !           290:        com = lex(word);
        !           291:        if (com == NONE) {
        !           292:                printf("Unknown command: \"%s\"\n", word);
        !           293:                goto out;
        !           294:        }
        !           295:
        !           296:        /*
        !           297:         * See if we should execute the command -- if a conditional
        !           298:         * we always execute it, otherwise, check the state of cond.
        !           299:         */
        !           300:
        !           301:        if ((com->c_argtype & F) == 0)
        !           302:                if (cond == CRCV && !rcvmode || cond == CSEND && rcvmode)
        !           303:                        return(0);
        !           304:
        !           305:        /*
        !           306:         * Process the arguments to the command, depending
        !           307:         * on the type he expects.  Default to an error.
        !           308:         * If we are sourcing an interactive command, it's
        !           309:         * an error.
        !           310:         */
        !           311:
        !           312:        if (!rcvmode && (com->c_argtype & M) == 0) {
        !           313:                printf("May not execute \"%s\" while sending\n",
        !           314:                    com->c_name);
        !           315:                goto out;
        !           316:        }
        !           317:        if (sourcing && com->c_argtype & I) {
        !           318:                printf("May not execute \"%s\" while sourcing\n",
        !           319:                    com->c_name);
        !           320:                goto out;
        !           321:        }
        !           322:        if (readonly && com->c_argtype & W) {
        !           323:                printf("May not execute \"%s\" -- message file is read only\n",
        !           324:                   com->c_name);
        !           325:                goto out;
        !           326:        }
        !           327:        if (contxt && com->c_argtype & R) {
        !           328:                printf("Cannot recursively invoke \"%s\"\n", com->c_name);
        !           329:                goto out;
        !           330:        }
        !           331:        switch (com->c_argtype & ~(F|P|I|M|T|W|R)) {
        !           332:        case MSGLIST:
        !           333:                /*
        !           334:                 * A message list defaulting to nearest forward
        !           335:                 * legal message.
        !           336:                 */
        !           337:                if (msgvec == 0) {
        !           338:                        printf("Illegal use of \"message list\"\n");
        !           339:                        break;
        !           340:                }
        !           341:                if ((c = getmsglist(cp, msgvec, com->c_msgflag)) < 0)
        !           342:                        break;
        !           343:                if (c  == 0) {
        !           344:                        *msgvec = first(com->c_msgflag,
        !           345:                                com->c_msgmask);
        !           346:                        msgvec[1] = NULL;
        !           347:                }
        !           348:                if (*msgvec == NULL) {
        !           349:                        printf("No applicable messages\n");
        !           350:                        break;
        !           351:                }
        !           352:                e = (*com->c_func)(msgvec);
        !           353:                break;
        !           354:
        !           355:        case NDMLIST:
        !           356:                /*
        !           357:                 * A message list with no defaults, but no error
        !           358:                 * if none exist.
        !           359:                 */
        !           360:                if (msgvec == 0) {
        !           361:                        printf("Illegal use of \"message list\"\n");
        !           362:                        break;
        !           363:                }
        !           364:                if (getmsglist(cp, msgvec, com->c_msgflag) < 0)
        !           365:                        break;
        !           366:                e = (*com->c_func)(msgvec);
        !           367:                break;
        !           368:
        !           369:        case STRLIST:
        !           370:                /*
        !           371:                 * Just the straight string, with
        !           372:                 * leading blanks removed.
        !           373:                 */
        !           374:                while (isspace(*cp))
        !           375:                        cp++;
        !           376:                e = (*com->c_func)(cp);
        !           377:                break;
        !           378:
        !           379:        case RAWLIST:
        !           380:                /*
        !           381:                 * A vector of strings, in shell style.
        !           382:                 */
        !           383:                if ((c = getrawlist(cp, arglist,
        !           384:                                sizeof arglist / sizeof *arglist)) < 0)
        !           385:                        break;
        !           386:                if (c < com->c_minargs) {
        !           387:                        printf("%s requires at least %d arg(s)\n",
        !           388:                                com->c_name, com->c_minargs);
        !           389:                        break;
        !           390:                }
        !           391:                if (c > com->c_maxargs) {
        !           392:                        printf("%s takes no more than %d arg(s)\n",
        !           393:                                com->c_name, com->c_maxargs);
        !           394:                        break;
        !           395:                }
        !           396:                e = (*com->c_func)(arglist);
        !           397:                break;
        !           398:
        !           399:        case NOLIST:
        !           400:                /*
        !           401:                 * Just the constant zero, for exiting,
        !           402:                 * eg.
        !           403:                 */
        !           404:                e = (*com->c_func)(0);
        !           405:                break;
        !           406:
        !           407:        default:
        !           408:                panic("Unknown argtype");
        !           409:        }
        !           410:
        !           411: out:
        !           412:        /*
        !           413:         * Exit the current source file on
        !           414:         * error.
        !           415:         */
        !           416:        if (e) {
        !           417:                if (e < 0)
        !           418:                        return 1;
        !           419:                if (loading)
        !           420:                        return 1;
        !           421:                if (sourcing)
        !           422:                        unstack();
        !           423:                return 0;
        !           424:        }
        !           425:        if (value("autoprint") != NOSTR && com->c_argtype & P)
        !           426:                if ((dot->m_flag & MDELETED) == 0) {
        !           427:                        muvec[0] = dot - &message[0] + 1;
        !           428:                        muvec[1] = 0;
        !           429:                        type(muvec);
        !           430:                }
        !           431:        if (!sourcing && (com->c_argtype & T) == 0)
        !           432:                sawcom = 1;
        !           433:        return(0);
        !           434: }
        !           435:
        !           436: /*
        !           437:  * Set the size of the message vector used to construct argument
        !           438:  * lists to message list functions.
        !           439:  */
        !           440: void
        !           441: setmsize(sz)
        !           442:        int sz;
        !           443: {
        !           444:
        !           445:        if (msgvec != 0)
        !           446:                free((char *) msgvec);
        !           447:        msgvec = (int *) calloc((unsigned) (sz + 1), sizeof *msgvec);
        !           448: }
        !           449:
        !           450: /*
        !           451:  * Find the correct command in the command table corresponding
        !           452:  * to the passed command "word"
        !           453:  */
        !           454:
        !           455: struct cmd *
        !           456: lex(word)
        !           457:        char word[];
        !           458: {
        !           459:        register struct cmd *cp;
        !           460:        extern struct cmd cmdtab[];
        !           461:
        !           462:        for (cp = &cmdtab[0]; cp->c_name != NOSTR; cp++)
        !           463:                if (isprefix(word, cp->c_name))
        !           464:                        return(cp);
        !           465:        return(NONE);
        !           466: }
        !           467:
        !           468: /*
        !           469:  * Determine if as1 is a valid prefix of as2.
        !           470:  * Return true if yep.
        !           471:  */
        !           472: int
        !           473: isprefix(as1, as2)
        !           474:        char *as1, *as2;
        !           475: {
        !           476:        register char *s1, *s2;
        !           477:
        !           478:        s1 = as1;
        !           479:        s2 = as2;
        !           480:        while (*s1++ == *s2)
        !           481:                if (*s2++ == '\0')
        !           482:                        return(1);
        !           483:        return(*--s1 == '\0');
        !           484: }
        !           485:
        !           486: /*
        !           487:  * The following gets called on receipt of an interrupt.  This is
        !           488:  * to abort printout of a command, mainly.
        !           489:  * Dispatching here when command() is inactive crashes rcv.
        !           490:  * Close all open files except 0, 1, 2, and the temporary.
        !           491:  * Also, unstack all source files.
        !           492:  */
        !           493:
        !           494: int    inithdr;                        /* am printing startup headers */
        !           495:
        !           496: /*ARGSUSED*/
        !           497: void
        !           498: intr(s)
        !           499:        int s;
        !           500: {
        !           501:
        !           502:        noreset = 0;
        !           503:        if (!inithdr)
        !           504:                sawcom++;
        !           505:        inithdr = 0;
        !           506:        while (sourcing)
        !           507:                unstack();
        !           508:
        !           509:        close_all_files();
        !           510:
        !           511:        if (image >= 0) {
        !           512:                close(image);
        !           513:                image = -1;
        !           514:        }
        !           515:        fprintf(stderr, "Interrupt\n");
        !           516:        reset(0);
        !           517: }
        !           518:
        !           519: /*
        !           520:  * When we wake up after ^Z, reprint the prompt.
        !           521:  */
        !           522: void
        !           523: stop(s)
        !           524:        int s;
        !           525: {
        !           526:        sig_t old_action = signal(s, SIG_DFL);
        !           527:
        !           528:        sigsetmask(sigblock(0) & ~sigmask(s));
        !           529:        kill(0, s);
        !           530:        sigblock(sigmask(s));
        !           531:        signal(s, old_action);
        !           532:        if (reset_on_stop) {
        !           533:                reset_on_stop = 0;
        !           534:                reset(0);
        !           535:        }
        !           536: }
        !           537:
        !           538: /*
        !           539:  * Branch here on hangup signal and simulate "exit".
        !           540:  */
        !           541: /*ARGSUSED*/
        !           542: void
        !           543: hangup(s)
        !           544:        int s;
        !           545: {
        !           546:
        !           547:        /* nothing to do? */
        !           548:        exit(1);
        !           549: }
        !           550:
        !           551: /*
        !           552:  * Announce the presence of the current Mail version,
        !           553:  * give the message count, and print a header listing.
        !           554:  */
        !           555: void
        !           556: announce()
        !           557: {
        !           558:        int vec[2], mdot;
        !           559:
        !           560:        mdot = newfileinfo();
        !           561:        vec[0] = mdot;
        !           562:        vec[1] = 0;
        !           563:        dot = &message[mdot - 1];
        !           564:        if (msgCount > 0 && value("noheader") == NOSTR) {
        !           565:                inithdr++;
        !           566:                headers(vec);
        !           567:                inithdr = 0;
        !           568:        }
        !           569: }
        !           570:
        !           571: /*
        !           572:  * Announce information about the file we are editing.
        !           573:  * Return a likely place to set dot.
        !           574:  */
        !           575: int
        !           576: newfileinfo()
        !           577: {
        !           578:        register struct message *mp;
        !           579:        register int u, n, mdot, d, s;
        !           580:        char fname[BUFSIZ], zname[BUFSIZ], *ename;
        !           581:
        !           582:        for (mp = &message[0]; mp < &message[msgCount]; mp++)
        !           583:                if (mp->m_flag & MNEW)
        !           584:                        break;
        !           585:        if (mp >= &message[msgCount])
        !           586:                for (mp = &message[0]; mp < &message[msgCount]; mp++)
        !           587:                        if ((mp->m_flag & MREAD) == 0)
        !           588:                                break;
        !           589:        if (mp < &message[msgCount])
        !           590:                mdot = mp - &message[0] + 1;
        !           591:        else
        !           592:                mdot = 1;
        !           593:        s = d = 0;
        !           594:        for (mp = &message[0], n = 0, u = 0; mp < &message[msgCount]; mp++) {
        !           595:                if (mp->m_flag & MNEW)
        !           596:                        n++;
        !           597:                if ((mp->m_flag & MREAD) == 0)
        !           598:                        u++;
        !           599:                if (mp->m_flag & MDELETED)
        !           600:                        d++;
        !           601:                if (mp->m_flag & MSAVED)
        !           602:                        s++;
        !           603:        }
        !           604:        ename = mailname;
        !           605:        if (getfold(fname) >= 0) {
        !           606:                strcat(fname, "/");
        !           607:                if (strncmp(fname, mailname, strlen(fname)) == 0) {
        !           608:                        sprintf(zname, "+%s", mailname + strlen(fname));
        !           609:                        ename = zname;
        !           610:                }
        !           611:        }
        !           612:        printf("\"%s\": ", ename);
        !           613:        if (msgCount == 1)
        !           614:                printf("1 message");
        !           615:        else
        !           616:                printf("%d messages", msgCount);
        !           617:        if (n > 0)
        !           618:                printf(" %d new", n);
        !           619:        if (u-n > 0)
        !           620:                printf(" %d unread", u);
        !           621:        if (d > 0)
        !           622:                printf(" %d deleted", d);
        !           623:        if (s > 0)
        !           624:                printf(" %d saved", s);
        !           625:        if (readonly)
        !           626:                printf(" [Read only]");
        !           627:        printf("\n");
        !           628:        return(mdot);
        !           629: }
        !           630:
        !           631: /*
        !           632:  * Print the current version number.
        !           633:  */
        !           634:
        !           635: /*ARGSUSED*/
        !           636: int
        !           637: pversion(e)
        !           638:        int e;
        !           639: {
        !           640:        extern char *version;
        !           641:
        !           642:        printf("Version %s\n", version);
        !           643:        return(0);
        !           644: }
        !           645:
        !           646: /*
        !           647:  * Load a file of user definitions.
        !           648:  */
        !           649: void
        !           650: load(name)
        !           651:        char *name;
        !           652: {
        !           653:        register FILE *in, *oldin;
        !           654:
        !           655:        if ((in = Fopen(name, "r")) == NULL)
        !           656:                return;
        !           657:        oldin = input;
        !           658:        input = in;
        !           659:        loading = 1;
        !           660:        sourcing = 1;
        !           661:        commands();
        !           662:        loading = 0;
        !           663:        sourcing = 0;
        !           664:        input = oldin;
        !           665:        Fclose(in);
        !           666: }