Package: vacation
Version: 3.3.0
Severity: grave
Tags: patch

Vacation does not wait for its sendmail child to die in any way and exits!

Therefore accurate vacation parent (such as maildrop MDA) wipes forked
and executed sendmail before it could send any message...

Also multiple events that deserve it are not logged.

Patch for both flaws is attached.

-- 

\//\/\
(Sometimes credited as 1494 F8DD 6379 4CD7 E7E3 1FC9 D750 4243 1F05 9424.)

diff -U3 -r vacation-3.3.0-orig/vacation.c vacation-3.3.0/vacation.c
--- vacation-3.3.0-orig/vacation.c	2005-11-17 23:42:32.000000000 +0100
+++ vacation-3.3.0/vacation.c	2005-11-18 00:55:30.000000000 +0100
@@ -74,6 +74,9 @@
 #include <fcntl.h>
 #include <sys/param.h>
 #include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
 #ifdef HAVE_PATHS_H
 # include <paths.h>
 #else
@@ -232,7 +235,7 @@
 	}
 	if (msgfilename[0] != '/' || dbfilename[0] != '/')
 		if (chdir(pw->pw_dir)) {
-			msglog(LOG_ERR, "no such directory %s.\n", pw->pw_dir);
+			msglog(LOG_ERR, "error changing to directory %s: %s\n", pw->pw_dir, strerror(errno));
 			exit(1);
 		}
 
@@ -505,8 +508,8 @@
 void sendmessage(const char *myname, const char *msgfile)
 {
 	FILE *mfp, *sfp;
-	int i;
-	int pvect[2];
+	pid_t pid, wpid;
+	int pvect[2], wstatus;
 	char buf[MAXLINE];
 
 	mfp = fopen(msgfile, "r");
@@ -518,12 +521,12 @@
 		msglog(LOG_ERR, "pipe: %m");
 		exit(1);
 	}
-	i = fork();
-	if (i < 0) {
+	pid = fork();
+	if (pid < 0) {
 		msglog(LOG_ERR, "fork: %m");
 		exit(1);
 	}
-	if (i == 0) {
+	if (pid == 0) {
 		dup2(pvect[0], 0);
 		close(pvect[0]);
 		close(pvect[1]);
@@ -534,6 +537,7 @@
 		exit(1);
 	}
 	close(pvect[0]);
+
 	sfp = fdopen(pvect[1], "w");
 	fprintf(sfp, "To: %s\n", from);
 	while (fgets(buf, sizeof buf, mfp)) {
@@ -547,8 +551,31 @@
 			fputs(buf, sfp);
 		}
 	}
+
+	if (ferror(mfp)) {
+		msglog(LOG_ERR, "error reading file %s: %s\n", msgfile, strerror(errno));
+	} else if (ferror(sfp)) {
+		msglog(LOG_ERR, "error piping message to %s[%d]: %s\n", _PATH_SENDMAIL, pid, strerror(errno));
+	} else {
+		msglog(LOG_INFO, "response message passed to %s[%d].\n", _PATH_SENDMAIL, pid);
+	}
+
 	fclose(mfp);
 	fclose(sfp);
+
+	do {
+		wpid = waitpid(pid, &wstatus, 0);
+	} while (wpid == -1 && errno == EINTR);
+
+	if (wpid == -1) {
+		msglog(LOG_ERR, "error waiting for death of child %s[%d]: %s\n", _PATH_SENDMAIL, pid, strerror(errno));
+	} else if (WIFEXITED(wstatus)) {
+		if (WEXITSTATUS(wstatus) != 0) {
+			msglog(LOG_ERR, "process %s[%d] exited with return code %d\n", _PATH_SENDMAIL, pid, WEXITSTATUS(wstatus));
+		}
+	} else if (WIFSIGNALED(wstatus)) {
+		msglog(LOG_ERR, "process %s[%d] died with signal %d\n", _PATH_SENDMAIL, pid, WTERMSIG(wstatus));
+	}
 }
 
 void usage(void)

Reply via email to