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