]> git.saurik.com Git - apple/libc.git/blobdiff - gen/FreeBSD/popen.c.patch
Libc-825.24.tar.gz
[apple/libc.git] / gen / FreeBSD / popen.c.patch
diff --git a/gen/FreeBSD/popen.c.patch b/gen/FreeBSD/popen.c.patch
deleted file mode 100644 (file)
index e58f314..0000000
+++ /dev/null
@@ -1,255 +0,0 @@
---- 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.
-  */
-+#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>
- #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;
-       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;
-       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) {
-               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 (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) {
-               (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)
--                      (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. */
-       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]);
-       }
-@@ -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 */