aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--driver.c352
1 files changed, 174 insertions, 178 deletions
diff --git a/driver.c b/driver.c
index 7bd77e6b..5b2b44e7 100644
--- a/driver.c
+++ b/driver.c
@@ -8,6 +8,7 @@
#include <config.h>
#include <stdio.h>
+#include <setjmp.h>
#if defined(STDC_HEADERS)
#include <stdlib.h>
#include <string.h>
@@ -38,10 +39,7 @@
#define SMTP_PORT 25 /* standard SMTP service port */
static struct method *protocol;
-
-static int alarmed; /* a flag to indicate that SIGALRM happened */
-static int mytimeout; /* server-nonresponse timeout for current query */
-static char *srvname; /* current server name for timeout message */
+static jmp_buf restart;
char tag[TAGLEN];
static int tagnum;
@@ -647,9 +645,6 @@ struct hostrec *queryctl; /* query control record */
lines++;
}
- if (alarmed)
- return (0);
-
if (queryctl->mda[0])
{
/* close the delivery pipe, we'll reopen before next message */
@@ -706,17 +701,8 @@ int do_protocol(queryctl, proto)
struct hostrec *queryctl; /* parsed options with merged-in defaults */
struct method *proto; /* protocol method table */
{
- int ok, len;
- int mboxfd = -1;
- char buf [POPBUFSIZE+1], host[HOSTLEN+1];
- int socket;
- void (*sigsave)();
- int num, count, new, deletions = 0;
-
- srvname = queryctl->servername;
- alarmed = 0;
- sigsave = signal(SIGALRM, alarm_handler);
- alarm (mytimeout = queryctl->timeout);
+ int ok, mboxfd = -1;
+ void (*sigsave)() = signal(SIGALRM, alarm_handler);
#ifndef KERBEROS_V4
if (queryctl->authenticate == A_KERBEROS)
@@ -734,201 +720,215 @@ struct method *proto; /* protocol method table */
fprintf(stderr,
"Option --flush is not supported with %s\n",
proto->name);
- alarm(0);
- signal(SIGALRM, sigsave);
+ alarm(0);
+ signal(SIGALRM, sigsave);
return(PS_SYNTAX);
}
else if (queryctl->fetchall) {
fprintf(stderr,
"Option --all is not supported with %s\n",
proto->name);
- alarm(0);
- signal(SIGALRM, sigsave);
+ alarm(0);
+ signal(SIGALRM, sigsave);
return(PS_SYNTAX);
}
}
+ protocol = proto;
tagnum = 0;
tag[0] = '\0'; /* nuke any tag hanging out from previous query */
- protocol = proto;
+ ok = 0;
- /* open a socket to the mail server */
- if ((socket = Socket(queryctl->servername,
- queryctl->port ? queryctl->port : protocol->port))<0
- || alarmed)
+ if (setjmp(restart) == 1)
+ fprintf(stderr,
+ "fetchmail: timeout after %d seconds waiting for %s.\n",
+ queryctl->timeout, queryctl->servername);
+ else
{
- perror("fetchmail, connecting to host");
- ok = PS_SOCKET;
- goto closeUp;
- }
+ char buf [POPBUFSIZE+1], host[HOSTLEN+1];
+ int socket, len, num, count, new, deletions = 0;
+
+ alarm(queryctl->timeout);
+
+ /* open a socket to the mail server */
+ if ((socket = Socket(queryctl->servername,
+ queryctl->port ? queryctl->port : protocol->port))<0)
+ {
+ perror("fetchmail, connecting to host");
+ ok = PS_SOCKET;
+ goto closeUp;
+ }
#ifdef KERBEROS_V4
- if (queryctl->authenticate == A_KERBEROS)
- {
- ok = (kerberos_auth (socket, queryctl->canonical_name));
+ if (queryctl->authenticate == A_KERBEROS)
+ {
+ ok = (kerberos_auth (socket, queryctl->canonical_name));
+ if (ok != 0)
+ goto cleanUp;
+ }
+#endif /* KERBEROS_V4 */
+
+ /* accept greeting message from mail server */
+ ok = (protocol->parse_response)(socket, buf);
if (ok != 0)
goto cleanUp;
- }
-#endif /* KERBEROS_V4 */
- /* accept greeting message from mail server */
- ok = (protocol->parse_response)(socket, buf);
- if (alarmed || ok != 0)
- goto cleanUp;
-
- /* try to get authorized to fetch mail */
- shroud = queryctl->password;
- ok = (protocol->getauth)(socket, queryctl, buf);
- shroud = (char *)NULL;
- if (alarmed || ok == PS_ERROR)
- ok = PS_AUTHFAIL;
- if (alarmed || ok != 0)
- goto cleanUp;
-
- /* compute number of messages and number of new messages waiting */
- if ((protocol->getrange)(socket, queryctl, &count, &new) != 0 || alarmed)
- goto cleanUp;
-
- /* show user how many messages we downloaded */
- if (outlevel > O_SILENT && outlevel < O_VERBOSE)
- if (count == 0)
- fprintf(stderr, "No mail from %s@%s\n",
- queryctl->remotename,
- queryctl->servername);
- else
- {
- fprintf(stderr, "%d message%s", count, count > 1 ? "s" : "");
- if (new != -1 && (count - new) > 0)
- fprintf(stderr, " (%d seen)", count-new);
- fprintf(stderr,
- " from %s@%s.\n",
- queryctl->remotename,
- queryctl->servername);
- }
+ /* try to get authorized to fetch mail */
+ shroud = queryctl->password;
+ ok = (protocol->getauth)(socket, queryctl, buf);
+ shroud = (char *)NULL;
+ if (ok == PS_ERROR)
+ ok = PS_AUTHFAIL;
+ if (ok != 0)
+ goto cleanUp;
- if (check_only)
- {
- if (new == -1 || queryctl->fetchall)
- new = count;
- ok = ((new > 0) ? PS_SUCCESS : PS_NOMAIL);
- goto closeUp;
- }
- else if (count > 0)
- {
- if (queryctl->mda[0] == '\0')
- if ((mboxfd = Socket(queryctl->smtphost, SMTP_PORT)) < 0
- || SMTP_ok(mboxfd, NULL) != SM_OK
- || SMTP_helo(mboxfd, queryctl->servername) != SM_OK
- || alarmed)
+ /* compute number of messages and number of new messages waiting */
+ if ((protocol->getrange)(socket, queryctl, &count, &new) != 0)
+ goto cleanUp;
+
+ /* show user how many messages we downloaded */
+ if (outlevel > O_SILENT && outlevel < O_VERBOSE)
+ if (count == 0)
+ fprintf(stderr, "No mail from %s@%s\n",
+ queryctl->remotename,
+ queryctl->servername);
+ else
{
- ok = PS_SMTP;
- close(mboxfd);
- mboxfd = -1;
- goto cleanUp;
+ fprintf(stderr, "%d message%s", count, count > 1 ? "s" : "");
+ if (new != -1 && (count - new) > 0)
+ fprintf(stderr, " (%d seen)", count-new);
+ fprintf(stderr,
+ " from %s@%s.\n",
+ queryctl->remotename,
+ queryctl->servername);
}
-
- /* read, forward, and delete messages */
- for (num = 1; num <= count; num++)
- {
- int fetch_it = queryctl->fetchall ||
- !(protocol->is_old && (protocol->is_old)(socket,queryctl,num));
- /* we may want to reject this message if it's old */
- if (!fetch_it)
- fprintf(stderr, "skipping message %d ", num);
- else
+ if (check_only)
+ {
+ if (new == -1 || queryctl->fetchall)
+ new = count;
+ ok = ((new > 0) ? PS_SUCCESS : PS_NOMAIL);
+ goto closeUp;
+ }
+ else if (count > 0)
+ {
+ if (queryctl->mda[0] == '\0')
+ if ((mboxfd = Socket(queryctl->smtphost, SMTP_PORT)) < 0
+ || SMTP_ok(mboxfd, NULL) != SM_OK
+ || SMTP_helo(mboxfd, queryctl->servername) != SM_OK)
+ {
+ ok = PS_SMTP;
+ close(mboxfd);
+ mboxfd = -1;
+ goto cleanUp;
+ }
+
+ /* read, forward, and delete messages */
+ for (num = 1; num <= count; num++)
{
- /* request a message */
- (protocol->fetch)(socket, num, &len);
+ int fetch_it = queryctl->fetchall ||
+ !(protocol->is_old && (protocol->is_old)(socket,queryctl,num));
- if (outlevel > O_SILENT)
+ /* we may want to reject this message if it's old */
+ if (!fetch_it)
+ fprintf(stderr, "skipping message %d ", num);
+ else
{
- fprintf(stderr, "reading message %d", num);
- if (len > 0)
- fprintf(stderr, " (%d bytes)", len);
- if (outlevel == O_VERBOSE)
- fputc('\n', stderr);
- else
- fputc(' ', stderr);
+ /* request a message */
+ (protocol->fetch)(socket, num, &len);
+
+ if (outlevel > O_SILENT)
+ {
+ fprintf(stderr, "reading message %d", num);
+ if (len > 0)
+ fprintf(stderr, " (%d bytes)", len);
+ if (outlevel == O_VERBOSE)
+ fputc('\n', stderr);
+ else
+ 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, mboxfd,
+ len,
+ protocol->delimited,
+ queryctl);
+
+ /* tell the server we got it OK and resynchronize */
+ if (protocol->trail)
+ (protocol->trail)(socket, queryctl, num);
+ if (ok != 0)
+ goto cleanUp;
}
/*
- * 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
+ * At this point in flow of control, either we've bombed
+ * on a protocol error or had delivery refused by the SMTP
+ * server (unlikely -- I've never seen it) or we've seen
+ * `accepted for delivery' and the message is shipped.
+ * It's safe to mark the message seen and delete it on the
+ * server now.
*/
- /* read the message and ship it to the output sink */
- ok = gen_readmsg(socket, mboxfd,
- len,
- protocol->delimited,
- queryctl);
-
- /* tell the server we got it OK and resynchronize */
- if (protocol->trail)
- (protocol->trail)(socket, queryctl, num);
- if (alarmed || ok != 0)
- goto cleanUp;
+ /* maybe we delete this message now? */
+ if (protocol->delete
+ && (fetch_it ? !queryctl->keep : queryctl->flush))
+ {
+ deletions++;
+ if (outlevel > O_SILENT && outlevel < O_VERBOSE)
+ fprintf(stderr, " flushed\n", num);
+ ok = (protocol->delete)(socket, queryctl, num);
+ if (ok != 0)
+ goto cleanUp;
+ }
+ else if (outlevel > O_SILENT && outlevel < O_VERBOSE)
+ {
+ /* nuke it from the unseen-messages list */
+ delete_uid(&queryctl->newsaved, num);
+ fprintf(stderr, " not flushed\n", num);
+ }
}
- /*
- * At this point in flow of control, either we've bombed
- * on a protocol error or had delivery refused by the SMTP
- * server (unlikely -- I've never seen it) or we've seen
- * `accepted for delivery' and the message is shipped.
- * It's safe to mark the message seen and delete it on the
- * server now.
- */
-
- /* maybe we delete this message now? */
- if (protocol->delete
- && (fetch_it ? !queryctl->keep : queryctl->flush))
+ /* remove all messages flagged for deletion */
+ if (protocol->expunge_cmd && deletions > 0)
{
- deletions++;
- if (outlevel > O_SILENT && outlevel < O_VERBOSE)
- fprintf(stderr, " flushed\n", num);
- ok = (protocol->delete)(socket, queryctl, num);
- if (alarmed || ok != 0)
+ ok = gen_transact(socket, protocol->expunge_cmd);
+ if (ok != 0)
goto cleanUp;
}
- else if (outlevel > O_SILENT && outlevel < O_VERBOSE)
- {
- /* nuke it from the unseen-messages list */
- delete_uid(&queryctl->newsaved, num);
- fprintf(stderr, " not flushed\n", num);
- }
+
+ ok = gen_transact(socket, protocol->exit_cmd);
+ if (ok == 0)
+ ok = PS_SUCCESS;
+ close(socket);
+ goto closeUp;
+ }
+ else {
+ ok = gen_transact(socket, protocol->exit_cmd);
+ if (ok == 0)
+ ok = PS_NOMAIL;
+ close(socket);
+ goto closeUp;
}
- /* remove all messages flagged for deletion */
- if (protocol->expunge_cmd && deletions > 0)
+ cleanUp:
+ if (ok != 0 && ok != PS_SOCKET)
{
- ok = gen_transact(socket, protocol->expunge_cmd);
- if (alarmed || ok != 0)
- goto cleanUp;
- }
-
- ok = gen_transact(socket, protocol->exit_cmd);
- if (alarmed || ok == 0)
- ok = PS_SUCCESS;
- close(socket);
- goto closeUp;
- }
- else {
- ok = gen_transact(socket, protocol->exit_cmd);
- if (ok == 0)
- ok = PS_NOMAIL;
- close(socket);
- goto closeUp;
+ gen_transact(socket, protocol->exit_cmd);
+ close(socket);
+ }
}
-cleanUp:
- if (ok != 0 && ok != PS_SOCKET)
- {
- gen_transact(socket, protocol->exit_cmd);
- close(socket);
- }
+ alarm(0);
+ signal(SIGALRM, sigsave);
closeUp:
if (mboxfd != -1)
@@ -937,8 +937,7 @@ closeUp:
SMTP_quit(mboxfd);
close(mboxfd);
}
- alarm(0);
- signal(SIGALRM, sigsave);
+
return(ok);
}
@@ -1052,10 +1051,7 @@ void
alarm_handler (int signal)
/* handle server-timeout signal */
{
- alarmed = 1;
- fprintf(stderr,
- "fetchmail: timeout after %d seconds waiting for %s.\n",
- mytimeout, srvname);
+ longjmp(restart, 1);
}
/* driver.c ends here */