6 #include "stdio_impl.h"
9 extern char **__environ
;
11 FILE *popen(const char *cmd
, const char *mode
)
16 posix_spawn_file_actions_t fa
;
20 } else if (*mode
== 'w') {
27 if (pipe2(p
, O_CLOEXEC
)) return NULL
;
28 f
= fdopen(p
[op
], mode
);
30 __syscall(SYS_close
, p
[0]);
31 __syscall(SYS_close
, p
[1]);
36 /* If the child's end of the pipe happens to already be on the final
37 * fd number to which it will be assigned (either 0 or 1), it must
38 * be moved to a different fd. Otherwise, there is no safe way to
39 * remove the close-on-exec flag in the child without also creating
40 * a file descriptor leak race condition in the parent. */
41 if (p
[1-op
] == 1-op
) {
42 int tmp
= fcntl(1-op
, F_DUPFD_CLOEXEC
, 0);
47 __syscall(SYS_close
, p
[1-op
]);
52 if (!posix_spawn_file_actions_init(&fa
)) {
53 if (!posix_spawn_file_actions_adddup2(&fa
, p
[1-op
], 1-op
)) {
54 if (!(e
= posix_spawn(&pid
, "/bin/sh", &fa
, 0,
55 (char *[]){ "sh", "-c", (char *)cmd
, 0 }, __environ
))) {
56 posix_spawn_file_actions_destroy(&fa
);
58 if (!strchr(mode
, 'e'))
59 fcntl(p
[op
], F_SETFD
, 0);
60 __syscall(SYS_close
, p
[1-op
]);
65 posix_spawn_file_actions_destroy(&fa
);
69 __syscall(SYS_close
, p
[1-op
]);