Loading...
gen/FreeBSD/popen.c.patch Libc-763.13 Libc-391.2.9
--- Libc/Libc-763.13/gen/FreeBSD/popen.c.patch
+++ Libc/Libc-391.2.9/gen/FreeBSD/popen.c.patch
@@ -1,255 +1,72 @@
---- popen.c.orig	2009-12-02 15:21:37.000000000 -0800
-+++ popen.c	2009-12-02 15:36:51.000000000 -0800
-@@ -30,6 +30,10 @@
-  * SUCH DAMAGE.
-  */
+--- popen.c.orig	Mon May 24 23:50:41 2004
++++ popen.c	Tue May 25 00:09:39 2004
+@@ -43,6 +43,7 @@
+ #include "namespace.h"
+ #include <sys/param.h>
+ #include <sys/wait.h>
++#include <sys/socket.h>
  
-+#ifdef VARIANT_DARWINEXTSN
-+#define _DARWIN_UNLIMITED_STREAMS
-+#endif /* VARIANT_DARWINEXTSN */
-+
- #if defined(LIBC_SCCS) && !defined(lint)
- static char sccsid[] = "@(#)popen.c	8.3 (Berkeley) 5/3/95";
- #endif /* LIBC_SCCS and not lint */
-@@ -40,7 +44,8 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/pop
- #include <sys/param.h>
- #include <sys/queue.h>
- #include <sys/wait.h>
--
-+#include <sys/socket.h>
-+#include <wchar.h>		/* fwide() */
  #include <signal.h>
  #include <errno.h>
- #include <unistd.h>
-@@ -49,18 +54,39 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/pop
- #include <string.h>
- #include <paths.h>
- #include <pthread.h>
-+#include <spawn.h>
+@@ -55,11 +56,14 @@
  #include "un-namespace.h"
  #include "libc_private.h"
  
 -extern char **environ;
 +#include <crt_externs.h>
 +#define environ (*_NSGetEnviron())
-+
-+/* Our queue.h doesn't have SLIST_REMOVE_AFTER in it yet
-+ * <rdar://problem/7431558> API: Add SLIST_REMOVE_AFTER to sys/queue.h (from FreeBSD)
-+ */
-+#ifndef SLIST_REMOVE_AFTER
-+#define SLIST_REMOVE_AFTER(elm, field) do {                             \
-+        SLIST_NEXT(elm, field) =                                        \
-+            SLIST_NEXT(SLIST_NEXT(elm, field), field);                  \
-+} while (0)
-+#endif
  
 +/* 3516149 - store file descriptor and use that to close to prevent blocking */
