X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/4d931f7636fb0d5ef26e14312f3a5423acc74c8d..ca8907b2bb768fe1112070406459914c8335dd35:/usr/src/usr.bin/mail/lex.c diff --git a/usr/src/usr.bin/mail/lex.c b/usr/src/usr.bin/mail/lex.c index 4cd65f49fe..6c7f331322 100644 --- a/usr/src/usr.bin/mail/lex.c +++ b/usr/src/usr.bin/mail/lex.c @@ -8,7 +8,9 @@ * Lexical processing of commands. */ -static char *SccsId = "@(#)lex.c 1.5 %G%"; +static char *SccsId = "@(#)lex.c 2.11 %G%"; + +char *prompt = "& "; /* * Set up editing on the given file name. @@ -25,25 +27,18 @@ setfile(name, isedit) static int shudclob; static char efile[128]; extern char tempMesg[]; - int (*sigs[2])(); - if ((ibuf = fopen(name, "r")) == NULL) { - if (isedit) - perror(name); - else - printf("No mail for %s\n", myname); + if ((ibuf = fopen(name, "r")) == NULL) return(-1); - } /* * Looks like all will be well. We must now relinquish our - * hold on the current set of stuff. Must ignore signals + * hold on the current set of stuff. Must hold signals * while we are reading the new file, else we will ruin * the message[] data structure. */ - for (i = SIGINT; i <= SIGQUIT; i++) - sigs[i - SIGINT] = signal(i, SIG_IGN); + holdsigs(); if (shudclob) { if (edit) edstop(); @@ -69,6 +64,8 @@ setfile(name, isedit) edit = isedit; strncpy(efile, name, 128); editfile = efile; + if (name != mailname) + strcpy(mailname, name); mailsize = fsize(ibuf); if ((otf = fopen(tempMesg, "w")) == NULL) { perror(tempMesg); @@ -82,10 +79,7 @@ setfile(name, isedit) setptr(ibuf); setmsize(msgCount); fclose(ibuf); - for (i = SIGINT; i <= SIGQUIT; i++) - signal(i, sigs[i - SIGINT]); - printf("%s: ", name); - shudann = 1; + relsesigs(); sawcom = 0; return(0); } @@ -99,38 +93,23 @@ int *msgvec; commands() { - int prompt, firstsw, stop(); + int eofloop, shudprompt, stop(); register int n; char linebuf[LINESIZE]; - - if (rcvmode) - if (signal(SIGINT, SIG_IGN) == SIG_DFL) - signal(SIGINT, stop); - input = stdin; - prompt = 1; - if (!intty) - prompt = 0; - firstsw = 1; + int hangup(), contin(); + +# ifdef VMUNIX + sigset(SIGCONT, SIG_DFL); +# endif VMUNIX + if (rcvmode && !sourcing) { + if (sigset(SIGINT, SIG_IGN) != SIG_IGN) + sigset(SIGINT, stop); + if (sigset(SIGHUP, SIG_IGN) != SIG_IGN) + sigset(SIGHUP, hangup); + } + shudprompt = intty && !sourcing; for (;;) { setexit(); - if (firstsw > 0) { - firstsw = 0; - source1(mailrc); - if (!nosrc) - source1(MASTER); - } - - /* - * How's this for obscure: after we - * finish sourcing for the first time, - * go off and print the headers! - */ - - if (shudann && !sourcing) { - shudann = 0; - if (rcvmode) - announce(edit); - } /* * Print the prompt, if needed. Clear out @@ -139,9 +118,14 @@ commands() if (!rcvmode && !sourcing) return; + eofloop = 0; top: - if (prompt && !sourcing) - printf("_\r"); + if (shudprompt) { +# ifdef VMUNIX + sigset(SIGCONT, contin); +# endif VMUNIX + printf(prompt); + } flush(); sreset(); @@ -155,19 +139,20 @@ top: if (readline(input, &linebuf[n]) <= 0) { if (n != 0) break; + if (loading) + return; if (sourcing) { unstack(); goto more; } - if (value("ignoreeof") != NOSTR && prompt) { - printf("Use \"quit\" to quit.\n"); - goto top; + if (value("ignoreeof") != NOSTR && shudprompt) { + if (++eofloop < 25) { + printf("Use \"quit\" to quit.\n"); + goto top; + } } - if (!edit) { - signal(SIGINT, SIG_IGN); - return; - } - edstop(); + if (edit) + edstop(); return; } if ((n = strlen(linebuf)) == 0) @@ -177,7 +162,10 @@ top: break; linebuf[n++] = ' '; } - if (execute(linebuf)) +# ifdef VMUNIX + sigset(SIGCONT, SIG_DFL); +# endif VMUNIX + if (execute(linebuf, 0)) return; more: ; } @@ -187,9 +175,10 @@ more: ; * Execute a single command. If the command executed * is "quit," then return non-zero so that the caller * will know to return back to main, if he cares. + * Contxt is non-zero if called while composing mail. */ -execute(linebuf) +execute(linebuf, contxt) char linebuf[]; { char word[LINESIZE]; @@ -222,7 +211,7 @@ execute(linebuf) return(0); } cp2 = word; - while (*cp && !any(*cp, " \t0123456789$^./-+*'\"")) + while (*cp && !any(*cp, " \t0123456789$^.:/-+*'\"")) *cp2++ = *cp++; *cp2 = '\0'; @@ -238,12 +227,23 @@ execute(linebuf) return(0); com = lex(word); if (com == NONE) { - printf("What?\n"); + printf("Unknown command: \"%s\"\n", word); + if (loading) + return(1); if (sourcing) unstack(); return(0); } + /* + * See if we should execute the command -- if a conditional + * we always execute it, otherwise, check the state of cond. + */ + + if ((com->c_argtype & F) == 0) + if (cond == CRCV && !rcvmode || cond == CSEND && rcvmode) + return(0); + /* * Special case so that quit causes a return to * main, who will call the quit code directly. @@ -251,11 +251,13 @@ execute(linebuf) */ if (com->c_func == edstop && sourcing) { + if (loading) + return(1); unstack(); return(0); } if (!edit && com->c_func == edstop) { - signal(SIGINT, SIG_IGN); + sigset(SIGINT, SIG_IGN); return(1); } @@ -269,29 +271,44 @@ execute(linebuf) if (!rcvmode && (com->c_argtype & M) == 0) { printf("May not execute \"%s\" while sending\n", com->c_name); - unstack(); + if (loading) + return(1); + if (sourcing) + unstack(); return(0); } if (sourcing && com->c_argtype & I) { printf("May not execute \"%s\" while sourcing\n", com->c_name); + if (loading) + return(1); unstack(); return(0); } if (readonly && com->c_argtype & W) { printf("May not execute \"%s\" -- message file is read only\n", com->c_name); + if (loading) + return(1); if (sourcing) unstack(); return(0); } + if (contxt && com->c_argtype & R) { + printf("Cannot recursively invoke \"%s\"\n", com->c_name); + return(0); + } e = 1; - switch (com->c_argtype & ~(P|I|M|W)) { + switch (com->c_argtype & ~(F|P|I|M|T|W|R)) { case MSGLIST: /* * A message list defaulting to nearest forward * legal message. */ + if (msgvec == 0) { + printf("Illegal use of \"message list\"\n"); + return(-1); + } if ((c = getmsglist(cp, msgvec, com->c_msgflag)) < 0) break; if (c == 0) { @@ -311,6 +328,10 @@ execute(linebuf) * A message list with no defaults, but no error * if none exist. */ + if (msgvec == 0) { + printf("Illegal use of \"message list\"\n"); + return(-1); + } if (getmsglist(cp, msgvec, com->c_msgflag) < 0) break; e = (*com->c_func)(msgvec); @@ -362,6 +383,8 @@ execute(linebuf) * error. */ + if (e && loading) + return(1); if (e && sourcing) unstack(); if (com->c_func == edstop) @@ -372,11 +395,38 @@ execute(linebuf) muvec[1] = 0; type(muvec); } - if (!sourcing) + if (!sourcing && (com->c_argtype & T) == 0) sawcom = 1; return(0); } +/* + * When we wake up after ^Z, reprint the prompt. + */ +contin(s) +{ + + printf(prompt); + fflush(stdout); +} + +/* + * Branch here on hangup signal and simulate quit. + */ +hangup() +{ + + holdsigs(); + if (edit) { + if (setexit()) + exit(0); + edstop(); + } + else + quit(); + exit(0); +} + /* * Set the size of the message vector used to construct argument * lists to message list functions. @@ -436,13 +486,19 @@ isprefix(as1, as2) * Also, unstack all source files. */ -stop() +int inithdr; /* am printing startup headers */ + +stop(s) { register FILE *fp; +# ifndef VMUNIX + s = SIGINT; +# endif VMUNIX noreset = 0; - signal(SIGINT, SIG_IGN); - sawcom++; + if (!inithdr) + sawcom++; + inithdr = 0; while (sourcing) unstack(); getuserid((char *) -1); @@ -466,7 +522,11 @@ stop() } clrbuf(stdout); printf("Interrupt\n"); - signal(SIGINT, stop); +# ifdef VMUNIX + sigrelse(s); +# else + signal(s, stop); +# endif reset(0); } @@ -475,26 +535,83 @@ stop() * give the message count, and print a header listing. */ -char *greeting = "Mail version 2.0 %s. Type ? for help.\n"; +char *greeting = "Mail version %s. Type ? for help.\n"; announce(pr) { - int vec[2]; + int vec[2], mdot; extern char *version; - register struct message *mp; - vec[0] = 1; - vec[1] = 0; if (pr && value("quiet") == NOSTR) printf(greeting, version); + mdot = newfileinfo(); + vec[0] = mdot; + vec[1] = 0; + dot = &message[mdot - 1]; + if (msgCount > 0 && !noheader) { + inithdr++; + headers(vec); + inithdr = 0; + } +} + +/* + * Announce information about the file we are editing. + * Return a likely place to set dot. + */ +newfileinfo() +{ + register struct message *mp; + register int u, n, mdot, d, s; + char fname[BUFSIZ], zname[BUFSIZ], *ename; + + for (mp = &message[0]; mp < &message[msgCount]; mp++) + if (mp->m_flag & MNEW) + break; + if (mp >= &message[msgCount]) + for (mp = &message[0]; mp < &message[msgCount]; mp++) + if ((mp->m_flag & MREAD) == 0) + break; + if (mp < &message[msgCount]) + mdot = mp - &message[0] + 1; + else + mdot = 1; + s = d = 0; + for (mp = &message[0], n = 0, u = 0; mp < &message[msgCount]; mp++) { + if (mp->m_flag & MNEW) + n++; + if ((mp->m_flag & MREAD) == 0) + u++; + if (mp->m_flag & MDELETED) + d++; + if (mp->m_flag & MSAVED) + s++; + } + ename = mailname; + if (getfold(fname) >= 0) { + strcat(fname, "/"); + if (strncmp(fname, mailname, strlen(fname)) == 0) { + sprintf(zname, "+%s", mailname + strlen(fname)); + ename = zname; + } + } + printf("\"%s\": ", ename); if (msgCount == 1) printf("1 message"); else printf("%d messages", msgCount); + if (n > 0) + printf(" %d new", n); + if (u-n > 0) + printf(" %d unread", u); + if (d > 0) + printf(" %d deleted", d); + if (s > 0) + printf(" %d saved", s); if (readonly) printf(" [Read only]"); printf("\n"); - headers(vec); + return(mdot); } strace() {} @@ -505,6 +622,27 @@ strace() {} pversion(e) { - printf(greeting, version); + printf("Version %s\n", version); return(0); } + +/* + * Load a file of user definitions. + */ +load(name) + char *name; +{ + register FILE *in, *oldin; + + if ((in = fopen(name, "r")) == NULL) + return; + oldin = input; + input = in; + loading = 1; + sourcing = 1; + commands(); + loading = 0; + sourcing = 0; + input = oldin; + fclose(in); +}