diff options
| author | John Dyson <dyson@FreeBSD.org> | 1997-04-20 20:17:04 +0000 |
|---|---|---|
| committer | John Dyson <dyson@FreeBSD.org> | 1997-04-20 20:17:04 +0000 |
| commit | 5ae9116a7d7889483ed1fe8d54bcff6b11bdf6f8 (patch) | |
| tree | ab8588b48c93ad319d0be9557ff2d1344e263123 /lib/libc/gen/popen.c | |
| parent | fd48862f47715bc8122725309c4a7b5f009474e8 (diff) | |
Notes
Diffstat (limited to 'lib/libc/gen/popen.c')
| -rw-r--r-- | lib/libc/gen/popen.c | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/lib/libc/gen/popen.c b/lib/libc/gen/popen.c index 520bca772e9e..826ec93d9f53 100644 --- a/lib/libc/gen/popen.c +++ b/lib/libc/gen/popen.c @@ -94,18 +94,20 @@ popen(command, type) case 0: /* Child. */ if (*type == 'r') { /* - * We must NOT modify pdes, due to the - * semantics of vfork. + * 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. */ - 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 && (tpdes1 != STDIN_FILENO)) - (void)dup2(tpdes1, STDIN_FILENO); + if (pdes[1] != STDOUT_FILENO) { + (void)dup2(pdes[1], STDOUT_FILENO); + (void)close(pdes[1]); + (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); |
