aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>1996-10-09 16:03:23 +0000
committerEric S. Raymond <esr@thyrsus.com>1996-10-09 16:03:23 +0000
commit1413fd46bcbd4a05c3e46113fbd7ae11b3d4a40a (patch)
treed31255f0c1f6d1820d79a512ed178a8e8abdad37
parentdf4a9dc9bea6d5ebe6d6c409af795f665c115787 (diff)
downloadfetchmail-1413fd46bcbd4a05c3e46113fbd7ae11b3d4a40a.tar.gz
fetchmail-1413fd46bcbd4a05c3e46113fbd7ae11b3d4a40a.tar.bz2
fetchmail-1413fd46bcbd4a05c3e46113fbd7ae11b3d4a40a.zip
Arrange for timeout by client if server connection is dropped.
svn path=/trunk/; revision=260
-rw-r--r--NEWS10
-rw-r--r--driver.c67
-rw-r--r--socket.c14
3 files changed, 79 insertions, 12 deletions
diff --git a/NEWS b/NEWS
index a49ce809..bcff3c4f 100644
--- a/NEWS
+++ b/NEWS
@@ -19,6 +19,16 @@ Inflict severe pain on the person(s) responsible for removing LAST from POP3.
Release Notes:
+fetchmail-1.8 ():
+
+* Fix buggy getopt specification of P and p options.
+
+* Use kill(0, pid) to make lock handling a bit smarter (thanks to Johann
+ Vromans for the suggestion).
+
+* Arrange for timeout of client if connection to server is dropped
+ (thanks to Gasper Sinai).
+
fetchmail-1.7 (Tue Oct 8 11:32:44 EDT 1996):
features --
diff --git a/driver.c b/driver.c
index d43caa78..0336af84 100644
--- a/driver.c
+++ b/driver.c
@@ -16,6 +16,7 @@
#include <malloc.h>
#include <varargs.h>
#include <sys/time.h>
+#include <signal.h>
#ifdef HAVE_RRESVPORT_H
#include <netinet/in.h>
#endif /* HAVE_RRESVPORT_H */
@@ -26,6 +27,12 @@
static struct method *protocol;
+static int alarmed; /* A flag to indicate that SIGALRM happened */
+
+int timeout=300; /* Wake up from idle state */
+void alarm_handler();
+
+
#define SMTP_PORT 25 /* standard SMTP service port */
char tag[TAGLEN];
@@ -467,6 +474,8 @@ struct hostrec *queryctl;
else if (outlevel > O_SILENT)
fputs("\n", stderr);
+ if (alarmed)
+ return (0);
/* write message terminator */
if (!queryctl->mda[0])
if (SMTP_eom(mboxfd) != SM_OK)
@@ -498,11 +507,16 @@ struct method *proto;
int mboxfd = -1;
char buf [POPBUFSIZE+1], host[HOSTLEN+1];
int socket;
+ void (*sigsave)();
+
#ifdef HAVE_RRESVPORT_H
int privport = -1;
#endif /* HAVE_RRESVPORT_H */
int num, count, deletions = 0;
+ alarmed = 0;
+ sigsave = signal(SIGALRM, alarm_handler);
+ alarm (timeout);
/* lacking methods, there are some options that may fail */
if (!proto->is_old)
{
@@ -511,12 +525,16 @@ struct method *proto;
fprintf(stderr,
"Option --flush is not supported with %s\n",
proto->name);
+ 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);
return(PS_SYNTAX);
}
}
@@ -533,9 +551,11 @@ struct method *proto;
if (queryctl->port < IPPORT_RESERVED)
{
ok = IPPORT_RESERVED - 1;
- if ((privport = rresvport(&ok)) == -1)
+ if ((privport = rresvport(&ok)) == -1 || alarmed)
{
perror("fetchmail, binding to reserved port");
+ alarm(0);
+ signal(SIGALRM, sigsave);
return(PS_SOCKET);
}
}
@@ -543,7 +563,8 @@ struct method *proto;
/* open a socket to the mail server */
if ((socket = Socket(queryctl->servername,
- queryctl->port ? queryctl->port : protocol->port))<0)
+ queryctl->port ? queryctl->port : protocol->port))<0
+ || alarmed)
{
perror("fetchmail, connecting to host");
ok = PS_SOCKET;
@@ -552,18 +573,18 @@ struct method *proto;
/* accept greeting message from mail server */
ok = (protocol->parse_response)(socket, buf);
- if (ok != 0)
+ if (alarmed || ok != 0)
goto cleanUp;
/* try to get authorized to fetch mail */
ok = (protocol->getauth)(socket, queryctl, buf);
- if (ok == PS_ERROR)
+ if (alarmed || ok == PS_ERROR)
ok = PS_AUTHFAIL;
- if (ok != 0)
+ if (alarmed || ok != 0)
goto cleanUp;
/* compute count, and get UID list if possible */
- if ((protocol->getrange)(socket, queryctl, &count) != 0)
+ if ((protocol->getrange)(socket, queryctl, &count) != 0 || alarmed)
goto cleanUp;
/* show user how many messages we downloaded */
@@ -581,7 +602,8 @@ struct method *proto;
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)
+ || SMTP_helo(mboxfd, queryctl->servername) != SM_OK
+ || alarmed)
{
ok = PS_SMTP;
close(mboxfd);
@@ -624,13 +646,13 @@ struct method *proto;
/* close the delivery pipe, we'll reopen before next message */
if (queryctl->mda[0])
- if ((ok = closemailpipe(mboxfd)) != 0)
+ if ((ok = closemailpipe(mboxfd)) != 0 || alarmed)
goto cleanUp;
/* tell the server we got it OK and resynchronize */
if (protocol->trail)
(protocol->trail)(socket, queryctl, num);
- if (ok != 0)
+ if (alarmed || ok != 0)
goto cleanUp;
}
@@ -651,7 +673,7 @@ struct method *proto;
if (outlevel > O_SILENT && outlevel < O_VERBOSE)
fprintf(stderr,"flushing message %d\n", num);
ok = (protocol->delete)(socket, queryctl, num);
- if (ok != 0)
+ if (alarmed || ok != 0)
goto cleanUp;
}
}
@@ -660,12 +682,12 @@ struct method *proto;
if (protocol->expunge_cmd && deletions > 0)
{
ok = gen_transact(socket, protocol->expunge_cmd);
- if (ok != 0)
+ if (alarmed || ok != 0)
goto cleanUp;
}
ok = gen_transact(socket, protocol->exit_cmd);
- if (ok == 0)
+ if (alarmed || ok == 0)
ok = PS_SUCCESS;
close(socket);
goto closeUp;
@@ -696,6 +718,8 @@ closeUp:
SMTP_quit(mboxfd);
close(mboxfd);
}
+ alarm(0);
+ signal(SIGALRM, sigsave);
return(ok);
}
@@ -778,3 +802,22 @@ va_dcl {
}
+/*********************************************************************
+ function: alarm_handler
+ description: In real life process can get stuck waiting for
+ something. This deadlock is avoided here by this
+ sending SIGALRM
+
+ arguments:
+ signal hopefully SIGALRM
+
+ return value: none.
+ calls: none
+ globals: sets alarmed to 1
+ *********************************************************************/
+void
+alarm_handler (int signal)
+{
+ alarmed = 1;
+ fprintf(stderr,"Timeout after %d seconds.\n", timeout);
+}
diff --git a/socket.c b/socket.c
index 8b79e818..3cfb9f0a 100644
--- a/socket.c
+++ b/socket.c
@@ -13,6 +13,7 @@
#include <config.h>
+#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -43,6 +44,8 @@
#define INTERNAL_BUFSIZE 2048
+extern int timeout;
+extern void alarm_handler();
int Socket(host, clientPort)
char *host;
@@ -82,9 +85,17 @@ char *buf;
int len;
{
int rdlen = 0;
+ RETSIGTYPE (*sigsave)();
while (--len)
{
+ /* we have to push alarm in case we receive a large message */
+ sigsave = signal (SIGALRM, alarm_handler);
+ if (sigsave == alarm_handler)
+ alarm (timeout);
+ else
+ signal (SIGALRM, sigsave);
+
if (SockInternalRead(socket, buf, 1) != 1)
return -1;
else
@@ -134,6 +145,7 @@ int len;
{
int n;
+
while (len)
{
n = SockInternalRead(socket, buf, len);
@@ -158,6 +170,8 @@ int len;
if (sbuflen == 0) {
/* buffer is empty; refresh. */
if ((sbuflen = read(socket,sbuf,INTERNAL_BUFSIZE)) < 0) {
+ if (errno = EINTR)
+ return -1;
perror("SockInternalRead: read");
exit(9);
}