- struct pid {
- 	SLIST_ENTRY(pid) next;
+ static struct pid {
+ 	struct pid *next;
  	FILE *fp;
 +	int fd;
  	pid_t pid;
- };
--static SLIST_HEAD(, pid) pidlist = SLIST_HEAD_INITIALIZER(pidlist);
--static pthread_mutex_t pidlist_mutex = PTHREAD_MUTEX_INITIALIZER;
-+#define pidlist		__popen_pidlist
-+#define pidlist_mutex	__popen_pidlist_mutex
-+#ifndef BUILDING_VARIANT
-+__private_extern__ SLIST_HEAD(, pid) pidlist = SLIST_HEAD_INITIALIZER(pidlist);
-+__private_extern__ pthread_mutex_t pidlist_mutex = PTHREAD_MUTEX_INITIALIZER;
-+#else /* BUILDING_VARIANT */
-+extern SLIST_HEAD(, pid) pidlist;
-+extern pthread_mutex_t pidlist_mutex;
-+#endif /* !BUILDING_VARIANT */
- 
- #define	THREAD_LOCK()	if (__isthreaded) _pthread_mutex_lock(&pidlist_mutex)
- #define	THREAD_UNLOCK()	if (__isthreaded) _pthread_mutex_unlock(&pidlist_mutex)
-@@ -71,84 +97,108 @@ popen(command, type)
- {
- 	struct pid *cur;
- 	FILE *iop;
--	int pdes[2], pid, twoway;
-+	int pdes[2], pid, twoway, other;
+ } *pidlist;
+ static pthread_mutex_t pidlist_mutex = PTHREAD_MUTEX_INITIALIZER;
+@@ -77,20 +81,18 @@
  	char *argv[4];
  	struct pid *p;
-+	posix_spawn_file_actions_t file_actions;
-+	int err;
  
 -	/*
 -	 * 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) {
+ 	if (strchr(type, '+')) {
  		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;
+ 		if ((*type != 'r' && *type != 'w') || type[1])
+ 			return (NULL);
++		if (pipe(pdes) < 0)
 +			return (NULL);
-+		}
-+		if (pipe(pdes) < 0)
- 			return (NULL);
  	}
 -	if (pipe(pdes) < 0)
 -		return (NULL);
  
--	if ((cur = malloc(sizeof(struct pid))) == NULL) {
-+	/* fdopen can now fail */
-+	if (*type == 'r') {
-+		iop = fdopen(pdes[0], type);
-+		other = pdes[1];
-+	} else {
-+		iop = fdopen(pdes[1], type);
-+		other = pdes[0];
-+	}
-+	if (iop == NULL) {
+ 	if ((cur = malloc(sizeof(struct pid))) == NULL) {
  		(void)_close(pdes[0]);
- 		(void)_close(pdes[1]);
- 		return (NULL);
- 	}
- 
-+	if ((cur = malloc(sizeof(struct pid))) == NULL) {
-+		(void)fclose(iop);
-+		(void)_close(other);
-+		return (NULL);
-+	}
-+
-+	if ((err = posix_spawn_file_actions_init(&file_actions)) != 0) {
-+		(void)fclose(iop);
-+		(void)_close(other);
-+		free(cur);
-+		errno = err;
-+		return (NULL);
-+	}
-+	if (*type == 'r') {
-+		/*
-+		 * The dup2() to STDIN_FILENO is repeated to avoid
-+		 * writing to pdes[1], which might corrupt the
-+		 * parent's copy.  This isn't good enough in
-+		 * general, since the _exit() is no return, so
-+		 * the compiler is free to corrupt all the local
-+		 * variables.
-+		 */
-+		(void)posix_spawn_file_actions_addclose(&file_actions, pdes[0]);
-+		if (pdes[1] != STDOUT_FILENO) {
-+			(void)posix_spawn_file_actions_adddup2(&file_actions, pdes[1], STDOUT_FILENO);
-+			(void)posix_spawn_file_actions_addclose(&file_actions, pdes[1]);
-+			if (twoway)
-+				(void)posix_spawn_file_actions_adddup2(&file_actions, STDOUT_FILENO, STDIN_FILENO);
-+		} else if (twoway && (pdes[1] != STDIN_FILENO))
-+			(void)posix_spawn_file_actions_adddup2(&file_actions, pdes[1], STDIN_FILENO);
-+	} else {
-+		if (pdes[0] != STDIN_FILENO) {
-+			(void)posix_spawn_file_actions_adddup2(&file_actions, pdes[0], STDIN_FILENO);
-+			(void)posix_spawn_file_actions_addclose(&file_actions, pdes[0]);
-+		}
-+		(void)posix_spawn_file_actions_addclose(&file_actions, pdes[1]);
-+	}
-+	SLIST_FOREACH(p, &pidlist, next)
-+		(void)posix_spawn_file_actions_addclose(&file_actions, p->fd);
-+
- 	argv[0] = "sh";
- 	argv[1] = "-c";
- 	argv[2] = (char *)command;
- 	argv[3] = NULL;
- 
--	THREAD_LOCK();
--	switch (pid = vfork()) {
--	case -1:			/* Error. */
--		THREAD_UNLOCK();
--		(void)_close(pdes[0]);
--		(void)_close(pdes[1]);
-+	err = posix_spawn(&pid, _PATH_BSHELL, &file_actions, NULL, argv, environ);
-+	posix_spawn_file_actions_destroy(&file_actions);
-+
-+	if (err == ENOMEM || err == EAGAIN) { /* as if fork failed */
-+		(void)fclose(iop);
-+		(void)_close(other);
- 		free(cur);
-+		errno = err;
- 		return (NULL);
--		/* NOTREACHED */
--	case 0:				/* Child. */
--		if (*type == 'r') {
--			/*
--			 * The _dup2() to STDIN_FILENO is repeated to avoid
--			 * writing to pdes[1], which might corrupt the
--			 * parent's copy.  This isn't good enough in
--			 * general, since the _exit() is no return, so
--			 * the compiler is free to corrupt all the local
--			 * variables.
--			 */
--			(void)_close(pdes[0]);
--			if (pdes[1] != STDOUT_FILENO) {
--				(void)_dup2(pdes[1], STDOUT_FILENO);
--				(void)_close(pdes[1]);
--				if (twoway)
--					(void)_dup2(STDOUT_FILENO, STDIN_FILENO);
--			} else if (twoway && (pdes[1] != STDIN_FILENO))
--				(void)_dup2(pdes[1], STDIN_FILENO);
--		} else {
--			if (pdes[0] != STDIN_FILENO) {
--				(void)_dup2(pdes[0], STDIN_FILENO);
--				(void)_close(pdes[0]);
--			}
--			(void)_close(pdes[1]);
--		}
--		SLIST_FOREACH(p, &pidlist, next)
+@@ -138,7 +140,7 @@
+ 			(void)_close(pdes[1]);
+ 		}
+ 		for (p = pidlist; p; p = p->next) {
 -			(void)_close(fileno(p->fp));
--		_execve(_PATH_BSHELL, argv, environ);
--		_exit(127);
--		/* NOTREACHED */
-+	} else if (err != 0) { /* couldn't exec the shell */
-+		pid = -1;
- 	}
--	THREAD_UNLOCK();
- 
--	/* Parent; assume fdopen can't fail. */
++			(void)_close(p->fd);
+ 		}
+ 		_execve(_PATH_BSHELL, argv, environ);
+ 		_exit(127);
+@@ -149,9 +151,11 @@
+ 	/* Parent; assume fdopen can't fail. */
  	if (*type == 'r') {
--		iop = fdopen(pdes[0], type);
+ 		iop = fdopen(pdes[0], type);
 +		cur->fd = pdes[0];
  		(void)_close(pdes[1]);
  	} else {
--		iop = fdopen(pdes[1], type);
+ 		iop = fdopen(pdes[1], type);
 +		cur->fd = pdes[1];
  		(void)_close(pdes[0]);
  	}
  
-@@ -158,10 +208,11 @@ popen(command, type)
- 	THREAD_LOCK();
- 	SLIST_INSERT_HEAD(&pidlist, cur, next);
- 	THREAD_UNLOCK();
--
-+	fwide(iop, -1);		/* byte stream */
- 	return (iop);
- }
- 
-+#ifndef BUILDING_VARIANT
- /*
-  * pclose --
-  *	Pclose returns -1 if stream is not associated with a `popened' command,
-@@ -196,6 +247,10 @@ pclose(iop)
- 
- 	(void)fclose(iop);
- 
-+	if (cur->pid < 0) {
-+		free(cur);
-+		return W_EXITCODE(127, 0);
-+	}
- 	do {
- 		pid = _wait4(cur->pid, &pstat, 0, (struct rusage *)0);
- 	} while (pid == -1 && errno == EINTR);
-@@ -204,3 +259,4 @@ pclose(iop)
- 
- 	return (pid == -1 ? -1 : pstat);
- }
-+#endif /* !BUILDING_VARIANT */