popen.c.patch   [plain text]


--- popen.c.orig	2003-05-20 15:21:02.000000000 -0700
+++ popen.c	2005-09-14 15:53:35.000000000 -0700
@@ -43,7 +43,8 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/pop
 #include "namespace.h"
 #include <sys/param.h>
 #include <sys/wait.h>
-
+#include <sys/socket.h>
+#include <wchar.h>		/* fwide() */
 #include <signal.h>
 #include <errno.h>
 #include <unistd.h>
@@ -55,11 +56,14 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/pop
 #include "un-namespace.h"
 #include "libc_private.h"
 
-extern char **environ;
+#include <crt_externs.h>
+#define environ (*_NSGetEnviron())
 
+/* 3516149 - store file descriptor and use that to close to prevent blocking */
 static struct pid {
 	struct pid *next;
 	FILE *fp;
+	int fd;
 	pid_t pid;
 } *pidlist;
 static pthread_mutex_t pidlist_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -77,20 +81,24 @@ popen(command, type)
 	char *argv[4];
 	struct pid *p;
 
-	/*
-	 * Lite2 introduced two-way popen() pipes using _socketpair().
-	 * FreeBSD's pipe() is bidirectional, so we use that.
-	 */
-	if (strchr(type, '+')) {
+	if (type == NULL) {
+		errno = EINVAL;
+		return (NULL);
+	}
+	if (strcmp(type, "r+") == 0) {
 		twoway = 1;
 		type = "r+";
+		if (socketpair(AF_UNIX, SOCK_STREAM, 0, pdes) < 0)
+			return (NULL);
 	} else  {
 		twoway = 0;
-		if ((*type != 'r' && *type != 'w') || type[1])
+		if ((*type != 'r' && *type != 'w') || type[1]) {
+			errno = EINVAL;
 			return (NULL);
 	}
 	if (pipe(pdes) < 0)
 		return (NULL);
+	}
 
 	if ((cur = malloc(sizeof(struct pid))) == NULL) {
 		(void)_close(pdes[0]);
@@ -104,7 +112,7 @@ popen(command, type)
 	argv[3] = NULL;
 
 	THREAD_LOCK();
-	switch (pid = vfork()) {
+	switch (pid = fork()) {
 	case -1:			/* Error. */
 		THREAD_UNLOCK();
 		(void)_close(pdes[0]);
@@ -138,7 +146,7 @@ popen(command, type)
 			(void)_close(pdes[1]);
 		}
 		for (p = pidlist; p; p = p->next) {
-			(void)_close(fileno(p->fp));
+			(void)_close(p->fd);
 		}
 		_execve(_PATH_BSHELL, argv, environ);
 		_exit(127);
@@ -149,9 +157,11 @@ popen(command, type)
 	/* Parent; assume fdopen can't fail. */
 	if (*type == 'r') {
 		iop = fdopen(pdes[0], type);
+		cur->fd = pdes[0];
 		(void)_close(pdes[1]);
 	} else {
 		iop = fdopen(pdes[1], type);
+		cur->fd = pdes[1];
 		(void)_close(pdes[0]);
 	}
 
@@ -162,7 +172,7 @@ popen(command, type)
 	cur->next = pidlist;
 	pidlist = cur;
 	THREAD_UNLOCK();
-
+	fwide(iop, -1);		/* byte stream */
 	return (iop);
 }