diff options
-rw-r--r-- | driver.c | 23 | ||||
-rw-r--r-- | fetchmail.c | 21 | ||||
-rw-r--r-- | fetchmail.h | 18 | ||||
-rw-r--r-- | uid.c | 12 | ||||
-rw-r--r-- | xmalloc.c | 2 |
5 files changed, 53 insertions, 23 deletions
@@ -120,13 +120,25 @@ static int is_host_alias(const char *name, struct query *ctl) return(TRUE); /* + * Is it in the `also known as' cache accumulated by previous DNS checks? + * This cache may someday be primed by an aka option. + */ + else if (uid_in_list(&ctl->lead_server->aka, name)) + return(TRUE); + + /* * We know DNS service was up at the beginning of this poll cycle. * If it's down, our nameserver has crashed. We don't want to try * delivering the current message or anything else from this * mailbox until it's back up. */ else if ((he = gethostbyname(name)) != (struct hostent *)NULL) - return(strcmp(ctl->canonical_name, he->h_name) == 0); + { + if (strcmp(ctl->canonical_name, he->h_name) == 0) + goto match; + else + return(FALSE); + } else switch (h_errno) { @@ -162,7 +174,7 @@ static int is_host_alias(const char *name, struct query *ctl) case NO_ADDRESS: /* valid, but does not have an IP address */ for (mxp = mxrecords; mxp->name; mxp++) if (strcmp(name, mxp->name) == 0) - return(TRUE); + goto match; break; case NO_RECOVERY: /* non-recoverable name server error */ @@ -177,6 +189,11 @@ static int is_host_alias(const char *name, struct query *ctl) } return(FALSE); + +match: + /* add this name to relevant server's `also known as' list */ + save_uid(&ctl->lead_server->aka, -1, name); + return(TRUE); } void find_server_names(hdr, ctl, xmit_names) @@ -226,7 +243,7 @@ struct idlist **xmit_names; /* list of recipient names parsed out */ static FILE *smtp_open(struct query *ctl) /* try to open a socket to the appropriate SMTP server for this query */ { - ctl = ctl->leader; /* go to the SMTP leader for this query */ + ctl = ctl->lead_smtp; /* go to the SMTP leader for this query */ /* maybe it's time to close the socket in order to force delivery */ if (batchlimit && ctl->smtp_sockfp && batchcount++ == batchlimit) diff --git a/fetchmail.c b/fetchmail.c index 5e39b4dc..a3a734be 100644 --- a/fetchmail.c +++ b/fetchmail.c @@ -517,21 +517,32 @@ static int load_params(int argc, char **argv, int optind) * * In the typical case, there will be only one SMTP host (the * client machine) and thus just one SMTP leader (and one listener - * process) through the entire run. + * process) through the entire poll cycle. */ if (!ctl->mda[0]) { + ctl->smtp_sockfp = (FILE *)NULL; for (mp = querylist; mp && mp != ctl; mp = mp->next) if (strcmp(mp->smtphost, ctl->smtphost) == 0) { - ctl->leader = mp->leader; + ctl->lead_smtp = mp->lead_smtp; goto no_new_leader; } - ctl->leader = ctl; - ctl->smtp_sockfp = (FILE *)NULL; + ctl->lead_smtp = ctl; no_new_leader:; } + /* similarly, compute server leaders for queries */ + ctl->aka = (struct idlist *)NULL; + for (mp = querylist; mp && mp != ctl; mp = mp->next) + if (strcmp(mp->servername, ctl->servername) == 0) + { + ctl->lead_server = mp->lead_server; + goto no_new_server; + } + ctl->lead_server = ctl; + no_new_server:; + /* sanity checks */ if (ctl->port < 0) { @@ -588,7 +599,7 @@ void termhook(int sig) /* terminate all SMTP connections cleanly */ for (ctl = querylist; ctl; ctl = ctl->next) - if (ctl->leader == ctl && ctl->smtp_sockfp != (FILE *)NULL) + if (ctl->lead_smtp == ctl && ctl->smtp_sockfp != (FILE *)NULL) SMTP_quit(ctl->smtp_sockfp); if (!check_only) diff --git a/fetchmail.h b/fetchmail.h index 6acd0c99..3765f6f3 100644 --- a/fetchmail.h +++ b/fetchmail.h @@ -94,8 +94,10 @@ struct query int active; int errcount; /* count transient errors in last pass */ struct query *next; /* next query control block in chain */ - struct query *leader; /* pointer to this query's SMTP leader */ + struct query *lead_smtp; /* pointer to this query's SMTP leader */ FILE *smtp_sockfp; /* socket descriptor for SMTP connection */ + struct query *lead_server; /* pointer to lead query for this server */ + struct idlist *aka; /* server alias list */ unsigned int uid; /* UID of user to deliver to */ char digest [DIGESTLEN]; /* md5 digest buffer */ #ifdef HAVE_GETHOSTBYNAME @@ -162,7 +164,7 @@ int gen_transact (); #endif void *xmalloc(int); -char *xstrdup(char *); +char *xstrdup(const char *); int do_protocol(struct query *, const struct method *); int doPOP2 (struct query *); @@ -172,18 +174,18 @@ int doIMAP (struct query *); void reply_hack(char *, const char *); char *nxtaddr(const char *); -void initialize_saved_lists(struct query *, char *); -struct idlist *save_uid(struct idlist **, int, char *); +void initialize_saved_lists(struct query *, const char *); +struct idlist *save_uid(struct idlist **, int, const char *); void free_uid_list(struct idlist **); -void save_id_pair(struct idlist **, char *, char *); +void save_id_pair(struct idlist **, const char *, const char *); void free_idpair_list(struct idlist **); int delete_uid(struct idlist **, int); -int uid_in_list(struct idlist **, char *); +int uid_in_list(struct idlist **, const char *); char *uid_find(struct idlist **, int); -char *idpair_find(struct idlist **, char *); +char *idpair_find(struct idlist **, const char *); void append_uid_list(struct idlist **, struct idlist **); void update_uid_lists(struct query *); -void write_saved_lists(struct query *, char *); +void write_saved_lists(struct query *, const char *); struct query *hostalloc(struct query *); int parsecmdline (int, char **, struct query *); @@ -62,7 +62,7 @@ /* UIDs associated with un-queried hosts */ static struct idlist *scratchlist; -void initialize_saved_lists(struct query *hostlist, char *idfile) +void initialize_saved_lists(struct query *hostlist, const char *idfile) /* read file of saved IDs and attach to each host */ { int st; @@ -99,7 +99,7 @@ void initialize_saved_lists(struct query *hostlist, char *idfile) } } -struct idlist *save_uid(struct idlist **idl, int num, char *str) +struct idlist *save_uid(struct idlist **idl, int num, const char *str) /* save a number/UID pair on the given UID list */ { struct idlist *new; @@ -125,7 +125,7 @@ void free_uid_list(struct idlist **idl) *idl = (struct idlist *)NULL; } -void save_id_pair(struct idlist **idl, char *str1, char *str2) +void save_id_pair(struct idlist **idl, const char *str1, const char *str2) /* save an ID pair on the given list */ { struct idlist *new; @@ -155,7 +155,7 @@ void free_idpair_list(struct idlist **idl) } #endif -int uid_in_list(struct idlist **idl, char *str) +int uid_in_list(struct idlist **idl, const char *str) /* is a given ID in the given list? */ { if (*idl == (struct idlist *)NULL || str == (char *) NULL) @@ -177,7 +177,7 @@ char *uid_find(struct idlist **idl, int number) return(uid_find(&(*idl)->next, number)); } -char *idpair_find(struct idlist **idl, char *id) +char *idpair_find(struct idlist **idl, const char *id) /* return the id of the given number in the given list. */ { if (*idl == (struct idlist *) 0) @@ -226,7 +226,7 @@ void update_uid_lists(struct query *hostp) hostp->newsaved = (struct idlist *) NULL; } -void write_saved_lists(struct query *hostlist, char *idfile) +void write_saved_lists(struct query *hostlist, const char *idfile) /* perform end-of-run write of seen-messages list */ { int idcount; @@ -31,7 +31,7 @@ xmalloc (int n) return(p); } -char *xstrdup(char *s) +char *xstrdup(const char *s) { char *p; p = (char *) xmalloc(strlen(s)+1); |