version 1.10, 2001/01/16 05:36:08 |
version 1.11, 2001/11/21 15:26:39 |
|
|
|
|
#ifndef lint |
#ifndef lint |
#if 0 |
#if 0 |
static char sccsid[] = "@(#)list.c 8.4 (Berkeley) 5/1/95"; |
static const char sccsid[] = "@(#)list.c 8.4 (Berkeley) 5/1/95"; |
#else |
#else |
static char rcsid[] = "$OpenBSD$"; |
static const char rcsid[] = "$OpenBSD$"; |
#endif |
#endif |
#endif /* not lint */ |
#endif /* not lint */ |
|
|
|
|
#include <ctype.h> |
#include <ctype.h> |
#include "extern.h" |
#include "extern.h" |
|
|
int matchto __P((char *, int)); |
int matchto(char *, int); |
|
|
/* |
/* |
* Mail -- a mail program |
* Mail -- a mail program |
|
|
* Returns the count of messages picked up or -1 on error. |
* Returns the count of messages picked up or -1 on error. |
*/ |
*/ |
int |
int |
getmsglist(buf, vector, flags) |
getmsglist(char *buf, int *vector, int flags) |
char *buf; |
|
int *vector, flags; |
|
{ |
{ |
int *ip; |
int *ip; |
struct message *mp; |
struct message *mp; |
|
|
/* |
/* |
* Bit values for colon modifiers. |
* Bit values for colon modifiers. |
*/ |
*/ |
|
|
#define CMNEW 01 /* New messages */ |
#define CMNEW 01 /* New messages */ |
#define CMOLD 02 /* Old messages */ |
#define CMOLD 02 /* Old messages */ |
#define CMUNREAD 04 /* Unread messages */ |
#define CMUNREAD 04 /* Unread messages */ |
|
|
* The following table describes the letters which can follow |
* The following table describes the letters which can follow |
* the colon and gives the corresponding modifier bit. |
* the colon and gives the corresponding modifier bit. |
*/ |
*/ |
|
|
struct coltab { |
struct coltab { |
char co_char; /* What to find past : */ |
char co_char; /* What to find past : */ |
int co_bit; /* Associated modifier bit */ |
int co_bit; /* Associated modifier bit */ |
|
|
{ 0, 0, 0, 0 } |
{ 0, 0, 0, 0 } |
}; |
}; |
|
|
static int lastcolmod; |
static int lastcolmod; |
|
|
int |
int |
markall(buf, f) |
markall(char *buf, int f) |
char buf[]; |
|
int f; |
|
{ |
{ |
char **np; |
char **np; |
int i; |
int i; |
|
|
* so that we can unmark any whose sender was not selected |
* so that we can unmark any whose sender was not selected |
* if any user names were given. |
* if any user names were given. |
*/ |
*/ |
|
|
if ((np > namelist || colmod != 0) && mc == 0) |
if ((np > namelist || colmod != 0) && mc == 0) |
for (i = 1; i <= msgCount; i++) |
for (i = 1; i <= msgCount; i++) |
if ((message[i-1].m_flag & MDELETED) == f) |
if ((message[i-1].m_flag & MDELETED) == f) |
|
|
* If any names were given, go through and eliminate any |
* If any names were given, go through and eliminate any |
* messages whose senders were not requested. |
* messages whose senders were not requested. |
*/ |
*/ |
|
|
if (np > namelist) { |
if (np > namelist) { |
for (i = 1; i <= msgCount; i++) { |
for (i = 1; i <= msgCount; i++) { |
for (mc = 0, np = &namelist[0]; *np != NULL; np++) |
for (mc = 0, np = &namelist[0]; *np != NULL; np++) |
|
|
/* |
/* |
* Make sure we got some decent messages. |
* Make sure we got some decent messages. |
*/ |
*/ |
|
|
mc = 0; |
mc = 0; |
for (i = 1; i <= msgCount; i++) |
for (i = 1; i <= msgCount; i++) |
if (message[i-1].m_flag & MMARK) { |
if (message[i-1].m_flag & MMARK) { |
|
|
* If any colon modifiers were given, go through and |
* If any colon modifiers were given, go through and |
* unmark any messages which do not satisfy the modifiers. |
* unmark any messages which do not satisfy the modifiers. |
*/ |
*/ |
|
|
if (colmod != 0) { |
if (colmod != 0) { |
for (i = 1; i <= msgCount; i++) { |
for (i = 1; i <= msgCount; i++) { |
struct coltab *colp; |
struct coltab *colp; |
|
|
if ((mp->m_flag & colp->co_mask) |
if ((mp->m_flag & colp->co_mask) |
!= colp->co_equal) |
!= colp->co_equal) |
unmark(i); |
unmark(i); |
|
|
} |
} |
for (mp = &message[0]; mp < &message[msgCount]; mp++) |
for (mp = &message[0]; mp < &message[msgCount]; mp++) |
if (mp->m_flag & MMARK) |
if (mp->m_flag & MMARK) |
|
|
* value. |
* value. |
*/ |
*/ |
int |
int |
evalcol(col) |
evalcol(int col) |
int col; |
|
{ |
{ |
struct coltab *colp; |
struct coltab *colp; |
|
|
|
|
* has to be undeleted. |
* has to be undeleted. |
*/ |
*/ |
int |
int |
check(mesg, f) |
check(int mesg, int f) |
int mesg, f; |
|
{ |
{ |
struct message *mp; |
struct message *mp; |
|
|
|
|
* for a RAWLIST. |
* for a RAWLIST. |
*/ |
*/ |
int |
int |
getrawlist(line, argv, argc) |
getrawlist(char *line, char **argv, int argc) |
char line[]; |
|
char **argv; |
|
int argc; |
|
{ |
{ |
char c, *cp, *cp2, quotec; |
char c, *cp, *cp2, quotec; |
int argn; |
int argn; |
|
|
} |
} |
|
|
/* |
/* |
* scan out a single lexical item and return its token number, |
* Scan out a single lexical item and return its token number, |
* updating the string pointer passed **p. Also, store the value |
* updating the string pointer passed **p. Also, store the value |
* of the number or string scanned in lexnumber or lexstring as |
* of the number or string scanned in lexnumber or lexstring as |
* appropriate. In any event, store the scanned `thing' in lexstring. |
* appropriate. In any event, store the scanned `thing' in lexstring. |
*/ |
*/ |
|
|
struct lex { |
struct lex { |
char l_char; |
char l_char; |
char l_token; |
char l_token; |
|
|
}; |
}; |
|
|
int |
int |
scan(sp) |
scan(char **sp) |
char **sp; |
|
{ |
{ |
char *cp, *cp2; |
char *cp, *cp2; |
int c; |
int c; |
|
|
/* |
/* |
* strip away leading white space. |
* strip away leading white space. |
*/ |
*/ |
|
|
while (c == ' ' || c == '\t') |
while (c == ' ' || c == '\t') |
c = *cp++; |
c = *cp++; |
|
|
|
|
* If no characters remain, we are at end of line, |
* If no characters remain, we are at end of line, |
* so report that. |
* so report that. |
*/ |
*/ |
|
|
if (c == '\0') { |
if (c == '\0') { |
*sp = --cp; |
*sp = --cp; |
return(TEOL); |
return(TEOL); |
|
|
* the number and convert it on the fly. |
* the number and convert it on the fly. |
* Return TNUMBER when done. |
* Return TNUMBER when done. |
*/ |
*/ |
|
|
if (isdigit(c)) { |
if (isdigit(c)) { |
lexnumber = 0; |
lexnumber = 0; |
while (isdigit(c)) { |
while (isdigit(c)) { |
|
|
* Check for single character tokens; return such |
* Check for single character tokens; return such |
* if found. |
* if found. |
*/ |
*/ |
|
|
for (lp = &singles[0]; lp->l_char != 0; lp++) |
for (lp = &singles[0]; lp->l_char != 0; lp++) |
if (c == lp->l_char) { |
if (c == lp->l_char) { |
lexstring[0] = c; |
lexstring[0] = c; |
|
|
* If the lead character is a " or ', save it |
* If the lead character is a " or ', save it |
* and scan until you get another. |
* and scan until you get another. |
*/ |
*/ |
|
|
quotec = 0; |
quotec = 0; |
if (c == '\'' || c == '"') { |
if (c == '\'' || c == '"') { |
quotec = c; |
quotec = c; |
|
|
* Unscan the named token by pushing it onto the regret stack. |
* Unscan the named token by pushing it onto the regret stack. |
*/ |
*/ |
void |
void |
regret(token) |
regret(int token) |
int token; |
|
{ |
{ |
|
|
if (++regretp >= REGDEP) |
if (++regretp >= REGDEP) |
errx(1, "Too many regrets"); |
errx(1, "Too many regrets"); |
regretstack[regretp] = token; |
regretstack[regretp] = token; |
|
|
* Reset all the scanner global variables. |
* Reset all the scanner global variables. |
*/ |
*/ |
void |
void |
scaninit() |
scaninit(void) |
{ |
{ |
|
|
regretp = -1; |
regretp = -1; |
} |
} |
|
|
|
|
* its message number. |
* its message number. |
*/ |
*/ |
int |
int |
first(f, m) |
first(int f, int m) |
int f, m; |
|
{ |
{ |
struct message *mp; |
struct message *mp; |
|
|
|
|
* if so. |
* if so. |
*/ |
*/ |
int |
int |
matchsender(str, mesg) |
matchsender(char *str, int mesg) |
char *str; |
|
int mesg; |
|
{ |
{ |
char *cp, *cp2, *backup; |
char *cp, *cp2, *backup; |
|
|
|
|
* See if the passed name received the passed message number. Return true |
* See if the passed name received the passed message number. Return true |
* if so. |
* if so. |
*/ |
*/ |
|
|
static char *to_fields[] = { "to", "cc", "bcc", NULL }; |
static char *to_fields[] = { "to", "cc", "bcc", NULL }; |
|
|
int |
int |
matchto(str, mesg) |
matchto(char *str, int mesg) |
char *str; |
|
{ |
{ |
struct message *mp; |
struct message *mp; |
char *cp, *cp2, *backup, **to; |
char *cp, *cp2, *backup, **to; |
|
|
* have the form "/search-string." If it is of the form "/," we use the |
* have the form "/search-string." If it is of the form "/," we use the |
* previous search string. |
* previous search string. |
*/ |
*/ |
|
|
char lastscan[STRINGLEN]; |
char lastscan[STRINGLEN]; |
|
|
int |
int |
matchsubj(str, mesg) |
matchsubj(char *str, int mesg) |
char *str; |
|
int mesg; |
|
{ |
{ |
struct message *mp; |
struct message *mp; |
char *cp, *cp2, *backup; |
char *cp, *cp2, *backup; |
|
|
str++; |
str++; |
if (*str == '\0') |
if (*str == '\0') |
str = lastscan; |
str = lastscan; |
else { |
else |
strncpy(lastscan, str, sizeof(lastscan) - 1); |
strlcpy(lastscan, str, sizeof(lastscan)); |
lastscan[sizeof(lastscan) - 1] = '\0'; |
|
} |
|
mp = &message[mesg-1]; |
mp = &message[mesg-1]; |
|
|
/* |
/* |
* Now look, ignoring case, for the word in the string. |
* Now look, ignoring case, for the word in the string. |
*/ |
*/ |
|
|
if (value("searchheaders") && (cp = strchr(str, ':'))) { |
if (value("searchheaders") && (cp = strchr(str, ':'))) { |
/* Check for special case "/To:" */ |
/* Check for special case "/To:" */ |
if (raise(str[0]) == 'T' && raise(str[1]) == 'O' && |
if (raise(str[0]) == 'T' && raise(str[1]) == 'O' && |
|
|
* Mark the named message by setting its mark bit. |
* Mark the named message by setting its mark bit. |
*/ |
*/ |
void |
void |
mark(mesg) |
mark(int mesg) |
int mesg; |
|
{ |
{ |
int i; |
int i; |
|
|
|
|
* Unmark the named message. |
* Unmark the named message. |
*/ |
*/ |
void |
void |
unmark(mesg) |
unmark(int mesg) |
int mesg; |
|
{ |
{ |
int i; |
int i; |
|
|
|
|
* Return the message number corresponding to the passed meta character. |
* Return the message number corresponding to the passed meta character. |
*/ |
*/ |
int |
int |
metamess(meta, f) |
metamess(int meta, int f) |
int meta, f; |
|
{ |
{ |
int c, m; |
int c, m; |
struct message *mp; |
struct message *mp; |