clean up sloppy nested inclusion from pthread_impl.h
[musl] / src / stdio / popen.c
1 #include <fcntl.h>
2 #include <unistd.h>
3 #include <errno.h>
4 #include <string.h>
5 #include "stdio_impl.h"
6 #include "pthread_impl.h"
7 #include "syscall.h"
8
9 static void dummy_0()
10 {
11 }
12 weak_alias(dummy_0, __acquire_ptc);
13 weak_alias(dummy_0, __release_ptc);
14
15 pid_t __vfork(void);
16
17 FILE *popen(const char *cmd, const char *mode)
18 {
19         int p[2], op, i;
20         pid_t pid;
21         FILE *f;
22         sigset_t old;
23         const char *modes = "rw", *mi = strchr(modes, *mode);
24
25         if (mi) {
26                 op = mi-modes;
27         } else {
28                 errno = EINVAL;
29                 return 0;
30         }
31         
32         if (pipe2(p, O_CLOEXEC)) return NULL;
33         f = fdopen(p[op], mode);
34         if (!f) {
35                 __syscall(SYS_close, p[0]);
36                 __syscall(SYS_close, p[1]);
37                 return NULL;
38         }
39
40         sigprocmask(SIG_BLOCK, SIGALL_SET, &old);
41         
42         __acquire_ptc();
43         pid = __vfork();
44
45         if (pid) {
46                 __release_ptc();
47                 __syscall(SYS_close, p[1-op]);
48                 sigprocmask(SIG_SETMASK, &old, 0);
49                 if (pid < 0) {
50                         fclose(f);
51                         return 0;
52                 }
53                 f->pipe_pid = pid;
54                 return f;
55         }
56
57         /* See notes in system.c for why this is needed. */
58         for (i=1; i<=8*__SYSCALL_SSLEN; i++) {
59                 struct sigaction sa;
60                 __libc_sigaction(i, 0, &sa);
61                 if (sa.sa_handler!=SIG_IGN && sa.sa_handler!=SIG_DFL) {
62                         sa.sa_handler = SIG_DFL;
63                         __libc_sigaction(i, &sa, 0);
64                 }
65         }
66         if (dup2(p[1-op], 1-op) < 0) _exit(127);
67         fcntl(1-op, F_SETFD, 0);
68         if (p[0] != 1-op) __syscall(SYS_close, p[0]);
69         if (p[1] != 1-op) __syscall(SYS_close, p[1]);
70         sigprocmask(SIG_SETMASK, &old, 0);
71         execl("/bin/sh", "sh", "-c", cmd, (char *)0);
72         _exit(127);
73 }