From b3149556edd89b9f9e8133c3320d89fb60688647 Mon Sep 17 00:00:00 2001 From: "Kurt A. Schoens" Date: Wed, 8 Oct 1980 17:50:32 -0800 Subject: [PATCH] date and time created 80/10/08 09:50:32 by kas SCCS-vsn: usr.bin/mail/list.c 1.1 --- usr/src/usr.bin/mail/list.c | 522 ++++++++++++++++++++++++++++++++++++ 1 file changed, 522 insertions(+) create mode 100644 usr/src/usr.bin/mail/list.c diff --git a/usr/src/usr.bin/mail/list.c b/usr/src/usr.bin/mail/list.c new file mode 100644 index 0000000000..fe43a40eb8 --- /dev/null +++ b/usr/src/usr.bin/mail/list.c @@ -0,0 +1,522 @@ +# + +#include "rcv.h" +#include + +/* + * Mail -- a mail program + * + * Message list handling. + */ + +static char *SccsId = "@(#)list.c 1.1 %G%"; + +/* + * Convert the user string of message numbers and + * store the numbers into vector. + * + * Returns the count of messages picked up or -1 on error. + */ + +getmsglist(buf, vector, flags) + char *buf; + int *vector; +{ + register int *ip; + register struct message *mp; + + if (markall(buf, flags) < 0) + return(-1); + ip = vector; + for (mp = &message[0]; mp < &message[msgCount]; mp++) + if (mp->m_flag & MMARK) + *ip++ = mp - &message[0] + 1; + *ip = NULL; + return(ip - vector); +} + +/* + * Mark all messages that the user wanted from the command + * line in the message structure. Return 0 on success, -1 + * on error. + */ + +markall(buf, f) + char buf[]; +{ + register char **np; + register int i; + char *namelist[NMLSIZE], *bufp; + int tok, beg, mc, star, other, valdot; + + valdot = dot - &message[0] + 1; + for (i = 1; i <= msgCount; i++) + unmark(i); + bufp = buf; + mc = 0; + np = &namelist[0]; + scaninit(); + tok = scan(&bufp); + star = 0; + other = 0; + beg = 0; + while (tok != TEOL) { + switch (tok) { + case TNUMBER: +number: + if (star) { + printf("No numbers mixed with *\n"); + return(-1); + } + mc++; + other++; + if (beg != 0) { + if (check(lexnumber, f)) + return(-1); + for (i = beg; i <= lexnumber; i++) + mark(i); + beg = 0; + break; + } + beg = lexnumber; + if (check(beg, f)) + return(-1); + tok = scan(&bufp); + regret(tok); + if (tok != TDASH) { + mark(beg); + beg = 0; + } + break; + + case TPLUS: + if (beg != 0) { + printf("Non-numeric second argument\n"); + return(-1); + } + if (valdot < msgCount) + mark(valdot+1); + else { + printf("Referencing beyond EOF\n"); + return(-1); + } + break; + + case TDASH: + if (beg == 0) { + if (valdot > 1) + mark(valdot-1); + else { + printf("Referencing before 1\n"); + return(-1); + } + } + break; + + case TSTRING: + if (beg != 0) { + printf("Non-numeric second argument\n"); + return(-1); + } + other++; + *np++ = savestr(lexstring); + break; + + case TDOLLAR: + case TUP: + case TDOT: + lexnumber = metamess(lexstring[0], f); + if (lexnumber == -1) + return(-1); + goto number; + + case TSTAR: + if (other) { + printf("Can't mix \"*\" with anything\n"); + return(-1); + } + star++; + break; + } + tok = scan(&bufp); + } + *np = NOSTR; + mc = 0; + if (star) { + for (i = 0; i < msgCount; i++) + if ((message[i].m_flag & MDELETED) == f) { + mark(i+1); + mc++; + } + if (mc == 0) { + printf("No applicable messages.\n"); + return(-1); + } + return(0); + } + + /* + * If no numbers were given, mark all of the messages, + * so that we can unmark any whose sender was not selected + * if any user names were given. + */ + + if (np > namelist && mc == 0) + for (i = 1; i <= msgCount; i++) + if ((message[i-1].m_flag & (MSAVED|MDELETED)) == f) + mark(i); + + /* + * If any names were given, go through and eliminate any + * messages whose senders were not requested. + */ + + if (np > namelist) { + for (i = 1; i <= msgCount; i++) { + for (mc = 0, np = &namelist[0]; *np != NOSTR; np++) + if (sender(*np, i)) { + mc++; + break; + } + if (mc == 0) + unmark(i); + } + + /* + * Make sure we got some decent messages. + */ + + mc = 0; + for (i = 1; i <= msgCount; i++) + if (message[i-1].m_flag & MMARK) { + mc++; + break; + } + if (mc == 0) { + printf("No applicable messages from {%s", + namelist[0]); + for (np = &namelist[1]; *np != NOSTR; np++) + printf(", %s", *np); + printf("}\n"); + return(-1); + } + } + return(0); +} + +/* + * Check the passed message number for legality and proper flags. + */ + +check(mesg, f) +{ + register struct message *mp; + + if (mesg < 1 || mesg > msgCount) { + printf("%d: Invalid message number\n", mesg); + return(-1); + } + mp = &message[mesg-1]; + if ((mp->m_flag & MDELETED) != f) { + printf("%d: Inappropriate message\n", mesg); + return(-1); + } + return(0); +} + +/* + * Scan out the list of string arguments, shell style + * for a RAWLIST. + */ + +getrawlist(line, argv) + char line[]; + char **argv; +{ + register char **ap, *cp, *cp2; + char linebuf[BUFSIZ], quotec; + + ap = argv; + cp = line; + while (*cp != '\0') { + while (any(*cp, " \t")) + cp++; + cp2 = linebuf; + quotec = 0; + if (any(*cp, "'\"")) + quotec = *cp++; + if (quotec == 0) + while (*cp != '\0' && !any(*cp, " \t")) + *cp2++ = *cp++; + else { + while (*cp != '\0' && *cp != quotec) + *cp2++ = *cp++; + if (*cp != '\0') + cp++; + } + *cp2 = '\0'; + if (cp2 == linebuf) + break; + *ap++ = savestr(linebuf); + } + *ap = NOSTR; + return(ap-argv); +} + +/* + * scan out a single lexical item and return its token number, + * updating the string pointer passed **p. Also, store the value + * of the number or string scanned in lexnumber or lexstring as + * appropriate. In any event, store the scanned `thing' in lexstring. + */ + +struct lex { + char l_char; + char l_token; +} singles[] = { + '$', TDOLLAR, + '.', TDOT, + '^', TUP, + '*', TSTAR, + '-', TDASH, + '+', TPLUS, + '(', TOPEN, + ')', TCLOSE, + 0, 0 +}; + +scan(sp) + char **sp; +{ + register char *cp, *cp2; + register int c; + register struct lex *lp; + int quotec; + + if (regretp >= 0) { + copy(stringstack[regretp], lexstring); + lexnumber = numberstack[regretp]; + return(regretstack[regretp--]); + } + cp = *sp; + cp2 = lexstring; + c = *cp++; + + /* + * strip away leading white space. + */ + + while (any(c, " \t")) + c = *cp++; + + /* + * If no characters remain, we are at end of line, + * so report that. + */ + + if (c == '\0') { + *sp = --cp; + return(TEOL); + } + + /* + * If the leading character is a digit, scan + * the number and convert it on the fly. + * Return TNUMBER when done. + */ + + if (isdigit(c)) { + lexnumber = 0; + while (isdigit(c)) { + lexnumber = lexnumber*10 + c - '0'; + *cp2++ = c; + c = *cp++; + } + *cp2 = '\0'; + *sp = --cp; + return(TNUMBER); + } + + /* + * Check for single character tokens; return such + * if found. + */ + + for (lp = &singles[0]; lp->l_char != 0; lp++) + if (c == lp->l_char) { + lexstring[0] = c; + lexstring[1] = '\0'; + *sp = cp; + return(lp->l_token); + } + + /* + * We've got a string! Copy all the characters + * of the string into lexstring, until we see + * a null, space, or tab. + * If the lead character is a " or ', save it + * and scan until you get another. + */ + + quotec = 0; + if (any(c, "'\"")) { + quotec = c; + c = *cp++; + } + while (c != '\0') { + if (c == quotec) + break; + if (quotec == 0 && any(c, " \t")) + break; + if (cp2 - lexstring < STRINGLEN-1) + *cp2++ = c; + c = *cp++; + } + if (quotec && c == 0) + fprintf(stderr, "Missing %c\n", quotec); + *sp = --cp; + *cp2 = '\0'; + return(TSTRING); +} + +/* + * Unscan the named token by pushing it onto the regret stack. + */ + +regret(token) +{ + if (++regretp >= REGDEP) + panic("Too many regrets"); + regretstack[regretp] = token; + lexstring[STRINGLEN-1] = '\0'; + stringstack[regretp] = savestr(lexstring); + numberstack[regretp] = lexnumber; +} + +/* + * Reset all the scanner global variables. + */ + +scaninit() +{ + regretp = -1; +} + +/* + * Find the first message whose flags & m == f and return + * its message number. + */ + +first(f, m) +{ + register int mesg; + register struct message *mp; + + mesg = dot - &message[0] + 1; + f &= MDELETED; + m &= MDELETED; + for (mp = dot; mp < &message[msgCount]; mp++) { + if ((mp->m_flag & m) == f) + return(mesg); + mesg++; + } + mesg = dot - &message[0]; + for (mp = dot-1; mp >= &message[0]; mp--) { + if ((mp->m_flag & m) == f) + return(mesg); + mesg--; + } + return(NULL); +} + +/* + * See if the passed name sent the passed message number. Return true + * if so. + */ + +sender(str, mesg) + char *str; +{ + register struct message *mp; + register char *cp; + + mp = &message[mesg-1]; + cp = nameof(mp); + return(icequal(cp, str)); +} + +/* + * Mark the named message by setting its mark bit. + */ + +mark(mesg) +{ + register int i; + + i = mesg; + if (i < 1 || i > msgCount) + panic("Bad message number to mark"); + message[i-1].m_flag |= MMARK; +} + +/* + * Unmark the named message. + */ + +unmark(mesg) +{ + register int i; + + i = mesg; + if (i < 1 || i > msgCount) + panic("Bad message number to unmark"); + message[i-1].m_flag &= ~MMARK; +} + +/* + * Return the message number corresponding to the passed meta character. + */ + +metamess(meta, f) +{ + register int c, m; + register struct message *mp; + + c = meta; + switch (c) { + case '^': + /* + * First 'good' message left. + */ + for (mp = &message[0]; mp < &message[msgCount]; mp++) + if ((mp->m_flag & MDELETED) == f) + return(mp - &message[0] + 1); + printf("No applicable messages\n"); + return(-1); + + case '$': + /* + * Last 'good message left. + */ + for (mp = &message[msgCount-1]; mp >= &message[0]; mp--) + if ((mp->m_flag & MDELETED) == f) + return(mp - &message[0] + 1); + printf("No applicable messages\n"); + return(-1); + + case '.': + /* + * Current message. + */ + m = dot - &message[0] + 1; + if ((dot->m_flag & MDELETED) != f) { + printf("%d: Inappropriate message\n", m); + return(-1); + } + return(m); + + default: + printf("Unknown metachar (%c)\n", c); + return(-1); + } +} -- 2.20.1