home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
minnie.tuhs.org
/
unixen.tar
/
unixen
/
PDP-11
/
Distributions
/
ucb
/
spencer_2bsd.tar.gz
/
2bsd.tar
/
src
/
Mail
/
list.c
< prev
next >
Wrap
C/C++ Source or Header
|
1980-02-17
|
9KB
|
499 lines
/* Copyright (c) 1979 Regents of the University of California */
#
#include "rcv.h"
/*
* Mail -- a mail program
*
* Message list handling.
*/
/*
* 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;
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 TDASH:
if (beg == 0) {
printf("Unexpected leading dash\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,
'(', 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];
mesg++;
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;
mp = &message[mesg-1];
return(!strcmp(nameof(mp), 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);
}
}