1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
/*
* system.c
*
* The system() function. If this turns out to actually be *used*,
* we may want to try to detect the very simple cases (no shell magic)
* and handle them internally, instead of requiring that /bin/sh be
* present.
*/
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
int system(const char *string)
{
pid_t pid;
struct sigaction ignore, old_int, old_quit;
sigset_t masked, oldmask;
static const char *argv[] = { "/bin/sh", "-c", NULL, NULL };
int status;
/* Block SIGCHLD and ignore SIGINT and SIGQUIT */
/* Do this before the fork() to avoid races */
ignore.sa_handler = SIG_IGN;
sigemptyset(&ignore.sa_mask);
ignore.sa_flags = 0;
sigaction(SIGINT, &ignore, &old_int);
sigaction(SIGQUIT, &ignore, &old_quit);
sigemptyset(&masked);
sigaddset(&masked, SIGCHLD);
sigprocmask(SIG_BLOCK, &masked, &oldmask);
pid = fork();
if ( pid < 0 )
return -1;
else if ( pid == 0 ) {
sigaction(SIGINT, &old_int, NULL);
sigaction(SIGQUIT, &old_quit, NULL);
sigprocmask(SIG_SETMASK, &oldmask, NULL);
argv[2] = string;
execve(argv[0], (char * const *)argv, (char * const *)environ);
_exit(127);
}
/* else... */
waitpid(pid, &status, 0);
sigaction(SIGINT, &old_int, NULL);
sigaction(SIGQUIT, &old_quit, NULL);
sigprocmask(SIG_SETMASK, &oldmask, NULL);
return status;
}
|