remove no-longer-needed special case handling in popen
[musl] / src / stdio / popen.c
1 #include <fcntl.h>
2 #include <unistd.h>
3 #include <errno.h>
4 #include <string.h>
5 #include <spawn.h>
6 #include "stdio_impl.h"
7 #include "syscall.h"
8
9 extern char **__environ;
10
11 FILE *popen(const char *cmd, const char *mode)
12 {
13         int p[2], op, e;
14         pid_t pid;
15         FILE *f;
16         posix_spawn_file_actions_t fa;
17
18         if (*mode == 'r') {
19                 op = 0;
20         } else if (*mode == 'w') {
21                 op = 1;
22         } else {
23                 errno = EINVAL;
24                 return 0;
25         }
26         
27         if (pipe2(p, O_CLOEXEC)) return NULL;
28         f = fdopen(p[op], mode);
29         if (!f) {
30                 __syscall(SYS_close, p[0]);
31                 __syscall(SYS_close, p[1]);
32                 return NULL;
33         }
34         FLOCK(f);
35
36         e = ENOMEM;
37         if (!posix_spawn_file_actions_init(&fa)) {
38                 if (!posix_spawn_file_actions_adddup2(&fa, p[1-op], 1-op)) {
39                         if (!(e = posix_spawn(&pid, "/bin/sh", &fa, 0,
40                             (char *[]){ "sh", "-c", (char *)cmd, 0 }, __environ))) {
41                                 posix_spawn_file_actions_destroy(&fa);
42                                 f->pipe_pid = pid;
43                                 if (!strchr(mode, 'e'))
44                                         fcntl(p[op], F_SETFD, 0);
45                                 __syscall(SYS_close, p[1-op]);
46                                 FUNLOCK(f);
47                                 return f;
48                         }
49                 }
50                 posix_spawn_file_actions_destroy(&fa);
51         }
52         fclose(f);
53         __syscall(SYS_close, p[1-op]);
54
55         errno = e;
56         return 0;
57 }