diff options
author | Eric S. Raymond <esr@thyrsus.com> | 1998-03-13 20:20:19 +0000 |
---|---|---|
committer | Eric S. Raymond <esr@thyrsus.com> | 1998-03-13 20:20:19 +0000 |
commit | d3833f31da28808274c6d08804646116be7dabb8 (patch) | |
tree | 985ae69fd971dffb43a300f92f3b4867857267ab | |
parent | 8517cf573fdb368fa69d776bc113cd95c6646edb (diff) | |
download | fetchmail-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-- | NEWS | 1 | ||||
-rw-r--r-- | driver.c | 51 | ||||
-rw-r--r-- | fetchmail.c | 8 | ||||
-rw-r--r-- | fetchmail.h | 44 | ||||
-rw-r--r-- | options.c | 4 | ||||
-rw-r--r-- | pop3.c | 20 | ||||
-rw-r--r-- | rcfile_y.y | 16 | ||||
-rw-r--r-- | uid.c | 37 |
8 files changed, 88 insertions, 93 deletions
@@ -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. @@ -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 **); @@ -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++; @@ -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)++; } } @@ -115,12 +115,12 @@ serverspecs : /* EMPTY */ | serverspecs serv_option ; -alias_list : STRING {save_str(¤t.server.akalist,-1,$1);} - | alias_list STRING {save_str(¤t.server.akalist,-1,$2);} +alias_list : STRING {save_str(¤t.server.akalist,$1,0);} + | alias_list STRING {save_str(¤t.server.akalist,$2,0);} ; -domain_list : STRING {save_str(¤t.server.localdomains,-1,$1);} - | domain_list STRING {save_str(¤t.server.localdomains,-1,$2);} +domain_list : STRING {save_str(¤t.server.localdomains,$1,0);} + | domain_list STRING {save_str(¤t.server.localdomains,$2,0);} ; serv_option : AKA alias_list @@ -252,12 +252,12 @@ mapping : STRING {save_str_pair(¤t.localnames, $1, $3);} ; -folder_list : STRING {save_str(¤t.mailboxes,-1,$1);} - | folder_list STRING {save_str(¤t.mailboxes,-1,$2);} +folder_list : STRING {save_str(¤t.mailboxes,$1,0);} + | folder_list STRING {save_str(¤t.mailboxes,$2,0);} ; -smtp_list : STRING {save_str(¤t.smtphunt, TRUE,$1);} - | smtp_list STRING {save_str(¤t.smtphunt, TRUE,$2);} +smtp_list : STRING {save_str(¤t.smtphunt, $1,TRUE);} + | smtp_list STRING {save_str(¤t.smtphunt, $2,TRUE);} ; user_option : TO localnames HERE @@ -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); } |