X-Git-Url: http://nsz.repo.hu/git/?p=musl;a=blobdiff_plain;f=src%2Fprocess%2Fsystem.c;h=f5b7b492e64eb6a4fdcbe1ba6af6b8d89432c017;hp=ebe207f597f13edd3bba746115260b6894ce20c4;hb=3df0b66ee95c837496ae434ba7a2282d97ca71ef;hpb=599f97360389911c293e0ca4c5eb49e007377fba diff --git a/src/process/system.c b/src/process/system.c index ebe207f5..f5b7b492 100644 --- a/src/process/system.c +++ b/src/process/system.c @@ -2,64 +2,46 @@ #include #include #include +#include #include #include "pthread_impl.h" #include "libc.h" -static void dummy_0() -{ -} -weak_alias(dummy_0, __acquire_ptc); -weak_alias(dummy_0, __release_ptc); - -pid_t __vfork(void); +extern char **__environ; int system(const char *cmd) { pid_t pid; - sigset_t old; + sigset_t old, reset; struct sigaction sa = { .sa_handler = SIG_IGN }, oldint, oldquit; - int status = -1, i; + int status = 0x7f00, ret; + posix_spawnattr_t attr; + + pthread_testcancel(); if (!cmd) return 1; sigaction(SIGINT, &sa, &oldint); sigaction(SIGQUIT, &sa, &oldquit); - sigprocmask(SIG_BLOCK, SIGALL_SET, &old); - - __acquire_ptc(); - pid = __vfork(); - - if (pid) __release_ptc(); - - if (pid > 0) { - sigset_t new = old; - sigaddset(&new, SIGCHLD); - sigprocmask(SIG_BLOCK, &new, 0); - while (waitpid(pid, &status, 0) && errno == EINTR); - } - - if (pid) { - sigaction(SIGINT, &oldint, NULL); - sigaction(SIGQUIT, &oldquit, NULL); - sigprocmask(SIG_SETMASK, &old, NULL); - return status; - } - - /* Before we can unblock signals in the child, all signal - * handlers must be eliminated -- even implementation-internal - * ones. Otherwise, a signal handler could run in the child - * and clobber the parent's memory (due to vfork). */ - for (i=1; i<=8*__SYSCALL_SSLEN; i++) { - struct sigaction sa; - __libc_sigaction(i, 0, &sa); - if (sa.sa_handler!=SIG_IGN && sa.sa_handler!=SIG_DFL) { - sa.sa_handler = SIG_DFL; - __libc_sigaction(i, &sa, 0); - } - } - + sigaddset(&sa.sa_mask, SIGCHLD); + sigprocmask(SIG_BLOCK, &sa.sa_mask, &old); + + sigemptyset(&reset); + if (oldint.sa_handler != SIG_IGN) sigaddset(&reset, SIGINT); + if (oldquit.sa_handler != SIG_IGN) sigaddset(&reset, SIGQUIT); + posix_spawnattr_init(&attr); + posix_spawnattr_setsigmask(&attr, &old); + posix_spawnattr_setsigdefault(&attr, &reset); + posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGDEF|POSIX_SPAWN_SETSIGMASK); + ret = posix_spawn(&pid, "/bin/sh", 0, &attr, + (char *[]){"sh", "-c", (char *)cmd, 0}, __environ); + posix_spawnattr_destroy(&attr); + + if (!ret) while (waitpid(pid, &status, 0)<0 && errno == EINTR); + sigaction(SIGINT, &oldint, NULL); + sigaction(SIGQUIT, &oldquit, NULL); sigprocmask(SIG_SETMASK, &old, NULL); - execl("/bin/sh", "sh", "-c", cmd, (char *)0); - _exit(127); + + if (ret) errno = ret; + return status; }