--- 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); }