diff options
author | dyson <dyson@FreeBSD.org> | 1997-04-16 03:26:50 +0000 |
---|---|---|
committer | dyson <dyson@FreeBSD.org> | 1997-04-16 03:26:50 +0000 |
commit | a07e70af85c12241e44d8305caf5a643bd30022c (patch) | |
tree | 144c75931ccceb59bf8a41b5afbbcc58a73e44bd /lib/libc/gen | |
parent | 94dc06fdd46cc83f93e272a25cb799f9b09cf623 (diff) | |
download | FreeBSD-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')
-rw-r--r-- | lib/libc/gen/popen.c | 17 |
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); |