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