aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>1996-10-29 01:54:58 +0000
committerEric S. Raymond <esr@thyrsus.com>1996-10-29 01:54:58 +0000
commit800186e3873690997bdbd7e1b60c83ca2d9819cd (patch)
treef15eaa7f138442747b0ed3691a70b817619a0b32
parent83840832840c57e9ae6109627a1e18e0c6b04d58 (diff)
downloadfetchmail-800186e3873690997bdbd7e1b60c83ca2d9819cd.tar.gz
fetchmail-800186e3873690997bdbd7e1b60c83ca2d9819cd.tar.bz2
fetchmail-800186e3873690997bdbd7e1b60c83ca2d9819cd.zip
Only open one conneection per host in daemon mode.
svn path=/trunk/; revision=414
-rw-r--r--NEWS1
-rw-r--r--driver.c60
-rw-r--r--fetchmail.c38
-rw-r--r--fetchmail.h6
4 files changed, 68 insertions, 37 deletions
diff --git a/NEWS b/NEWS
index 5a464d3b..2cce085e 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@
pl 1.9.4 ():
* Correct status interpretation in closemailpipe() (thanks to Neil Harkins).
+* Tweak SMTP forwarding to only open one listener per SMTP host in daemon mode.
pl 1.9.3 (Sun Oct 27 22:35:33 EST 1996):
* Handle nested parens in RFC822 comments.
diff --git a/driver.c b/driver.c
index a1a68f59..f4f3b110 100644
--- a/driver.c
+++ b/driver.c
@@ -49,7 +49,6 @@ char tag[TAGLEN];
static int tagnum;
#define GENSYM (sprintf(tag, "a%04d", ++tagnum), tag)
-static int mboxfd; /* desc to which retrieved message will be written */
static char *shroud; /* string to shroud in debug output, if non-NULL */
static int strcrlf(dst, src, count)
@@ -449,29 +448,26 @@ struct idlist **xmit_names; /* list of recipient names parsed out */
}
#endif /* HAVE_GETHOSTBYNAME */
-int smtp_open(host)
-/* try to open a socket to given host's SMTP server */
-char *host;
+static int smtp_open(ctl)
+/* try to open a socket to the appropriate SMTP server for this query */
+struct query *ctl;
{
- if ((mboxfd = Socket(host, SMTP_PORT)) < 0
- || SMTP_ok(mboxfd, NULL) != SM_OK
- || SMTP_helo(mboxfd, "localhost") != SM_OK)
- {
- close(mboxfd);
- mboxfd = -1;
- }
-
- return(mboxfd);
-}
+ ctl = ctl->leader; /* go to the SMTP leader for this query */
-void smtp_close()
-/* close the current SMTP connection */
-{
- if (mboxfd != -1)
+ /* if no socket to this host is already set up, try to open one */
+ if (ctl->smtp_socket == -1)
{
- SMTP_quit(mboxfd);
- close(mboxfd);
+ if ((ctl->smtp_socket = Socket(ctl->smtphost, SMTP_PORT)) == -1)
+ return(-1);
+ else if (SMTP_ok(ctl->smtp_socket, NULL) != SM_OK
+ || SMTP_helo(ctl->smtp_socket, ctl->servername) != SM_OK)
+ {
+ close(ctl->smtp_socket);
+ ctl->smtp_socket = -1;
+ }
}
+
+ return(ctl->smtp_socket);
}
static int gen_readmsg (socket, len, delimited, ctl)
@@ -483,7 +479,7 @@ struct query *ctl; /* query control record */
{
char buf [MSGBUFSIZE+1];
char *bufp, *headers, *fromhdr, *tohdr, *cchdr, *bcchdr;
- int n, oldlen;
+ int n, oldlen, mboxfd;
int inheaders,lines,sizeticker;
/* read the message content from the server */
@@ -643,7 +639,7 @@ struct query *ctl; /* query control record */
}
else
{
- if (ctl->mda[0] == '\0' && (smtp_open(ctl->smtphost) < 0))
+ if (ctl->mda[0] == '\0' && ((mboxfd = smtp_open(ctl)) < 0))
{
free_uid_list(&xmit_names);
fprintf(stderr, "fetchmail: SMTP connect failed\n");
@@ -826,7 +822,6 @@ const struct method *proto; /* protocol method table */
tagnum = 0;
tag[0] = '\0'; /* nuke any tag hanging out from previous query */
ok = 0;
- mboxfd = -1;
if (setjmp(restart) == 1)
fprintf(stderr,
@@ -946,14 +941,6 @@ const struct method *proto; /* protocol method table */
fputc(' ', stderr);
}
- /*
- * If we're forwarding via SMTP, mboxfd is initialized
- * at this point (it was set at start of retrieval).
- * If we're using an MDA it's not set -- gen_readmsg()
- * may have to parse message headers to know what
- * delivery addresses should be passed to the MDA
- */
-
/* read the message and ship it to the output sink */
ok = gen_readmsg(socket,
len,
@@ -1029,11 +1016,18 @@ const struct method *proto; /* protocol method table */
signal(SIGALRM, sigsave);
closeUp:
- if (!ctl->mda[0])
- smtp_close();
return(ok);
}
+void smtp_close(mboxfd)
+/* close the current SMTP connection */
+int mboxfd;
+{
+ if (mboxfd != -1)
+ {
+ close(mboxfd);
+ }
+}
#if defined(HAVE_STDARG_H)
void gen_send(int socket, char *fmt, ... )
/* assemble command in printf(3) style and send to the server */
diff --git a/fetchmail.c b/fetchmail.c
index d6b8349d..5f76b8c2 100644
--- a/fetchmail.c
+++ b/fetchmail.c
@@ -63,7 +63,6 @@ char *user; /* the name of the invoking user */
static void termhook();
static char *lockfile;
static int popstatus;
-static struct query *ctl;
RETSIGTYPE donothing(sig) int sig; {signal(sig, donothing);}
@@ -72,7 +71,7 @@ int argc;
char **argv;
{
int st, lossage, bkgd = FALSE;
- struct query def_opts;
+ struct query def_opts, *ctl, *mp;
int parsestatus, implicitmode;
char *home, *tmpdir, tmpbuf[BUFSIZ];
struct passwd *pw;
@@ -175,6 +174,7 @@ char **argv;
/* merge in wired defaults, do sanity checks and prepare internal fields */
for (ctl = querylist; ctl; ctl = ctl->next)
+ {
if (ctl->active && !(implicitmode && ctl->skip))
{
#ifdef HAVE_GETHOSTBYNAME
@@ -232,6 +232,30 @@ char **argv;
}
#endif /* HAVE_GETHOSTBYNAME */
+ /*
+ * Assign SMTP leaders. We want to allow all query blocks
+ * sharing the same SMTP host to use the same SMTP connection.
+ * To accomplish this, we initialize each query block's leader
+ * field to point to the first block in the list with a matching
+ * SMTP host.
+ *
+ * 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.
+ */
+ if (!ctl->mda[0])
+ {
+ for (mp = querylist; mp && mp != ctl; mp = mp->next)
+ if (strcmp(mp->smtphost, ctl->smtphost) == 0)
+ {
+ ctl->leader = mp->leader;
+ goto no_new_leader;
+ }
+ ctl->leader = ctl;
+ ctl->smtp_socket = -1;
+ no_new_leader:;
+ }
+
/* sanity checks */
if (ctl->port < 0)
{
@@ -263,6 +287,9 @@ char **argv;
ctl->mda_argv[1] = argp + 1 ;
}
}
+ }
+
+
/* set up to do lock protocol */
if ((tmpdir = getenv("TMPDIR")) == (char *)NULL)
@@ -499,9 +526,16 @@ char **argv;
void termhook(int sig)
/* to be executed on normal or signal-induced termination */
{
+ struct query *ctl;
+
if (sig != 0)
fprintf(stderr, "terminated with signal %d\n", sig);
+ /* terminate all SMTP connections cleanly */
+ for (ctl = querylist; ctl; ctl = ctl->next)
+ if (ctl->leader == ctl && ctl->smtp_socket != -1)
+ SMTP_quit(ctl->smtp_socket);
+
if (!check_only)
write_saved_lists(querylist, idfile);
diff --git a/fetchmail.h b/fetchmail.h
index b03899d0..4022f625 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -92,9 +92,11 @@ struct query
/* internal use */
int active;
- struct query *next; /* next host in chain */
+ struct query *next; /* next query control block in chain */
+ struct query *leader; /* pointer to this query's SMTP leader */
+ int smtp_socket; /* socket descriptor for SMTP connection */
unsigned int uid; /* UID of user to deliver to */
- char digest [DIGESTLEN];
+ char digest [DIGESTLEN]; /* md5 digest buffer */
#ifdef HAVE_GETHOSTBYNAME
char *canonical_name; /* DNS canonical name of server host */
#endif /* HAVE_GETHOSTBYNAME */