summaryrefslogtreecommitdiffstats
path: root/lib/libc/gen/popen.c
diff options
context:
space:
mode:
authordyson <dyson@FreeBSD.org>1997-04-16 03:26:50 +0000
committerdyson <dyson@FreeBSD.org>1997-04-16 03:26:50 +0000
commita07e70af85c12241e44d8305caf5a643bd30022c (patch)
tree144c75931ccceb59bf8a41b5afbbcc58a73e44bd /lib/libc/gen/popen.c
parent94dc06fdd46cc83f93e272a25cb799f9b09cf623 (diff)
downloadFreeBSD-src-a07e70af85c12241e44d8305caf5a643bd30022c.zip
FreeBSD-src-a07e70af85c12241e44d8305caf5a643bd30022c.tar.gz
Fix the problem in popen that makes correct vfork semantics fail.
Specifically, popen modifies a variable "pdes[1]" in the child in such a way that it breaks code in the parent (due to the address space sharing.)
Diffstat (limited to 'lib/libc/gen/popen.c')
-rw-r--r--lib/libc/gen/popen.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/lib/libc/gen/popen.c b/lib/libc/gen/popen.c
index f76f9e5..520bca7 100644
--- a/lib/libc/gen/popen.c
+++ b/lib/libc/gen/popen.c
@@ -93,14 +93,19 @@ popen(command, type)
/* NOTREACHED */
case 0: /* Child. */
if (*type == 'r') {
- if (pdes[1] != STDOUT_FILENO) {
- (void)dup2(pdes[1], STDOUT_FILENO);
- (void)close(pdes[1]);
- pdes[1] = STDOUT_FILENO;
+ /*
+ * We must NOT modify pdes, due to the
+ * semantics of vfork.
+ */
+ int tpdes1 = pdes[1];
+ if (tpdes1 != STDOUT_FILENO) {
+ (void)dup2(tpdes1, STDOUT_FILENO);
+ (void)close(tpdes1);
+ tpdes1 = STDOUT_FILENO;
}
(void) close(pdes[0]);
- if (twoway && (pdes[1] != STDIN_FILENO))
- (void)dup2(pdes[1], STDIN_FILENO);
+ if (twoway && (tpdes1 != STDIN_FILENO))
+ (void)dup2(tpdes1, STDIN_FILENO);
} else {
if (pdes[0] != STDIN_FILENO) {
(void)dup2(pdes[0], STDIN_FILENO);
OpenPOWER on IntegriCloud