1251877Speter#include <unistd.h>
2251877Speter#include <stdlib.h>
3251877Speter#include <signal.h>
4251877Speter#include <sys/wait.h>
5251877Speter#include <spawn.h>
6251877Speter#include <errno.h>
7251877Speter#include "pthread_impl.h"
8251877Speter#include "libc.h"
9251877Speter
10251877Speterextern char **__environ;
11251877Speter
12251877Speterint system(const char *cmd)
13251877Speter{
14251877Speter	pid_t pid;
15251877Speter	sigset_t old, reset;
16251877Speter	struct sigaction sa = { .sa_handler = SIG_IGN }, oldint, oldquit;
17251877Speter	int status = 0x7f00, ret;
18251877Speter	posix_spawnattr_t attr;
19251877Speter
20251877Speter	pthread_testcancel();
21251877Speter
22251877Speter	if (!cmd) return 1;
23251877Speter
24251877Speter	sigaction(SIGINT, &sa, &oldint);
25251877Speter	sigaction(SIGQUIT, &sa, &oldquit);
26251877Speter	sigaddset(&sa.sa_mask, SIGCHLD);
27251877Speter	sigprocmask(SIG_BLOCK, &sa.sa_mask, &old);
28251877Speter
29251877Speter	sigemptyset(&reset);
30251877Speter	if (oldint.sa_handler != SIG_IGN) sigaddset(&reset, SIGINT);
31251877Speter	if (oldquit.sa_handler != SIG_IGN) sigaddset(&reset, SIGQUIT);
32251877Speter	posix_spawnattr_init(&attr);
33251877Speter	posix_spawnattr_setsigmask(&attr, &old);
34251877Speter	posix_spawnattr_setsigdefault(&attr, &reset);
35251877Speter	posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGDEF|POSIX_SPAWN_SETSIGMASK);
36251877Speter	ret = posix_spawn(&pid, "/bin/sh", 0, &attr,
37251877Speter		(char *[]){"sh", "-c", (char *)cmd, 0}, __environ);
38251877Speter	posix_spawnattr_destroy(&attr);
39251877Speter
40251877Speter	if (!ret) while (waitpid(pid, &status, 0)<0 && errno == EINTR);
41251877Speter	sigaction(SIGINT, &oldint, NULL);
42251877Speter	sigaction(SIGQUIT, &oldquit, NULL);
43251877Speter	sigprocmask(SIG_SETMASK, &old, NULL);
44251877Speter
45251877Speter	if (ret) errno = ret;
46251877Speter	return status;
47251877Speter}
48251877Speter