aboutsummaryrefslogtreecommitdiffstats
path: root/sink.c
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2001-07-01 16:19:04 +0000
committerEric S. Raymond <esr@thyrsus.com>2001-07-01 16:19:04 +0000
commitd9a79d4bc51b408cd3de5161fa318c7140ef4369 (patch)
tree1b862f87497edd7d52104c5b45ee3adb191a80d6 /sink.c
parent52c4509bc72fd0627e3104e11e8750fbb1fc5b48 (diff)
downloadfetchmail-d9a79d4bc51b408cd3de5161fa318c7140ef4369.tar.gz
fetchmail-d9a79d4bc51b408cd3de5161fa318c7140ef4369.tar.bz2
fetchmail-d9a79d4bc51b408cd3de5161fa318c7140ef4369.zip
Fix for zombie problem.
svn path=/trunk/; revision=3387
Diffstat (limited to 'sink.c')
-rw-r--r--sink.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/sink.c b/sink.c
index 151554a9..3e55b89a 100644
--- a/sink.c
+++ b/sink.c
@@ -14,23 +14,35 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
+#include <signal.h>
+#include <time.h>
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif /* HAVE_MEMORY_H */
#if defined(STDC_HEADERS)
#include <stdlib.h>
#endif
#if defined(HAVE_UNISTD_H)
-#include <unistd.h>
+#include <unistd.h>
#endif
#if defined(HAVE_STDARG_H)
#include <stdarg.h>
#else
#include <varargs.h>
#endif
+#include <ctype.h>
+#include <time.h>
#include "fetchmail.h"
#include "socket.h"
#include "smtp.h"
#include "i18n.h"
+/* BSD portability hack...I know, this is an ugly place to put it */
+#if !defined(SIGCHLD) && defined(SIGCLD)
+#define SIGCHLD SIGCLD
+#endif
+
/* makes the open_sink()/close_sink() pair non-reentrant */
static int lmtp_responses;
@@ -164,6 +176,11 @@ int smtp_open(struct query *ctl)
/* these are shared by open_sink and stuffline */
static FILE *sinkfp;
+#ifndef HAVE_SIGACTION
+static RETSIGTYPE (*sigchld)(int);
+#else
+static struct sigaction sa_old;
+#endif /* HAVE_SIGACTION */
int stuffline(struct query *ctl, char *buf)
/* ship a line to the given control block's output sink (SMTP server or MDA) */
@@ -491,6 +508,9 @@ int open_sink(struct query *ctl, struct msgblk *msg,
/* set up sinkfp to be an input sink we can ship a message to */
{
struct idlist *idp;
+#ifdef HAVE_SIGACTION
+ struct sigaction sa_new;
+#endif /* HAVE_SIGACTION */
*bad_addresses = *good_addresses = 0;
@@ -915,6 +935,20 @@ int open_sink(struct query *ctl, struct msgblk *msg,
report(stderr, _("MDA open failed\n"));
return(PS_IOERR);
}
+
+ /*
+ * We need to disable the normal SIGCHLD handling here because
+ * sigchld_handler() would reap away the error status, returning
+ * error status instead of 0 for successful completion.
+ */
+#ifndef HAVE_SIGACTION
+ sigchld = signal(SIGCHLD, SIG_DFL);
+#else
+ memset (&sa_new, 0, sizeof sa_new);
+ sigemptyset (&sa_new.sa_mask);
+ sa_new.sa_handler = SIG_DFL;
+ sigaction (SIGCHLD, &sa_new, &sa_old);
+#endif /* HAVE_SIGACTION */
}
/*
@@ -938,6 +972,12 @@ void release_sink(struct query *ctl)
pclose(sinkfp);
sinkfp = (FILE *)NULL;
}
+#ifndef HAVE_SIGACTION
+ signal(SIGCHLD, sigchld);
+#else
+ sigaction (SIGCHLD, &sa_old, NULL);
+#endif /* HAVE_SIGACTION */
+ deal_with_sigchld();
}
}
@@ -956,6 +996,12 @@ int close_sink(struct query *ctl, struct msgblk *msg, flag forward)
}
else
rc = 0;
+#ifndef HAVE_SIGACTION
+ signal(SIGCHLD, sigchld);
+#else
+ sigaction (SIGCHLD, &sa_old, NULL);
+#endif /* HAVE_SIGACTION */
+ deal_with_sigchld();
if (rc)
{
report(stderr,