aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>1998-03-13 20:20:19 +0000
committerEric S. Raymond <esr@thyrsus.com>1998-03-13 20:20:19 +0000
commitd3833f31da28808274c6d08804646116be7dabb8 (patch)
tree985ae69fd971dffb43a300f92f3b4867857267ab
parent8517cf573fdb368fa69d776bc113cd95c6646edb (diff)
downloadfetchmail-d3833f31da28808274c6d08804646116be7dabb8.tar.gz
fetchmail-d3833f31da28808274c6d08804646116be7dabb8.tar.bz2
fetchmail-d3833f31da28808274c6d08804646116be7dabb8.zip
Re-engineer the UIDL stuff to avoid having the status flag collide
with message numbers. svn path=/trunk/; revision=1699
-rw-r--r--NEWS1
-rw-r--r--driver.c51
-rw-r--r--fetchmail.c8
-rw-r--r--fetchmail.h44
-rw-r--r--options.c4
-rw-r--r--pop3.c20
-rw-r--r--rcfile_y.y16
-rw-r--r--uid.c37
8 files changed, 88 insertions, 93 deletions
diff --git a/NEWS b/NEWS
index 6a19dbc4..e78cf496 100644
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,7 @@ fetchmail-4.4.0 ():
* Fix bug that prevented graceful exit from POP3 validation on wrong password.
* Dominique Unruh's patch that copes gracefully with bodiless messages.
* Fix timer-leak problem pointed ouit by Dave Bodenstab.
+* Improvements in UID handling; should be a cleaner fix for Dick van den Burg.
There are 268 people on fetchmail-friends and 160 on fetchmail-announce.
diff --git a/driver.c b/driver.c
index b14d9a61..018b17cc 100644
--- a/driver.c
+++ b/driver.c
@@ -248,7 +248,7 @@ static int is_host_alias(const char *name, struct query *ctl)
}
/* add this name to relevant server's `also known as' list */
- save_str(&lead_server->akalist, -1, name);
+ save_str(&lead_server->akalist, name, 0);
return(TRUE);
#endif /* HAVE_RES_SEARCH */
}
@@ -281,7 +281,7 @@ struct idlist **xmit_names; /* list of recipient names parsed out */
}
if (outlevel == O_VERBOSE)
error(0, 0, "mapped %s to local %s", name, lname+off);
- save_str(xmit_names, XMIT_ACCEPT, lname+off);
+ save_str(xmit_names, lname+off, XMIT_ACCEPT);
accept_count++;
}
}
@@ -323,7 +323,7 @@ struct idlist **xmit_names; /* list of recipient names parsed out */
if (outlevel == O_VERBOSE)
error(0, 0, "passed through %s matching %s",
cp, idp->id);
- save_str(xmit_names, XMIT_ACCEPT, cp);
+ save_str(xmit_names, cp, XMIT_ACCEPT);
accept_count++;
break;
}
@@ -339,7 +339,7 @@ struct idlist **xmit_names; /* list of recipient names parsed out */
*/
if (!is_host_alias(atsign+1, ctl))
{
- save_str(xmit_names, XMIT_REJECT, cp);
+ save_str(xmit_names, cp, XMIT_REJECT);
reject_count++;
continue;
}
@@ -879,16 +879,19 @@ int num; /* index of message */
else if (!strncasecmp("Content-Transfer-Encoding:", line, 26))
ctt_offs = (line - headers);
- else if (!strncasecmp("Message-Id:", buf, 11 ))
+ else if (!strncasecmp("Message-Id:", buf, 11))
{
- if( ctl->server.uidl )
+ if (ctl->server.uidl)
{
char id[IDLEN+1];
- /* prevent stack overflows */
- buf[IDLEN+12] = 0;
- sscanf( buf+12, "%s", id);
- if( !str_find( &ctl->newsaved, num ) )
- save_str(&ctl->newsaved, num, id );
+
+ buf[IDLEN+12] = 0; /* prevent stack overflow */
+ sscanf(buf+12, "%s", id);
+ if (!str_find( &ctl->newsaved, num))
+ {
+ struct idlist *new = save_str(&ctl->newsaved,id,UID_SEEN);
+ new->val.status.num = num;
+ }
}
}
@@ -1050,7 +1053,7 @@ int num; /* index of message */
if (!accept_count)
{
no_local_matches = TRUE;
- save_str(&xmit_names, XMIT_ACCEPT, user);
+ save_str(&xmit_names, user, XMIT_ACCEPT);
if (outlevel == O_VERBOSE)
error(0, 0,
"no local matches, forwarding to %s",
@@ -1058,7 +1061,7 @@ int num; /* index of message */
}
}
else /* it's a single-drop box, use first localname */
- save_str(&xmit_names, XMIT_ACCEPT, ctl->localnames->id);
+ save_str(&xmit_names, ctl->localnames->id, XMIT_ACCEPT);
/*
@@ -1078,7 +1081,7 @@ int num; /* index of message */
char *names, *before, *after;
for (idp = xmit_names; idp; idp = idp->next)
- if (idp->val.num == XMIT_ACCEPT)
+ if (idp->val.status.mark == XMIT_ACCEPT)
good_addresses++;
destaddr = "localhost";
@@ -1105,13 +1108,13 @@ int num; /* index of message */
* long lists of users and (re)implement %s.
*/
for (idp = xmit_names; idp; idp = idp->next)
- if (idp->val.num == XMIT_ACCEPT)
+ if (idp->val.status.mark == XMIT_ACCEPT)
length += (strlen(idp->id) + 1);
names = (char *)xmalloc(++length);
names[0] = '\0';
for (idp = xmit_names; idp; idp = idp->next)
- if (idp->val.num == XMIT_ACCEPT)
+ if (idp->val.status.mark == XMIT_ACCEPT)
{
strcat(names, idp->id);
strcat(names, " ");
@@ -1318,7 +1321,7 @@ int num; /* index of message */
destaddr = ctl->smtpaddress ? ctl->smtpaddress : ( ctl->smtphost ? ctl->smtphost : "localhost");
for (idp = xmit_names; idp; idp = idp->next)
- if (idp->val.num == XMIT_ACCEPT)
+ if (idp->val.status.mark == XMIT_ACCEPT)
{
if (strchr(idp->id, '@'))
strcpy(addr, idp->id);
@@ -1334,7 +1337,7 @@ int num; /* index of message */
else
{
bad_addresses++;
- idp->val.num = XMIT_ANTISPAM;
+ idp->val.status.mark = XMIT_ANTISPAM;
error(0, 0,
"SMTP listener doesn't like recipient address `%s'",
addr);
@@ -1406,7 +1409,7 @@ int num; /* index of message */
else if (good_addresses == 1)
{
for (idp = xmit_names; idp; idp = idp->next)
- if (idp->val.num == XMIT_ACCEPT)
+ if (idp->val.status.mark == XMIT_ACCEPT)
break; /* only report first address */
if (strchr(idp->id, '@'))
sprintf(buf+1, "for <%s>", idp->id);
@@ -1475,7 +1478,7 @@ int num; /* index of message */
else
{
for (idp = xmit_names; idp; idp = idp->next)
- if (idp->val.num == XMIT_REJECT)
+ if (idp->val.status.mark == XMIT_REJECT)
break;
sprintf(errhd+strlen(errhd), "recipient address %s didn't match any local name", idp->id);
}
@@ -1495,13 +1498,13 @@ int num; /* index of message */
strcat(errhd, "SMTP listener rejected local recipient addresses: ");
errlen = strlen(errhd);
for (idp = xmit_names; idp; idp = idp->next)
- if (idp->val.num == XMIT_ANTISPAM)
+ if (idp->val.status.mark == XMIT_ANTISPAM)
errlen += strlen(idp->id) + 2;
errmsg = alloca(errlen+3);
(void) strcpy(errmsg, errhd);
for (idp = xmit_names; idp; idp = idp->next)
- if (idp->val.num == XMIT_ANTISPAM)
+ if (idp->val.status.mark == XMIT_ANTISPAM)
{
strcat(errmsg, idp->id);
if (idp->next)
@@ -2248,8 +2251,8 @@ const struct method *proto; /* protocol method table */
struct idlist *sdp;
for (sdp = ctl->newsaved; sdp; sdp = sdp->next)
- if (sdp->val.num == num)
- MARK_SEEN(sdp->val.num);
+ if (sdp->val.status.num == num)
+ sdp->val.status.mark = UID_SEEN;
}
/* maybe we delete this message now? */
diff --git a/fetchmail.c b/fetchmail.c
index da259b05..52ffa5f3 100644
--- a/fetchmail.c
+++ b/fetchmail.c
@@ -719,7 +719,7 @@ static int load_params(int argc, char **argv, int optind)
/* make sure we have a nonempty host list to forward to */
if (!ctl->smtphunt)
- save_str(&ctl->smtphunt, FALSE, fetchmailhost);
+ save_str(&ctl->smtphunt, fetchmailhost, FALSE);
/* keep lusers from shooting themselves in the foot :-) */
if (poll_interval && ctl->limit)
@@ -792,7 +792,7 @@ static int load_params(int argc, char **argv, int optind)
/* if no folders were specified, set up the null one as default */
if (!ctl->mailboxes)
- save_str(&ctl->mailboxes, -1, (char *)NULL);
+ save_str(&ctl->mailboxes, (char *)NULL, 0);
/* maybe user overrode timeout on command line? */
if (ctl->server.timeout == -1)
@@ -1102,10 +1102,10 @@ void dump_params (struct query *ctl)
printf(" Messages will be SMTP-forwarded to:");
for (idp = ctl->smtphunt; idp; idp = idp->next)
- if (ctl->server.protocol != P_ETRN || idp->val.num)
+ if (ctl->server.protocol != P_ETRN || idp->val.status.mark)
{
printf(" %s", idp->id);
- if (!idp->val.num)
+ if (!idp->val.status.mark)
printf(" (default)");
}
printf("\n");
diff --git a/fetchmail.h b/fetchmail.h
index 259add67..9480ddb0 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -66,6 +66,16 @@
#define SIZETICKER 1024 /* print 1 dot per this many bytes */
+/*
+ * We #ifdef this and use flag rather than bool
+ * to avoid a type clash with curses.h
+ */
+#ifndef TRUE
+#define FALSE 0
+#define TRUE 1
+#endif /* TRUE */
+typedef char flag;
+
/* we need to use zero as a flag-uninitialized value */
#define FLAG_TRUE 2
#define FLAG_FALSE 1
@@ -75,22 +85,21 @@ struct idlist
char *id;
union
{
- int num;
+ struct
+ {
+ short num;
+ flag mark; /* UID-index information */
+#define UID_UNSEEN 0 /* hasn't been seen */
+#define UID_SEEN 1 /* seen, but not deleted */
+#define UID_DELETED 2 /* this message has been deleted */
+#define UID_EXPUNGED 3 /* this message has been expunged */
+ }
+ status;
char *id2;
} val;
struct idlist *next;
};
-/*
- * We #ifdef this and use flag rather than bool
- * to avoid a type clash with curses.h
- */
-#ifndef TRUE
-#define FALSE 0
-#define TRUE 1
-#endif /* TRUE */
-typedef char flag;
-
struct hostdata /* shared among all user connections to given server */
{
/* rc file data */
@@ -175,17 +184,6 @@ struct query
};
/*
- * UID-index information. If the sign bit is on, this means the
- * message UID has been seen or expunged and should be written
- * out to .fetchids at end of run.
- */
-#define UID_KEPT 0 /* remembered from a previous run */
-#define UID_DELETED INT_MIN /* this message has been deleted */
-#define UID_EXPUNGED INT_MAX /* this message has been expunged */
-#define SAVE_UID(n) ((n) <= 0) /* must this UID be saved? */
-#define MARK_SEEN(n) n *= -1 /* mark a UID seen */
-
-/*
* Numeric option handling. Numeric option value of zero actually means
* it's unspecified. Value less than zero is zero.
*/
@@ -299,7 +297,7 @@ char *nxtaddr(const char *);
/* uid.c: UID support */
void initialize_saved_lists(struct query *, const char *);
-struct idlist *save_str(struct idlist **, int, const char *);
+struct idlist *save_str(struct idlist **, const char *, flag);
void free_str_list(struct idlist **);
void save_str_pair(struct idlist **, const char *, const char *);
void free_str_pair_list(struct idlist **);
diff --git a/options.c b/options.c
index f104c1a2..ffa50e47 100644
--- a/options.c
+++ b/options.c
@@ -312,7 +312,7 @@ struct query *ctl; /* option record to be initialized */
strcpy(buf, optarg);
cp = strtok(buf, ",");
do {
- save_str(&ctl->mailboxes, -1, cp);
+ save_str(&ctl->mailboxes, cp, 0);
} while
((cp = strtok((char *)NULL, ",")));
break;
@@ -321,7 +321,7 @@ struct query *ctl; /* option record to be initialized */
strcpy(buf, optarg);
cp = strtok(buf, ",");
do {
- save_str(&ctl->smtphunt, TRUE, cp);
+ save_str(&ctl->smtphunt, cp, TRUE);
} while
((cp = strtok((char *)NULL, ",")));
ocount++;
diff --git a/pop3.c b/pop3.c
index 3004e747..1634755b 100644
--- a/pop3.c
+++ b/pop3.c
@@ -331,11 +331,14 @@ pop3_slowuidl( int sock, struct query *ctl, int *countp, int *newp)
}
}
}
- /* The first try_id messages are known -> copy them to
- the newsaved list */
+ /* the first try_id messages are known -> copy them to the newsaved list */
for( num = first_nr; num < list_len; num++ )
- save_str(&ctl->newsaved, num-first_nr + 1,
- str_from_nr_list( &ctl->oldsaved, num ));
+ {
+ struct idlist *new = save_str(&ctl->newsaved,
+ str_from_nr_list(&ctl->oldsaved, num),
+ UID_UNSEEN);
+ new->val.status.num = num - first_nr + 1;
+ }
if( nolinear ) {
free_str_list(&ctl->oldsaved);
@@ -424,10 +427,15 @@ static int pop3_getrange(int sock,
break;
else if (sscanf(buf, "%d %s", &num, id) == 2)
{
- save_str(&ctl->newsaved, num, id);
+ struct idlist *new;
+
+ new = save_str(&ctl->newsaved, id, UID_UNSEEN);
+ new->val.status.num = num;
/* note: ID comparison is caseblind */
- if (!str_in_list(&ctl->oldsaved, id))
+ if (str_in_list(&ctl->oldsaved, id))
+ new->val.status.mark = UID_SEEN;
+ else
(*newp)++;
}
}
diff --git a/rcfile_y.y b/rcfile_y.y
index 68d61c7e..9c536bdf 100644
--- a/rcfile_y.y
+++ b/rcfile_y.y
@@ -115,12 +115,12 @@ serverspecs : /* EMPTY */
| serverspecs serv_option
;
-alias_list : STRING {save_str(&current.server.akalist,-1,$1);}
- | alias_list STRING {save_str(&current.server.akalist,-1,$2);}
+alias_list : STRING {save_str(&current.server.akalist,$1,0);}
+ | alias_list STRING {save_str(&current.server.akalist,$2,0);}
;
-domain_list : STRING {save_str(&current.server.localdomains,-1,$1);}
- | domain_list STRING {save_str(&current.server.localdomains,-1,$2);}
+domain_list : STRING {save_str(&current.server.localdomains,$1,0);}
+ | domain_list STRING {save_str(&current.server.localdomains,$2,0);}
;
serv_option : AKA alias_list
@@ -252,12 +252,12 @@ mapping : STRING
{save_str_pair(&current.localnames, $1, $3);}
;
-folder_list : STRING {save_str(&current.mailboxes,-1,$1);}
- | folder_list STRING {save_str(&current.mailboxes,-1,$2);}
+folder_list : STRING {save_str(&current.mailboxes,$1,0);}
+ | folder_list STRING {save_str(&current.mailboxes,$2,0);}
;
-smtp_list : STRING {save_str(&current.smtphunt, TRUE,$1);}
- | smtp_list STRING {save_str(&current.smtphunt, TRUE,$2);}
+smtp_list : STRING {save_str(&current.smtphunt, $1,TRUE);}
+ | smtp_list STRING {save_str(&current.smtphunt, $2,TRUE);}
;
user_option : TO localnames HERE
diff --git a/uid.c b/uid.c
index 1a904656..ecc6b0b4 100644
--- a/uid.c
+++ b/uid.c
@@ -93,14 +93,14 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile)
strcasecmp(host, ctl->server.truename) == 0
&& strcasecmp(user, ctl->remotename) == 0)
{
- save_str(&ctl->oldsaved, UID_KEPT, id);
+ save_str(&ctl->oldsaved, id, UID_SEEN);
break;
}
}
/* if it's not in a host we're querying, save it anyway */
if (ctl == (struct query *)NULL)
- save_str(&scratchlist, UID_KEPT, buf);
+ save_str(&scratchlist, buf, UID_SEEN);
}
}
fclose(tmpfp);
@@ -108,7 +108,7 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile)
}
#endif /* POP3_ENABLE */
-struct idlist *save_str(struct idlist **idl, int num, const char *str)
+struct idlist *save_str(struct idlist **idl, const char *str, flag status)
/* save a number/UID pair on the given UID list */
{
struct idlist **end;
@@ -118,7 +118,7 @@ struct idlist *save_str(struct idlist **idl, int num, const char *str)
continue;
*end = (struct idlist *)xmalloc(sizeof(struct idlist));
- (*end)->val.num = num;
+ (*end)->val.status.mark = status;
(*end)->id = str ? xstrdup(str) : (char *)NULL;
(*end)->next = NULL;
@@ -231,7 +231,7 @@ char *str_find(struct idlist **idl, int number)
{
if (*idl == (struct idlist *) 0)
return((char *) 0);
- else if (number == (*idl)->val.num)
+ else if (number == (*idl)->val.status.num)
return((*idl)->id);
else
return(str_find(&(*idl)->next, number));
@@ -251,31 +251,15 @@ char *idpair_find(struct idlist **idl, const char *id)
int delete_str(struct idlist **idl, int num)
/* delete given message from given list */
{
-#ifdef HARD_DELETE /* not used */
- if (*idl == (struct idlist *)NULL)
- return(0);
- else if ((*idl)->val.num == num)
- {
- struct idlist *next = (*idl)->next;
-
- free ((*idl)->id);
- free(*idl);
- *idl = next;
- return(1);
- }
- else
- return(delete_str(&(*idl)->next, num));
-#else
struct idlist *idp;
for (idp = *idl; idp; idp = idp->next)
- if (idp->val.num == num)
+ if (idp->val.status.num == num)
{
- idp->val.num = UID_DELETED;
+ idp->val.status.mark = UID_DELETED;
return(1);
}
return(0);
-#endif /* HARD_DELETE */
}
void append_str_list(struct idlist **idl, struct idlist **nidl)
@@ -296,8 +280,8 @@ void expunge_uids(struct query *ctl)
struct idlist *idl;
for (idl = ctl->newsaved; idl; idl = idl->next)
- if (idl->val.num == UID_DELETED)
- idl->val.num = UID_EXPUNGED;
+ if (idl->val.status.mark == UID_DELETED)
+ idl->val.status.mark = UID_EXPUNGED;
}
void update_str_lists(struct query *ctl)
@@ -330,7 +314,8 @@ void write_saved_lists(struct query *hostlist, const char *idfile)
if ((tmpfp = fopen(idfile, "w")) != (FILE *)NULL) {
for (ctl = hostlist; ctl; ctl = ctl->next) {
for (idp = ctl->oldsaved; idp; idp = idp->next)
- if (SAVE_UID(idp->val.num))
+ if (idp->val.status.mark == UID_SEEN
+ || idp->val.status.mark == UID_DELETED)
fprintf(tmpfp, "%s@%s %s\n",
ctl->remotename, ctl->server.truename, idp->id);
}