1 #define _GNU_SOURCE
2 #include "fdop.h"
3 #include "libc.h"
4 #include "threads_impl.h"
5 #include <fcntl.h>
6 #include <sched.h>
7 #include <spawn.h>
8 #include <sys/wait.h>
9 #include <unistd.h>
10
11 struct args {
12 int p[2];
13 sigset_t oldmask;
14 const char* path;
15 int (*exec)(const char*, char* const*, char* const*);
16 const posix_spawn_file_actions_t* fa;
17 const posix_spawnattr_t* restrict attr;
18 char *const *argv, *const *envp;
19 };
20
__posix_spawnx(pid_t * restrict res,const char * restrict path,int (* exec)(const char *,char * const *,char * const *),const posix_spawn_file_actions_t * fa,const posix_spawnattr_t * restrict attr,char * const argv[restrict],char * const envp[restrict])21 int __posix_spawnx(pid_t* restrict res, const char* restrict path,
22 int (*exec)(const char*, char* const*, char* const*),
23 const posix_spawn_file_actions_t* fa, const posix_spawnattr_t* restrict attr,
24 char* const argv[restrict], char* const envp[restrict]) {
25 pid_t pid;
26 int ec = 0;
27 struct args args;
28
29 if (pipe2(args.p, O_CLOEXEC))
30 return errno;
31
32 args.path = path;
33 args.exec = exec;
34 args.fa = fa;
35 args.attr = attr ? attr : &(const posix_spawnattr_t){};
36 args.argv = argv;
37 args.envp = envp;
38 pthread_sigmask(SIG_BLOCK, SIGALL_SET, &args.oldmask);
39
40 // TODO(kulakowski) Launchpad up a process here.
41 pid = -ENOSYS;
42 close(args.p[1]);
43
44 if (pid > 0) {
45 if (read(args.p[0], &ec, sizeof ec) != sizeof ec)
46 ec = 0;
47 else
48 waitpid(pid, &(int){0}, 0);
49 } else {
50 ec = -pid;
51 }
52
53 close(args.p[0]);
54
55 if (!ec && res)
56 *res = pid;
57
58 pthread_sigmask(SIG_SETMASK, &args.oldmask, 0);
59
60 return ec;
61 }
62
posix_spawn(pid_t * restrict res,const char * restrict path,const posix_spawn_file_actions_t * fa,const posix_spawnattr_t * restrict attr,char * const argv[restrict],char * const envp[restrict])63 int posix_spawn(pid_t* restrict res, const char* restrict path,
64 const posix_spawn_file_actions_t* fa, const posix_spawnattr_t* restrict attr,
65 char* const argv[restrict], char* const envp[restrict]) {
66 return __posix_spawnx(res, path, execve, fa, attr, argv, envp);
67 }
68