1 diff -rup /tmp/fetchmail-6.3.21//daemon.c ./daemon.c
2 --- /tmp/fetchmail-6.3.21//daemon.c 2011-08-21 15:34:58.000000000 +0200
3 +++ ./daemon.c 2012-02-19 21:10:16.200367846 +0100
9 -sigchld_handler (int sig)
10 -/* process SIGCHLD to obtain the exit code of the terminating process */
11 +int wait_for_child(pid_t who)
13 #if defined(HAVE_WAITPID) /* the POSIX way */
15 @@ -70,13 +68,23 @@ sigchld_handler (int sig)
19 - while ((pid = wait3(&status, WNOHANG, 0)) > 0)
20 + while ((pid = wait4(who, &status, WNOHANG, 0)) > 0)
21 continue; /* swallow 'em up. */
22 #else /* Zooks! Nothing to do but wait(), and hope we don't block... */
32 +sigchld_handler (int sig)
33 +/* process SIGCHLD to obtain the exit code of the terminating process */
40 diff -rup /tmp/fetchmail-6.3.21//fetchmail.c ./fetchmail.c
41 --- /tmp/fetchmail-6.3.21//fetchmail.c 2011-08-21 15:34:58.000000000 +0200
42 +++ ./fetchmail.c 2012-02-19 21:13:05.279377301 +0100
43 @@ -1393,11 +1393,24 @@ static RETSIGTYPE terminate_poll(int sig
44 #endif /* POP3_ENABLE */
47 +extern pid_t mda_pid;
49 static RETSIGTYPE terminate_run(int sig)
50 /* to be executed on normal or signal-induced termination */
55 + * kill explicitly the MDA process so that it dies *before* fetchmail
56 + * otherwise an uncomplete message might be delivered generating garbage
57 + * in the maildir/mailbox
59 + if( (sig == SIGINT || sig == SIGTERM ) && mda_pid != 0)
61 + report(stdout, GT_("killing MDA with PID %d\n"), mda_pid);
68 diff -rup /tmp/fetchmail-6.3.21//sink.c ./sink.c
69 --- /tmp/fetchmail-6.3.21//sink.c 2012-02-19 17:57:37.000000000 +0100
70 +++ ./sink.c 2012-02-19 21:11:07.518370716 +0100
71 @@ -632,6 +632,7 @@ static int handle_smtp_report_without_bo
73 /* these are shared by open_sink and stuffline */
77 int stuffline(struct query *ctl, char *buf)
78 /* ship a line to the given control block's output sink (SMTP server or MDA) */
79 @@ -1102,6 +1103,7 @@ static int open_mda_sink(struct query *c
81 int length = 0, fromlen = 0, nameslen = 0;
82 char *names = NULL, *before, *after, *from = NULL;
87 @@ -1219,7 +1221,7 @@ static int open_mda_sink(struct query *c
90 if (outlevel >= O_DEBUG)
91 - report(stdout, GT_("about to deliver with: %s\n"), before);
92 + report(stdout, GT_("about to deliver with: '%s'\n"), before);
96 @@ -1235,7 +1237,29 @@ static int open_mda_sink(struct query *c
98 #endif /* HAVE_SETEUID */
100 - sinkfp = popen(before, "w");
101 + if(pipe(mda_pipe) != 0) {
102 + report(stderr, GT_("Cannot create a pipe for the MDA: %s\n"), strerror(errno));
106 + /* save client's (MDA) PID in a global var for a clean shutdown in the fetchmail signal handler */
109 + report(stderr, GT_("Unable to fork for the MDA dispatching: %s\n"), strerror(errno));
112 + else if(mda_pid == 0) { /* child */
113 + /* close the write-end of the pipe connecting the stdin of the mda process to the read-end */
114 + close(mda_pipe[1]);
115 + dup2(mda_pipe[0], STDIN_FILENO);
117 + execl("/bin/sh", "sh", "-c", before, NULL);
118 + report(stderr, GT_("Unable to exec the MDA: %s\n"), strerror(errno));
122 + close(mda_pipe[0]);
123 + sinkfp = fdopen(mda_pipe[1], "w");
127 @@ -1249,6 +1273,7 @@ static int open_mda_sink(struct query *c
132 report(stderr, GT_("MDA open failed\n"));
135 @@ -1338,8 +1363,10 @@ void release_sink(struct query *ctl)
140 + fclose(sinkfp); // send EOF to the pipe
141 sinkfp = (FILE *)NULL;
142 + wait_for_child(mda_pid);
145 deal_with_sigchld(); /* Restore SIGCHLD handling to reap zombies */
147 @@ -1381,11 +1408,12 @@ int close_sink(struct query *ctl, struct
151 - if ((fflush(sinkfp)))
152 + if (fclose(sinkfp)) // send EOF to the pipe
156 - rc = pclose(sinkfp);
157 + rc = wait_for_child(mda_pid);
160 sinkfp = (FILE *)NULL;
162 @@ -1404,8 +1432,8 @@ int close_sink(struct query *ctl, struct
163 GT_("MDA returned nonzero status %d\n"), WEXITSTATUS(rc));
166 - GT_("Strange: MDA pclose returned %d and errno %d/%s, cannot handle at %s:%d\n"),
167 - rc, e, strerror(e), __FILE__, __LINE__);
168 + GT_("Unexpected error %d/%s waiting for MDA process, cannot handle at %s:%d\n"),
169 + e, strerror(e), __FILE__, __LINE__);