diff dbutil.c @ 484:effb4a25b1ae

Don't capture stderr from spawned processes in proxycommand mode
author Matt Johnston <matt@ucc.asn.au>
date Wed, 17 Sep 2008 14:35:36 +0000
parents 7ad49f34a122
children d59f628e7baa
line wrap: on
line diff
--- a/dbutil.c	Mon Sep 15 14:40:30 2008 +0000
+++ b/dbutil.c	Wed Sep 17 14:35:36 2008 +0000
@@ -146,7 +146,7 @@
 	}
 
 	va_start(param, format);
-	fprintf(stderr, "TRACE: ");
+	fprintf(stderr, "TRACE (%d): ", getpid());
 	vfprintf(stderr, format, param);
 	fprintf(stderr, "\n");
 	va_end(param);
@@ -391,7 +391,9 @@
 
 /* Sets up a pipe for a, returning three non-blocking file descriptors
  * and the pid. exec_fn is the function that will actually execute the child process,
- * it will be run after the child has fork()ed, and is passed exec_data. */
+ * it will be run after the child has fork()ed, and is passed exec_data.
+ * If ret_errfd == NULL then stderr will not be captured.
+ * ret_pid can be passed as  NULL to discard the pid. */
 int spawn_command(void(*exec_fn)(void *user_data), void *exec_data,
 		int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) {
 	int infds[2];
@@ -403,12 +405,15 @@
 	const int FDOUT = 1;
 
 	/* redirect stdin/stdout/stderr */
-	if (pipe(infds) != 0)
+	if (pipe(infds) != 0) {
+		return DROPBEAR_FAILURE;
+	}
+	if (pipe(outfds) != 0) {
 		return DROPBEAR_FAILURE;
-	if (pipe(outfds) != 0)
+	}
+	if (ret_errfd && pipe(errfds) != 0) {
 		return DROPBEAR_FAILURE;
-	if (pipe(errfds) != 0)
-		return DROPBEAR_FAILURE;
+	}
 
 #ifdef __uClinux__
 	pid = vfork();
@@ -416,8 +421,9 @@
 	pid = fork();
 #endif
 
-	if (pid < 0)
+	if (pid < 0) {
 		return DROPBEAR_FAILURE;
+	}
 
 	if (!pid) {
 		/* child */
@@ -432,7 +438,7 @@
 
 		if ((dup2(infds[FDIN], STDIN_FILENO) < 0) ||
 			(dup2(outfds[FDOUT], STDOUT_FILENO) < 0) ||
-			(dup2(errfds[FDOUT], STDERR_FILENO) < 0)) {
+			(ret_errfd && dup2(errfds[FDOUT], STDERR_FILENO) < 0)) {
 			TRACE(("leave noptycommand: error redirecting FDs"))
 			dropbear_exit("child dup2() failure");
 		}
@@ -441,8 +447,11 @@
 		close(infds[FDIN]);
 		close(outfds[FDIN]);
 		close(outfds[FDOUT]);
-		close(errfds[FDIN]);
-		close(errfds[FDOUT]);
+		if (ret_errfd)
+		{
+			close(errfds[FDIN]);
+			close(errfds[FDOUT]);
+		}
 
 		exec_fn(exec_data);
 		/* not reached */
@@ -451,16 +460,24 @@
 		/* parent */
 		close(infds[FDIN]);
 		close(outfds[FDOUT]);
-		close(errfds[FDOUT]);
 
-		setnonblocking(errfds[FDIN]);
 		setnonblocking(outfds[FDIN]);
 		setnonblocking(infds[FDOUT]);
 
-		*ret_pid = pid;
+		if (ret_errfd) {
+			close(errfds[FDOUT]);
+			setnonblocking(errfds[FDIN]);
+		}
+
+		if (ret_pid) {
+			*ret_pid = pid;
+		}
+
 		*ret_writefd = infds[FDOUT];
 		*ret_readfd = outfds[FDIN];
-		*ret_errfd = errfds[FDIN];
+		if (ret_errfd) {
+			*ret_errfd = errfds[FDIN];
+		}
 		return DROPBEAR_SUCCESS;
 	}
 }