aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fetchmail.c84
-rw-r--r--fetchmail.h1
-rw-r--r--uid.c18
3 files changed, 61 insertions, 42 deletions
diff --git a/fetchmail.c b/fetchmail.c
index 570238b1..fc8490fb 100644
--- a/fetchmail.c
+++ b/fetchmail.c
@@ -80,12 +80,14 @@ int requestlen = 0;
#endif /* NET_SECURITY */
static char *lockfile; /* name of lockfile */
+static int lock_acquired; /* have we acquired a lock */
static int querystatus; /* status of query */
static int successes; /* count number of successful polls */
static struct runctl cmd_run; /* global options set from command line */
static time_t parsetime; /* time of last parse */
-static void termhook(int); /* forward declaration of exit hook */
+static void terminate_run(int);
+static void terminate_poll(int);
#ifdef SLEEP_WITH_ALARM
/*
@@ -122,7 +124,7 @@ static void unlockit(void)
#endif
/* must-do actions for exit (but we can't count on being able to do malloc) */
{
- if (lockfile[0])
+ if (lockfile && lock_acquired)
unlink(lockfile);
}
@@ -443,7 +445,9 @@ int main(int argc, char **argv)
else if (argc > 1)
{
/* this test enables re-execing on a changed rcfile */
- if (getpid() != pid)
+ if (getpid() == pid)
+ lock_acquired = TRUE;
+ else
{
fprintf(stderr,
_("fetchmail: can't accept options while a background fetchmail is running.\n"));
@@ -518,7 +522,7 @@ int main(int argc, char **argv)
if (run.poll_interval)
{
if (!nodetach)
- daemonize(run.logfile, termhook);
+ daemonize(run.logfile, terminate_run);
report(stdout, _("starting fetchmail %s daemon \n"), VERSION);
/*
@@ -536,12 +540,12 @@ int main(int argc, char **argv)
/* beyond here we don't want more than one fetchmail running per user */
umask(0077);
- signal(SIGABRT, termhook);
- signal(SIGINT, termhook);
- signal(SIGTERM, termhook);
- signal(SIGALRM, termhook);
- signal(SIGPIPE, termhook);
- signal(SIGQUIT, termhook);
+ signal(SIGABRT, terminate_run);
+ signal(SIGINT, terminate_run);
+ signal(SIGTERM, terminate_run);
+ signal(SIGALRM, terminate_run);
+ signal(SIGPIPE, terminate_run);
+ signal(SIGQUIT, terminate_run);
/* here's the exclusion lock */
if ((st = open(lockfile, O_WRONLY | O_CREAT | O_EXCL, 0666)) != -1) {
@@ -553,6 +557,7 @@ int main(int argc, char **argv)
write(st, tmpbuf, strlen(tmpbuf));
}
close(st);
+ lock_acquired = TRUE;
}
/*
@@ -628,11 +633,7 @@ int main(int argc, char **argv)
#ifdef POP3_ENABLE
if (!check_only)
- {
- write_saved_lists(querylist, run.idfile);
- if (outlevel >= O_DEBUG)
- report(stdout, _("saved UID lists\n"));
- }
+ uid_end_query(ctl);
#endif /* POP3_ENABLE */
if (querystatus == PS_SUCCESS)
@@ -660,21 +661,8 @@ int main(int argc, char **argv)
endhostent(); /* release TCP/IP connection to nameserver */
#endif /* HAVE_RES_SEARCH */
- /*
- * Close all SMTP delivery sockets. For optimum performance
- * we'd like to hold them open til end of run, but (1) this
- * loses if our poll interval is longer than the MTA's inactivity
- * timeout, and (2) some MTAs (like smail) don't deliver after
- * each message, but rather queue up mail and wait to actually
- * deliver it until the input socket is closed.
- */
- for (ctl = querylist; ctl; ctl = ctl->next)
- if (ctl->smtp_socket != -1)
- {
- SMTP_quit(ctl->smtp_socket);
- close(ctl->smtp_socket);
- ctl->smtp_socket = -1;
- }
+ /* close connections cleanly */
+ terminate_poll(0);
/*
* OK, we've polled. Now sleep.
@@ -828,7 +816,7 @@ int main(int argc, char **argv)
report(stdout, _("normal termination, status %d\n"),
successes ? PS_SUCCESS : querystatus);
- termhook(0);
+ terminate_run(0);
exit(successes ? PS_SUCCESS : querystatus);
}
@@ -1275,12 +1263,17 @@ static int load_params(int argc, char **argv, int optind)
return(implicitmode);
}
-static void termhook(int sig)
-/* to be executed on normal or signal-induced termination */
+static void terminate_poll(int sig)
+/* to be executed at the nd of a poll cycle */
{
- struct query *ctl;
-
/*
+ * Close all SMTP delivery sockets. For optimum performance
+ * we'd like to hold them open til end of run, but (1) this
+ * loses if our poll interval is longer than the MTA's inactivity
+ * timeout, and (2) some MTAs (like smail) don't deliver after
+ * each message, but rather queue up mail and wait to actually
+ * deliver it until the input socket is closed.
+ *
* Sending SMTP QUIT on signal is theoretically nice, but led to a
* subtle bug. If fetchmail was terminated by signal while it was
* shipping message text, it would hang forever waiting for a
@@ -1293,15 +1286,36 @@ static void termhook(int sig)
if (sig != 0)
report(stdout, _("terminated with signal %d\n"), sig);
else
+ {
+ struct query *ctl;
+
/* terminate all SMTP connections cleanly */
for (ctl = querylist; ctl; ctl = ctl->next)
if (ctl->smtp_socket != -1)
+ {
SMTP_quit(ctl->smtp_socket);
+ close(ctl->smtp_socket);
+ ctl->smtp_socket = -1;
+ }
+ }
#ifdef POP3_ENABLE
+ /*
+ * Update UID information at end of each poll, rather than at end
+ * of run, because that way we don't lose all UIDL information since
+ * the beginning of time if fetchmail crashes.
+ */
if (!check_only)
write_saved_lists(querylist, run.idfile);
#endif /* POP3_ENABLE */
+}
+
+static void terminate_run(int sig)
+/* to be executed on normal or signal-induced termination */
+{
+ struct query *ctl;
+
+ terminate_poll(sig);
/*
* Craig Metz, the RFC1938 one-time-password guy, points out:
diff --git a/fetchmail.h b/fetchmail.h
index c98c18ea..0e19d7cb 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -433,6 +433,7 @@ char *str_find(struct idlist **, int);
char *idpair_find(struct idlist **, const char *);
void append_str_list(struct idlist **, struct idlist **);
void expunge_uids(struct query *);
+void uid_expunge_query(struct query *);
void write_saved_lists(struct query *, const char *);
/* rcfile_y.y */
diff --git a/uid.c b/uid.c
index 6bf4bf10..9a132606 100644
--- a/uid.c
+++ b/uid.c
@@ -368,14 +368,9 @@ void expunge_uids(struct query *ctl)
idl->val.status.mark = UID_EXPUNGED;
}
-void write_saved_lists(struct query *hostlist, const char *idfile)
-/* perform end-of-run write of seen-messages list */
+void uid_end_query(struct query *ctl)
+/* finish a query */
{
- int idcount;
- FILE *tmpfp;
- struct query *ctl;
- struct idlist *idp;
-
/* old state of mailbox is now irrelevant */
free_str_list(&ctl->oldsaved);
free_str_list(&scratchlist);
@@ -394,6 +389,15 @@ void write_saved_lists(struct query *hostlist, const char *idfile)
report_build(stdout, " <empty>");
report_complete(stdout, "\n");
}
+}
+
+void write_saved_lists(struct query *hostlist, const char *idfile)
+/* perform end-of-run write of seen-messages list */
+{
+ int idcount;
+ FILE *tmpfp;
+ struct query *ctl;
+ struct idlist *idp;
/* if all lists are empty, nuke the file */
idcount = 0;