1 #include "libc.h"
2 #include <errno.h>
3 #include <signal.h>
4 #include <spawn.h>
5 #include <stdlib.h>
6 #include <sys/wait.h>
7 #include <unistd.h>
8 
system(const char * cmd)9 int system(const char* cmd) {
10     pid_t pid;
11     sigset_t old, reset;
12     struct sigaction sa = {.sa_handler = SIG_IGN}, oldint, oldquit;
13     int status = 0x7f00, ret;
14     posix_spawnattr_t attr;
15 
16     if (!cmd)
17         return 1;
18 
19     sigaction(SIGINT, &sa, &oldint);
20     sigaction(SIGQUIT, &sa, &oldquit);
21     sigaddset(&sa.sa_mask, SIGCHLD);
22     sigprocmask(SIG_BLOCK, &sa.sa_mask, &old);
23 
24     sigemptyset(&reset);
25     if (oldint.sa_handler != SIG_IGN)
26         sigaddset(&reset, SIGINT);
27     if (oldquit.sa_handler != SIG_IGN)
28         sigaddset(&reset, SIGQUIT);
29     posix_spawnattr_init(&attr);
30     posix_spawnattr_setsigmask(&attr, &old);
31     posix_spawnattr_setsigdefault(&attr, &reset);
32     posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK);
33     ret = posix_spawn(&pid, "/bin/sh", 0, &attr, (char* []){(char*)"sh", (char*)"-c", (char*)cmd, 0}, __environ);
34     posix_spawnattr_destroy(&attr);
35 
36     if (!ret)
37         while (waitpid(pid, &status, 0) < 0 && errno == EINTR)
38             ;
39     sigaction(SIGINT, &oldint, NULL);
40     sigaction(SIGQUIT, &oldquit, NULL);
41     sigprocmask(SIG_SETMASK, &old, NULL);
42 
43     if (ret)
44         errno = ret;
45     return status;
46 }
47