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