summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordyson <dyson@FreeBSD.org>1997-04-20 20:17:04 +0000
committerdyson <dyson@FreeBSD.org>1997-04-20 20:17:04 +0000
commita0af1fc5d0140e3b5c2df713f76521a65c6aa8b1 (patch)
treeaf27ec2765d793331932a180cd9a980faf48f44d
parent37a353d4c88280e38725aae760a5c1ae9ccccd48 (diff)
downloadFreeBSD-src-a0af1fc5d0140e3b5c2df713f76521a65c6aa8b1.zip
FreeBSD-src-a0af1fc5d0140e3b5c2df713f76521a65c6aa8b1.tar.gz
Clean-up my modification of popen.c for vfork. Bruce's (this) is better.
Submitted by: Bruce Evans <bde@freebsd.org>
-rw-r--r--lib/libc/gen/popen.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/lib/libc/gen/popen.c b/lib/libc/gen/popen.c
index 520bca7..826ec93 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);
OpenPOWER on IntegriCloud