X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/59e0d9fe772464b93d835d2a2964457702469a43..51282358e8fdbfc483c0c34e7eae9b89b51f2570:/gen/FreeBSD/popen.c.patch?ds=sidebyside diff --git a/gen/FreeBSD/popen.c.patch b/gen/FreeBSD/popen.c.patch index e0ce5b8..f4467ff 100644 --- a/gen/FreeBSD/popen.c.patch +++ b/gen/FreeBSD/popen.c.patch @@ -1,14 +1,31 @@ ---- popen.c.orig Mon May 24 23:50:41 2004 -+++ popen.c Tue May 25 00:09:39 2004 -@@ -43,6 +43,7 @@ +--- popen.c.orig 2009-03-03 02:04:57.000000000 -0800 ++++ popen.c 2009-03-03 15:28:31.000000000 -0800 +@@ -34,6 +34,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 */ +@@ -43,7 +47,8 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/pop #include "namespace.h" #include #include +- +#include - ++#include /* fwide() */ #include #include -@@ -55,11 +56,14 @@ + #include +@@ -52,17 +57,29 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/pop + #include + #include + #include ++#include #include "un-namespace.h" #include "libc_private.h" @@ -16,57 +33,216 @@ +#include +#define environ (*_NSGetEnviron()) +-static struct pid { +/* 3516149 - store file descriptor and use that to close to prevent blocking */ - static struct pid { ++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,18 @@ +-} *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__ struct pid *pidlist = NULL; ++__private_extern__ pthread_mutex_t pidlist_mutex = PTHREAD_MUTEX_INITIALIZER; ++#else /* BUILDING_VARIANT */ ++extern struct 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) +@@ -73,85 +90,109 @@ 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 (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]) - return (NULL); -+ if (pipe(pdes) < 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) { +- 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]); -@@ -138,7 +140,7 @@ - (void)_close(pdes[1]); - } - for (p = pidlist; p; p = p->next) { + (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]); ++ } ++ for (p = pidlist; p; p = p->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]); +- } +- 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 +151,11 @@ - /* Parent; assume fdopen can't fail. */ +- } +- _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); +- 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]); } +@@ -162,10 +203,11 @@ popen(command, type) + cur->next = pidlist; + pidlist = cur; + 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, +@@ -198,6 +240,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); +@@ -206,3 +252,4 @@ pclose(iop) + + return (pid == -1 ? -1 : pstat); + } ++#endif /* !BUILDING_VARIANT */