xref: /haiku/src/system/libroot/posix/unistd/system.cpp (revision 6f80a9801fedbe7355c4360bd204ba746ec3ec2d)
1 /*
2  * Copyright 2004-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include <image.h>
7 
8 #include <errno.h>
9 #include <pthread.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/wait.h>
13 #include <unistd.h>
14 
15 #include <errno_private.h>
16 #include <syscall_utils.h>
17 
18 
19 extern "C" int
20 system(const char *command)
21 {
22 	if (!command)
23 		return 1;
24 
25 	const char *argv[] = { "/bin/sh", "-c", command, NULL };
26 	int argc = 3;
27 
28 	thread_id thread = load_image(argc, argv, (const char **)environ);
29 	if (thread < 0)
30 		RETURN_AND_SET_ERRNO_TEST_CANCEL(thread);
31 
32 	// block SIGCHLD ...
33 	sigset_t mask, oldMask;
34 	sigemptyset(&mask);
35 	sigaddset(&mask, SIGCHLD);
36 	sigprocmask(SIG_BLOCK, &mask, &oldMask);
37 
38 	// and ignore SIGINT and SIGQUIT while waiting for completion
39 	struct sigaction intSave, quitSave, sa;
40 	memset(&sa, 0, sizeof(sa));
41 	sigemptyset(&sa.sa_mask);
42 	sa.sa_handler = SIG_IGN;
43 	sigaction(SIGINT, &sa, &intSave);
44 	sigaction(SIGQUIT, &sa, &quitSave);
45 
46 	resume_thread(thread);
47 
48 	int exitStatus;
49 	pid_t result;
50 	while ((result = waitpid(thread, &exitStatus, 0)) < 0
51 		&& errno == B_INTERRUPTED) {
52 		// waitpid() was interrupted by a signal, retry...
53 	}
54 
55 	// unblock and reset signal handlers
56 	sigprocmask(SIG_SETMASK, &oldMask, NULL);
57 	sigaction(SIGINT, &intSave, NULL);
58 	sigaction(SIGQUIT, &quitSave, NULL);
59 
60 	if (result < 0)
61 		return -1;
62 
63 	return exitStatus;
64 }
65