122456Sdist /*
262083Sbostic * Copyright (c) 1980, 1993
362083Sbostic * The Regents of the University of California. All rights reserved.
433499Sbostic *
542741Sbostic * %sccs.include.redist.c%
622456Sdist */
722456Sdist
834905Sbostic #ifndef lint
9*68818Sdab static char sccsid[] = "@(#)lex.c 8.2 (Berkeley) 04/20/95";
1034905Sbostic #endif /* not lint */
111237Skas
121237Skas #include "rcv.h"
1324750Sserge #include <errno.h>
1454505Sbostic #include <fcntl.h>
1554505Sbostic #include "extern.h"
161237Skas
171237Skas /*
181237Skas * Mail -- a mail program
191237Skas *
201237Skas * Lexical processing of commands.
211237Skas */
221237Skas
234566Skurt char *prompt = "& ";
244566Skurt
251237Skas /*
261311Skas * Set up editing on the given file name.
2736734Sedward * If the first character of name is %, we are considered to be
2836734Sedward * editing the file, otherwise we are reading our mail which has
2936734Sedward * signficance for mbox and so forth.
301311Skas */
3154505Sbostic int
setfile(name)3236734Sedward setfile(name)
331311Skas char *name;
341311Skas {
351311Skas FILE *ibuf;
361311Skas int i;
3716837Sralph struct stat stb;
3836734Sedward char isedit = *name != '%';
3936734Sedward char *who = name[1] ? name + 1 : myname;
401311Skas static int shudclob;
411311Skas extern char tempMesg[];
4224750Sserge extern int errno;
431311Skas
4436734Sedward if ((name = expand(name)) == NOSTR)
4536734Sedward return -1;
4636734Sedward
4743865Sedward if ((ibuf = Fopen(name, "r")) == NULL) {
4836734Sedward if (!isedit && errno == ENOENT)
4936734Sedward goto nomail;
5036554Sedward perror(name);
511311Skas return(-1);
5236554Sedward }
5324750Sserge
5424750Sserge if (fstat(fileno(ibuf), &stb) < 0) {
5536554Sedward perror("fstat");
5643865Sedward Fclose(ibuf);
5724750Sserge return (-1);
5816837Sralph }
591311Skas
6024750Sserge switch (stb.st_mode & S_IFMT) {
6124750Sserge case S_IFDIR:
6243865Sedward Fclose(ibuf);
6324750Sserge errno = EISDIR;
6436554Sedward perror(name);
6524750Sserge return (-1);
6624750Sserge
6724750Sserge case S_IFREG:
6824750Sserge break;
6924750Sserge
7024750Sserge default:
7143865Sedward Fclose(ibuf);
7224750Sserge errno = EINVAL;
7336554Sedward perror(name);
7424750Sserge return (-1);
7524750Sserge }
7624750Sserge
771311Skas /*
781311Skas * Looks like all will be well. We must now relinquish our
793566Skurt * hold on the current set of stuff. Must hold signals
801311Skas * while we are reading the new file, else we will ruin
811311Skas * the message[] data structure.
821311Skas */
831311Skas
843566Skurt holdsigs();
8536554Sedward if (shudclob)
8636554Sedward quit();
871311Skas
881311Skas /*
891311Skas * Copy the messages into /tmp
901311Skas * and set pointers.
911311Skas */
921311Skas
931311Skas readonly = 0;
941311Skas if ((i = open(name, 1)) < 0)
951311Skas readonly++;
961311Skas else
971311Skas close(i);
981311Skas if (shudclob) {
991311Skas fclose(itf);
1001311Skas fclose(otf);
1011311Skas }
1021311Skas shudclob = 1;
1031311Skas edit = isedit;
10436734Sedward strcpy(prevfile, mailname);
1051523Skas if (name != mailname)
1061523Skas strcpy(mailname, name);
1071311Skas mailsize = fsize(ibuf);
1081311Skas if ((otf = fopen(tempMesg, "w")) == NULL) {
1091311Skas perror(tempMesg);
1101311Skas exit(1);
1111311Skas }
11256291Sedward (void) fcntl(fileno(otf), F_SETFD, 1);
1131311Skas if ((itf = fopen(tempMesg, "r")) == NULL) {
1141311Skas perror(tempMesg);
1151311Skas exit(1);
1161311Skas }
11756291Sedward (void) fcntl(fileno(itf), F_SETFD, 1);
11846242Sbostic rm(tempMesg);
119*68818Sdab setptr(ibuf, 0);
1201311Skas setmsize(msgCount);
121*68818Sdab /*
122*68818Sdab * New mail mail have arrived while we were reading
123*68818Sdab * up the mail file, so reset mailsize to be where
124*68818Sdab * we really are in the file...
125*68818Sdab */
126*68818Sdab mailsize = ftell(ibuf);
12743865Sedward Fclose(ibuf);
1283566Skurt relsesigs();
1291375Skas sawcom = 0;
13036734Sedward if (!edit && msgCount == 0) {
13136734Sedward nomail:
13236734Sedward fprintf(stderr, "No mail for %s\n", who);
13336734Sedward return -1;
13436734Sedward }
1351311Skas return(0);
1361311Skas }
1371311Skas
138*68818Sdab /*
139*68818Sdab * Incorporate any new mail that has arrived since we first
140*68818Sdab * started reading mail.
141*68818Sdab */
142*68818Sdab int
incfile()143*68818Sdab incfile()
144*68818Sdab {
145*68818Sdab int newsize;
146*68818Sdab int omsgCount = msgCount;
147*68818Sdab FILE *ibuf;
148*68818Sdab
149*68818Sdab ibuf = Fopen(mailname, "r");
150*68818Sdab if (ibuf == NULL)
151*68818Sdab return -1;
152*68818Sdab holdsigs();
153*68818Sdab newsize = fsize(ibuf);
154*68818Sdab if (newsize == 0)
155*68818Sdab return -1; /* mail box is now empty??? */
156*68818Sdab if (newsize < mailsize)
157*68818Sdab return -1; /* mail box has shrunk??? */
158*68818Sdab if (newsize == mailsize)
159*68818Sdab return 0; /* no new mail */
160*68818Sdab setptr(ibuf, mailsize);
161*68818Sdab setmsize(msgCount);
162*68818Sdab mailsize = ftell(ibuf);
163*68818Sdab Fclose(ibuf);
164*68818Sdab relsesigs();
165*68818Sdab return(msgCount - omsgCount);
166*68818Sdab }
167*68818Sdab
16836554Sedward int *msgvec;
16936554Sedward int reset_on_stop; /* do a reset() if stopped */
17036554Sedward
1711311Skas /*
1721237Skas * Interpret user commands one by one. If standard input is not a tty,
1731237Skas * print no prompt.
1741237Skas */
17554505Sbostic void
commands()1761237Skas commands()
1771237Skas {
17836554Sedward int eofloop = 0;
1791237Skas register int n;
1801237Skas char linebuf[LINESIZE];
18147708Sbostic void intr(), stop(), hangup();
1821237Skas
18336554Sedward if (!sourcing) {
18431142Sedward if (signal(SIGINT, SIG_IGN) != SIG_IGN)
18536554Sedward signal(SIGINT, intr);
18631142Sedward if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
18731142Sedward signal(SIGHUP, hangup);
18836554Sedward signal(SIGTSTP, stop);
18936554Sedward signal(SIGTTOU, stop);
19036554Sedward signal(SIGTTIN, stop);
1913413Skurt }
19236554Sedward setexit();
1931237Skas for (;;) {
1941237Skas /*
1951237Skas * Print the prompt, if needed. Clear out
1961237Skas * string space, and flush the output.
1971237Skas */
19834750Sedward if (!sourcing && value("interactive") != NOSTR) {
199*68818Sdab if ((value("autoinc") != NOSTR) && (incfile() > 0))
200*68818Sdab printf("New mail has arrived.\n");
20136554Sedward reset_on_stop = 1;
20213132Ssam printf(prompt);
20331142Sedward }
20431142Sedward fflush(stdout);
20534968Sedward sreset();
2061237Skas /*
2071237Skas * Read a line of commands from the current input
2081237Skas * and handle end of file specially.
2091237Skas */
2101237Skas n = 0;
2111237Skas for (;;) {
21236554Sedward if (readline(input, &linebuf[n], LINESIZE - n) < 0) {
21336554Sedward if (n == 0)
21436554Sedward n = -1;
21536554Sedward break;
2161237Skas }
2171237Skas if ((n = strlen(linebuf)) == 0)
2181237Skas break;
2191237Skas n--;
2201237Skas if (linebuf[n] != '\\')
2211237Skas break;
2221237Skas linebuf[n++] = ' ';
2231237Skas }
22436554Sedward reset_on_stop = 0;
22536554Sedward if (n < 0) {
22636554Sedward /* eof */
22736554Sedward if (loading)
22836554Sedward break;
22936554Sedward if (sourcing) {
23036554Sedward unstack();
23136554Sedward continue;
23236554Sedward }
23336554Sedward if (value("interactive") != NOSTR &&
23436554Sedward value("ignoreeof") != NOSTR &&
23536554Sedward ++eofloop < 25) {
23636554Sedward printf("Use \"quit\" to quit.\n");
23736554Sedward continue;
23836554Sedward }
23936554Sedward break;
24036554Sedward }
24136554Sedward eofloop = 0;
2422118Skas if (execute(linebuf, 0))
24336554Sedward break;
2441237Skas }
2451237Skas }
2461237Skas
2471237Skas /*
24836554Sedward * Execute a single command.
24936554Sedward * Command functions return 0 for success, 1 for error, and -1
25036554Sedward * for abort. A 1 or -1 aborts a load or source. A -1 aborts
25136554Sedward * the interactive command loop.
2522118Skas * Contxt is non-zero if called while composing mail.
2531237Skas */
25454505Sbostic int
execute(linebuf,contxt)2552118Skas execute(linebuf, contxt)
2561237Skas char linebuf[];
25754505Sbostic int contxt;
2581237Skas {
2591237Skas char word[LINESIZE];
2601237Skas char *arglist[MAXARGC];
2611237Skas struct cmd *com;
2621237Skas register char *cp, *cp2;
2631237Skas register int c;
2641311Skas int muvec[2];
26536554Sedward int e = 1;
2661237Skas
2671237Skas /*
2681237Skas * Strip the white space away from the beginning
2691237Skas * of the command, then scan out a word, which
2701237Skas * consists of anything except digits and white space.
2711237Skas *
2721237Skas * Handle ! escapes differently to get the correct
2731237Skas * lexical conventions.
2741237Skas */
2751237Skas
27631142Sedward for (cp = linebuf; isspace(*cp); cp++)
27731142Sedward ;
2781237Skas if (*cp == '!') {
2791237Skas if (sourcing) {
2801237Skas printf("Can't \"!\" while sourcing\n");
28136554Sedward goto out;
2821237Skas }
2831237Skas shell(cp+1);
2841237Skas return(0);
2851237Skas }
2861237Skas cp2 = word;
28734987Sedward while (*cp && index(" \t0123456789$^.:/-+*'\"", *cp) == NOSTR)
2881237Skas *cp2++ = *cp++;
2891237Skas *cp2 = '\0';
2901237Skas
2911237Skas /*
2921237Skas * Look up the command; if not found, bitch.
2931237Skas * Normally, a blank command would map to the
2941237Skas * first command in the table; while sourcing,
2951237Skas * however, we ignore blank lines to eliminate
2961237Skas * confusion.
2971237Skas */
2981237Skas
29931142Sedward if (sourcing && *word == '\0')
3001237Skas return(0);
3011237Skas com = lex(word);
3021237Skas if (com == NONE) {
3036226Skurt printf("Unknown command: \"%s\"\n", word);
30436554Sedward goto out;
3051237Skas }
3061237Skas
3071237Skas /*
3081523Skas * See if we should execute the command -- if a conditional
3091523Skas * we always execute it, otherwise, check the state of cond.
3101523Skas */
3111523Skas
3122061Skas if ((com->c_argtype & F) == 0)
3131523Skas if (cond == CRCV && !rcvmode || cond == CSEND && rcvmode)
3141523Skas return(0);
3151523Skas
3161523Skas /*
3171237Skas * Process the arguments to the command, depending
3181237Skas * on the type he expects. Default to an error.
3191237Skas * If we are sourcing an interactive command, it's
3201237Skas * an error.
3211237Skas */
3221237Skas
3231237Skas if (!rcvmode && (com->c_argtype & M) == 0) {
3241237Skas printf("May not execute \"%s\" while sending\n",
3251237Skas com->c_name);
32636554Sedward goto out;
3271237Skas }
3281237Skas if (sourcing && com->c_argtype & I) {
3291237Skas printf("May not execute \"%s\" while sourcing\n",
3301237Skas com->c_name);
33136554Sedward goto out;
3321237Skas }
3331311Skas if (readonly && com->c_argtype & W) {
3341311Skas printf("May not execute \"%s\" -- message file is read only\n",
3351311Skas com->c_name);
33636554Sedward goto out;
3371311Skas }
3382118Skas if (contxt && com->c_argtype & R) {
3392118Skas printf("Cannot recursively invoke \"%s\"\n", com->c_name);
34036554Sedward goto out;
3412118Skas }
3422118Skas switch (com->c_argtype & ~(F|P|I|M|T|W|R)) {
3431237Skas case MSGLIST:
3441237Skas /*
3451237Skas * A message list defaulting to nearest forward
3461237Skas * legal message.
3471237Skas */
3486226Skurt if (msgvec == 0) {
3496226Skurt printf("Illegal use of \"message list\"\n");
35036554Sedward break;
3516226Skurt }
3521237Skas if ((c = getmsglist(cp, msgvec, com->c_msgflag)) < 0)
3531237Skas break;
3541237Skas if (c == 0) {
3551237Skas *msgvec = first(com->c_msgflag,
3561237Skas com->c_msgmask);
3571237Skas msgvec[1] = NULL;
3581237Skas }
3591237Skas if (*msgvec == NULL) {
3601237Skas printf("No applicable messages\n");
3611237Skas break;
3621237Skas }
3631237Skas e = (*com->c_func)(msgvec);
3641237Skas break;
3651237Skas
3661237Skas case NDMLIST:
3671237Skas /*
3681237Skas * A message list with no defaults, but no error
3691237Skas * if none exist.
3701237Skas */
3716226Skurt if (msgvec == 0) {
3726226Skurt printf("Illegal use of \"message list\"\n");
37336554Sedward break;
3746226Skurt }
3751237Skas if (getmsglist(cp, msgvec, com->c_msgflag) < 0)
3761237Skas break;
3771237Skas e = (*com->c_func)(msgvec);
3781237Skas break;
3791237Skas
3801237Skas case STRLIST:
3811237Skas /*
3821237Skas * Just the straight string, with
3831237Skas * leading blanks removed.
3841237Skas */
38531142Sedward while (isspace(*cp))
3861237Skas cp++;
3871237Skas e = (*com->c_func)(cp);
3881237Skas break;
3891237Skas
3901237Skas case RAWLIST:
3911237Skas /*
3921237Skas * A vector of strings, in shell style.
3931237Skas */
39425376Sserge if ((c = getrawlist(cp, arglist,
39525376Sserge sizeof arglist / sizeof *arglist)) < 0)
3961237Skas break;
3971237Skas if (c < com->c_minargs) {
3981237Skas printf("%s requires at least %d arg(s)\n",
3991237Skas com->c_name, com->c_minargs);
4001237Skas break;
4011237Skas }
4021237Skas if (c > com->c_maxargs) {
4031237Skas printf("%s takes no more than %d arg(s)\n",
4041237Skas com->c_name, com->c_maxargs);
4051237Skas break;
4061237Skas }
4071237Skas e = (*com->c_func)(arglist);
4081237Skas break;
4091237Skas
4101237Skas case NOLIST:
4111237Skas /*
4121237Skas * Just the constant zero, for exiting,
4131237Skas * eg.
4141237Skas */
4151237Skas e = (*com->c_func)(0);
4161237Skas break;
4171237Skas
4181237Skas default:
4191237Skas panic("Unknown argtype");
4201237Skas }
4211237Skas
42236554Sedward out:
4231237Skas /*
4241237Skas * Exit the current source file on
4251237Skas * error.
4261237Skas */
42736554Sedward if (e) {
42836554Sedward if (e < 0)
42936554Sedward return 1;
43036554Sedward if (loading)
43136554Sedward return 1;
43236554Sedward if (sourcing)
43336554Sedward unstack();
43436554Sedward return 0;
43536554Sedward }
4361237Skas if (value("autoprint") != NOSTR && com->c_argtype & P)
4371311Skas if ((dot->m_flag & MDELETED) == 0) {
4381311Skas muvec[0] = dot - &message[0] + 1;
4391311Skas muvec[1] = 0;
4401311Skas type(muvec);
4411311Skas }
4421523Skas if (!sourcing && (com->c_argtype & T) == 0)
4431237Skas sawcom = 1;
4441237Skas return(0);
4451237Skas }
4461237Skas
4471237Skas /*
4481311Skas * Set the size of the message vector used to construct argument
4491311Skas * lists to message list functions.
4501311Skas */
45154505Sbostic void
setmsize(sz)4521311Skas setmsize(sz)
45354505Sbostic int sz;
4541311Skas {
4551311Skas
45631142Sedward if (msgvec != 0)
45757659Sbostic free((char *) msgvec);
4581311Skas msgvec = (int *) calloc((unsigned) (sz + 1), sizeof *msgvec);
4591311Skas }
4601311Skas
4611311Skas /*
4621237Skas * Find the correct command in the command table corresponding
4631237Skas * to the passed command "word"
4641237Skas */
4651237Skas
4661237Skas struct cmd *
lex(word)4671237Skas lex(word)
4681237Skas char word[];
4691237Skas {
4701237Skas register struct cmd *cp;
4711237Skas extern struct cmd cmdtab[];
4721237Skas
4731237Skas for (cp = &cmdtab[0]; cp->c_name != NOSTR; cp++)
4741237Skas if (isprefix(word, cp->c_name))
4751237Skas return(cp);
4761237Skas return(NONE);
4771237Skas }
4781237Skas
4791237Skas /*
4801237Skas * Determine if as1 is a valid prefix of as2.
4811237Skas * Return true if yep.
4821237Skas */
48354505Sbostic int
isprefix(as1,as2)4841237Skas isprefix(as1, as2)
4851237Skas char *as1, *as2;
4861237Skas {
4871237Skas register char *s1, *s2;
4881237Skas
4891237Skas s1 = as1;
4901237Skas s2 = as2;
4911237Skas while (*s1++ == *s2)
4921237Skas if (*s2++ == '\0')
4931237Skas return(1);
4941237Skas return(*--s1 == '\0');
4951237Skas }
4961237Skas
4971237Skas /*
49831142Sedward * The following gets called on receipt of an interrupt. This is
4991237Skas * to abort printout of a command, mainly.
5001237Skas * Dispatching here when command() is inactive crashes rcv.
5011237Skas * Close all open files except 0, 1, 2, and the temporary.
5021237Skas * Also, unstack all source files.
5031237Skas */
5041237Skas
5053240Skas int inithdr; /* am printing startup headers */
5063240Skas
50731142Sedward /*ARGSUSED*/
50847708Sbostic void
intr(s)50936554Sedward intr(s)
51054505Sbostic int s;
5111237Skas {
5121237Skas
5131237Skas noreset = 0;
5143240Skas if (!inithdr)
5153240Skas sawcom++;
5163240Skas inithdr = 0;
5171237Skas while (sourcing)
5181237Skas unstack();
51918659Sserge
52043865Sedward close_all_files();
52118659Sserge
5221237Skas if (image >= 0) {
5231237Skas close(image);
5241237Skas image = -1;
5251237Skas }
52616857Sralph fprintf(stderr, "Interrupt\n");
5271237Skas reset(0);
5281237Skas }
5291237Skas
5301237Skas /*
53136554Sedward * When we wake up after ^Z, reprint the prompt.
53236554Sedward */
53347708Sbostic void
stop(s)53436554Sedward stop(s)
53554505Sbostic int s;
53636554Sedward {
53739612Sedward sig_t old_action = signal(s, SIG_DFL);
53836554Sedward
53936554Sedward sigsetmask(sigblock(0) & ~sigmask(s));
54036554Sedward kill(0, s);
54136554Sedward sigblock(sigmask(s));
54236554Sedward signal(s, old_action);
54336554Sedward if (reset_on_stop) {
54436554Sedward reset_on_stop = 0;
54536554Sedward reset(0);
54636554Sedward }
54736554Sedward }
54836554Sedward
54936554Sedward /*
55036554Sedward * Branch here on hangup signal and simulate "exit".
55136554Sedward */
55236554Sedward /*ARGSUSED*/
55347708Sbostic void
hangup(s)55436554Sedward hangup(s)
55554505Sbostic int s;
55636554Sedward {
55736554Sedward
55836554Sedward /* nothing to do? */
55936554Sedward exit(1);
56036554Sedward }
56136554Sedward
56236554Sedward /*
5631237Skas * Announce the presence of the current Mail version,
5641237Skas * give the message count, and print a header listing.
5651237Skas */
56654505Sbostic void
announce()56734754Sedward announce()
5681237Skas {
5691485Skas int vec[2], mdot;
5702130Skas
571*68818Sdab mdot = newfileinfo(0);
5722130Skas vec[0] = mdot;
5732130Skas vec[1] = 0;
5742130Skas dot = &message[mdot - 1];
57534704Sedward if (msgCount > 0 && value("noheader") == NOSTR) {
5763240Skas inithdr++;
5772130Skas headers(vec);
5783240Skas inithdr = 0;
5793240Skas }
5802130Skas }
5812130Skas
5822130Skas /*
5832130Skas * Announce information about the file we are editing.
5842130Skas * Return a likely place to set dot.
5852130Skas */
58654505Sbostic int
newfileinfo(omsgCount)587*68818Sdab newfileinfo(omsgCount)
588*68818Sdab int omsgCount;
5892130Skas {
5901237Skas register struct message *mp;
5916302Skurt register int u, n, mdot, d, s;
5926226Skurt char fname[BUFSIZ], zname[BUFSIZ], *ename;
5931237Skas
594*68818Sdab for (mp = &message[omsgCount]; mp < &message[msgCount]; mp++)
5951475Skas if (mp->m_flag & MNEW)
5961475Skas break;
5971485Skas if (mp >= &message[msgCount])
598*68818Sdab for (mp = &message[omsgCount]; mp < &message[msgCount]; mp++)
5991485Skas if ((mp->m_flag & MREAD) == 0)
6001485Skas break;
6011475Skas if (mp < &message[msgCount])
6021485Skas mdot = mp - &message[0] + 1;
6031475Skas else
604*68818Sdab mdot = omsgCount + 1;
6056302Skurt s = d = 0;
6061523Skas for (mp = &message[0], n = 0, u = 0; mp < &message[msgCount]; mp++) {
6071523Skas if (mp->m_flag & MNEW)
6081523Skas n++;
6091523Skas if ((mp->m_flag & MREAD) == 0)
6101523Skas u++;
6116302Skurt if (mp->m_flag & MDELETED)
6126302Skurt d++;
6136302Skurt if (mp->m_flag & MSAVED)
6146302Skurt s++;
6151523Skas }
6166226Skurt ename = mailname;
6176226Skurt if (getfold(fname) >= 0) {
6186226Skurt strcat(fname, "/");
6196226Skurt if (strncmp(fname, mailname, strlen(fname)) == 0) {
6206226Skurt sprintf(zname, "+%s", mailname + strlen(fname));
6216226Skurt ename = zname;
6226226Skurt }
6236226Skurt }
6246226Skurt printf("\"%s\": ", ename);
6252130Skas if (msgCount == 1)
6262130Skas printf("1 message");
6272130Skas else
6282130Skas printf("%d messages", msgCount);
6291523Skas if (n > 0)
6301523Skas printf(" %d new", n);
6311523Skas if (u-n > 0)
6321523Skas printf(" %d unread", u);
6336302Skurt if (d > 0)
6346302Skurt printf(" %d deleted", d);
6356302Skurt if (s > 0)
6366302Skurt printf(" %d saved", s);
6372130Skas if (readonly)
6382130Skas printf(" [Read only]");
6391311Skas printf("\n");
6402130Skas return(mdot);
6411237Skas }
6421237Skas
6431237Skas /*
6441237Skas * Print the current version number.
6451237Skas */
6461237Skas
64731142Sedward /*ARGSUSED*/
64854505Sbostic int
pversion(e)6491237Skas pversion(e)
65054505Sbostic int e;
6511237Skas {
65233219Sbostic extern char *version;
65331142Sedward
6544352Skurt printf("Version %s\n", version);
6551237Skas return(0);
6561237Skas }
6576226Skurt
6586226Skurt /*
6596226Skurt * Load a file of user definitions.
6606226Skurt */
66154505Sbostic void
load(name)6626226Skurt load(name)
6636226Skurt char *name;
6646226Skurt {
6656226Skurt register FILE *in, *oldin;
6666226Skurt
66743865Sedward if ((in = Fopen(name, "r")) == NULL)
6686226Skurt return;
6696226Skurt oldin = input;
6706226Skurt input = in;
6716226Skurt loading = 1;
6726226Skurt sourcing = 1;
6736226Skurt commands();
6746226Skurt loading = 0;
6756226Skurt sourcing = 0;
6766226Skurt input = oldin;
67743865Sedward Fclose(in);
6786226Skurt }
679