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