X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/312bdff639ded138ee72d7d5bf0f9b2bc8140366..f5576df6fd6c54ac0836b6cc9634f63a156f325a:/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 index 1e31b554cb..15ebf34002 100644 --- a/usr/src/usr.bin/mail/list.c +++ b/usr/src/usr.bin/mail/list.c @@ -1,4 +1,39 @@ -# +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)list.c 5.14 (Berkeley) 6/1/90"; +#endif /* not lint */ #include "rcv.h" #include @@ -9,8 +44,6 @@ * Message list handling. */ -static char *SccsId = "@(#)list.c 1.3 %G%"; - /* * Convert the user string of message numbers and * store the numbers into vector. @@ -25,13 +58,17 @@ getmsglist(buf, vector, flags) register int *ip; register struct message *mp; + if (msgCount == 0) { + *vector = 0; + return 0; + } 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; + *ip = 0; return(ip - vector); } @@ -41,15 +78,48 @@ getmsglist(buf, vector, flags) * on error. */ +/* + * Bit values for colon modifiers. + */ + +#define CMNEW 01 /* New messages */ +#define CMOLD 02 /* Old messages */ +#define CMUNREAD 04 /* Unread messages */ +#define CMDELETED 010 /* Deleted messages */ +#define CMREAD 020 /* Read messages */ + +/* + * The following table describes the letters which can follow + * the colon and gives the corresponding modifier bit. + */ + +struct coltab { + char co_char; /* What to find past : */ + int co_bit; /* Associated modifier bit */ + int co_mask; /* m_status bits to mask */ + int co_equal; /* ... must equal this */ +} coltab[] = { + 'n', CMNEW, MNEW, MNEW, + 'o', CMOLD, MNEW, 0, + 'u', CMUNREAD, MREAD, 0, + 'd', CMDELETED, MDELETED, MDELETED, + 'r', CMREAD, MREAD, MREAD, + 0, 0, 0, 0 +}; + +static int lastcolmod; + markall(buf, f) char buf[]; { register char **np; register int i; + register struct message *mp; char *namelist[NMLSIZE], *bufp; - int tok, beg, mc, star, other, valdot; + int tok, beg, mc, star, other, valdot, colmod, colresult; valdot = dot - &message[0] + 1; + colmod = 0; for (i = 1; i <= msgCount; i++) unmark(i); bufp = buf; @@ -74,7 +144,8 @@ number: if (check(lexnumber, f)) return(-1); for (i = beg; i <= lexnumber; i++) - mark(i); + if (f == MDELETED || (message[i - 1].m_flag & MDELETED) == 0) + mark(i); beg = 0; break; } @@ -94,22 +165,28 @@ number: printf("Non-numeric second argument\n"); return(-1); } - if (valdot < msgCount) - mark(valdot+1); - else { - printf("Referencing beyond EOF\n"); - return(-1); - } + i = valdot; + do { + i++; + if (i > msgCount) { + printf("Referencing beyond EOF\n"); + return(-1); + } + } while ((message[i - 1].m_flag & MDELETED) != f); + mark(i); break; case TDASH: if (beg == 0) { - if (valdot > 1) - mark(valdot-1); - else { - printf("Referencing before 1\n"); - return(-1); - } + i = valdot; + do { + i--; + if (i <= 0) { + printf("Referencing before 1\n"); + return(-1); + } + } while ((message[i - 1].m_flag & MDELETED) != f); + mark(i); } break; @@ -119,7 +196,17 @@ number: return(-1); } other++; - *np++ = savestr(lexstring); + if (lexstring[0] == ':') { + colresult = evalcol(lexstring[1]); + if (colresult == 0) { + printf("Unknown colon modifier \"%s\"\n", + lexstring); + return(-1); + } + colmod |= colresult; + } + else + *np++ = savestr(lexstring); break; case TDOLLAR: @@ -137,9 +224,13 @@ number: } star++; break; + + case TERROR: + return -1; } tok = scan(&bufp); } + lastcolmod = colmod; *np = NOSTR; mc = 0; if (star) { @@ -161,9 +252,9 @@ number: * if any user names were given. */ - if (np > namelist && mc == 0) + if ((np > namelist || colmod != 0) && mc == 0) for (i = 1; i <= msgCount; i++) - if ((message[i-1].m_flag & (MSAVED|MDELETED)) == f) + if ((message[i-1].m_flag & MDELETED) == f) mark(i); /* @@ -181,7 +272,7 @@ number: } } else { - if (sender(*np, i)) { + if (matchsender(*np, i)) { mc++; break; } @@ -209,13 +300,62 @@ number: return(-1); } } + + /* + * If any colon modifiers were given, go through and + * unmark any messages which do not satisfy the modifiers. + */ + + if (colmod != 0) { + for (i = 1; i <= msgCount; i++) { + register struct coltab *colp; + + mp = &message[i - 1]; + for (colp = &coltab[0]; colp->co_char; colp++) + if (colp->co_bit & colmod) + if ((mp->m_flag & colp->co_mask) + != colp->co_equal) + unmark(i); + + } + for (mp = &message[0]; mp < &message[msgCount]; mp++) + if (mp->m_flag & MMARK) + break; + if (mp >= &message[msgCount]) { + register struct coltab *colp; + + printf("No messages satisfy"); + for (colp = &coltab[0]; colp->co_char; colp++) + if (colp->co_bit & colmod) + printf(" :%c", colp->co_char); + printf("\n"); + return(-1); + } + } return(0); } /* - * Check the passed message number for legality and proper flags. + * Turn the character after a colon modifier into a bit + * value. */ +evalcol(col) +{ + register struct coltab *colp; + + if (col == 0) + return(lastcolmod); + for (colp = &coltab[0]; colp->co_char; colp++) + if (colp->co_char == col) + return(colp->co_bit); + return(0); +} +/* + * Check the passed message number for legality and proper flags. + * If f is MDELETED, then either kind will do. Otherwise, the message + * has to be undeleted. + */ check(mesg, f) { register struct message *mp; @@ -225,7 +365,7 @@ check(mesg, f) return(-1); } mp = &message[mesg-1]; - if ((mp->m_flag & MDELETED) != f) { + if (f != MDELETED && (mp->m_flag & MDELETED) != 0) { printf("%d: Inappropriate message\n", mesg); return(-1); } @@ -237,38 +377,91 @@ check(mesg, f) * for a RAWLIST. */ -getrawlist(line, argv) +getrawlist(line, argv, argc) char line[]; char **argv; + int argc; { - register char **ap, *cp, *cp2; - char linebuf[BUFSIZ], quotec; + register char c, *cp, *cp2, quotec; + int argn; + char linebuf[BUFSIZ]; - ap = argv; + argn = 0; cp = line; - while (*cp != '\0') { - while (any(*cp, " \t")) - cp++; + for (;;) { + for (; *cp == ' ' || *cp == '\t'; cp++) + ; + if (*cp == '\0') + break; + if (argn >= argc - 1) { + printf( + "Too many elements in the list; excess discarded.\n"); + break; + } 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++; + quotec = '\0'; + while ((c = *cp) != '\0') { + cp++; + if (quotec != '\0') { + if (c == quotec) + quotec = '\0'; + else if (c == '\\') + switch (c = *cp++) { + case '\0': + *cp2++ = *--cp; + break; + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + c -= '0'; + if (*cp >= '0' && *cp <= '7') + c = c * 8 + *cp++ - '0'; + if (*cp >= '0' && *cp <= '7') + c = c * 8 + *cp++ - '0'; + *cp2++ = c; + break; + case 'b': + *cp2++ = '\b'; + break; + case 'f': + *cp2++ = '\f'; + break; + case 'n': + *cp2++ = '\n'; + break; + case 'r': + *cp2++ = '\r'; + break; + case 't': + *cp2++ = '\t'; + break; + case 'v': + *cp2++ = '\v'; + break; + } + else if (c == '^') { + c = *cp++; + if (c == '?') + *cp2++ = '\177'; + /* null doesn't show up anyway */ + else if (c >= 'A' && c <= '_' || + c >= 'a' && c <= 'z') + *cp2++ &= 037; + else + *cp2++ = *--cp; + } else + *cp2++ = c; + } else if (c == '"' || c == '\'') + quotec = c; + else if (c == ' ' || c == '\t') + break; + else + *cp2++ = c; } *cp2 = '\0'; - if (cp2 == linebuf) - break; - *ap++ = savestr(linebuf); + argv[argn++] = savestr(linebuf); } - *ap = NOSTR; - return(ap-argv); + argv[argn] = NOSTR; + return argn; } /* @@ -302,7 +495,7 @@ scan(sp) int quotec; if (regretp >= 0) { - copy(stringstack[regretp], lexstring); + strcpy(lexstring, string_stack[regretp]); lexnumber = numberstack[regretp]; return(regretstack[regretp--]); } @@ -314,7 +507,7 @@ scan(sp) * strip away leading white space. */ - while (any(c, " \t")) + while (c == ' ' || c == '\t') c = *cp++; /* @@ -367,21 +560,25 @@ scan(sp) */ quotec = 0; - if (any(c, "'\"")) { + if (c == '\'' || c == '"') { quotec = c; c = *cp++; } while (c != '\0') { - if (c == quotec) + if (c == quotec) { + cp++; break; - if (quotec == 0 && any(c, " \t")) + } + if (quotec == 0 && (c == ' ' || c == '\t')) break; if (cp2 - lexstring < STRINGLEN-1) *cp2++ = c; c = *cp++; } - if (quotec && c == 0) + if (quotec && c == 0) { fprintf(stderr, "Missing %c\n", quotec); + return TERROR; + } *sp = --cp; *cp2 = '\0'; return(TSTRING); @@ -397,7 +594,7 @@ regret(token) panic("Too many regrets"); regretstack[regretp] = token; lexstring[STRINGLEN-1] = '\0'; - stringstack[regretp] = savestr(lexstring); + string_stack[regretp] = savestr(lexstring); numberstack[regretp] = lexnumber; } @@ -417,24 +614,19 @@ scaninit() first(f, m) { - register int mesg; register struct message *mp; - mesg = dot - &message[0] + 1; + if (msgCount == 0) + return 0; f &= MDELETED; m &= MDELETED; - for (mp = dot; mp < &message[msgCount]; mp++) { + 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--) { + return mp - message + 1; + for (mp = dot-1; mp >= &message[0]; mp--) if ((mp->m_flag & m) == f) - return(mesg); - mesg--; - } - return(NULL); + return mp - message + 1; + return 0; } /* @@ -442,15 +634,24 @@ first(f, m) * if so. */ -sender(str, mesg) +matchsender(str, mesg) char *str; { - register struct message *mp; - register char *cp; + register char *cp, *cp2, *backup; - mp = &message[mesg-1]; - cp = nameof(mp); - return(icequal(cp, str)); + if (!*str) /* null string matches nothing instead of everything */ + return 0; + backup = cp2 = nameof(&message[mesg - 1], 0); + cp = str; + while (*cp2) { + if (*cp == 0) + return(1); + if (raise(*cp++) != raise(*cp2++)) { + cp2 = ++backup; + cp = str; + } + } + return(*cp == 0); } /*