diff options
Diffstat (limited to '4init/4init.c')
| -rw-r--r-- | 4init/4init.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/4init/4init.c b/4init/4init.c new file mode 100644 index 0000000..50807b6 --- /dev/null +++ b/4init/4init.c @@ -0,0 +1,82 @@ +#define _POSIX_C_SOURCE 200809L + +#include <signal.h> +#include <stdio.h> +#include <sys/signalfd.h> +#include <sys/wait.h> +#include <unistd.h> + +#include "config.h" + +static void reap(void) +{ + int status; + while (waitpid(-1, &status, WNOHANG) > 0) {} +} + +int main(void) +{ + int sigfd = -1; + pid_t pid = -1; + sigset_t set; + + if (getpid() != 1) { + fprintf(stderr, "4init - you need to run this as PID 1...\n"); + return 1; + } + + sigfillset(&set); + sigdelset(&set, SIGILL); + sigdelset(&set, SIGTRAP); + sigdelset(&set, SIGBUS); + sigdelset(&set, SIGFPE); + sigdelset(&set, SIGSEGV); + + if (sigprocmask(SIG_SETMASK, &set, NULL) < 0) { + perror("sigprocmask"); + return 1; + } + + sigfd = signalfd(-1, &set, SFD_CLOEXEC); + if (sigfd < 0) { + perror("signalfd"); + return 1; + } + + pid = fork(); + if (pid < 0) { + perror("fork"); + return 1; + } + + if (pid == 0) { + sigset_t empty_set; + + sigemptyset(&empty_set); + sigprocmask(SIG_SETMASK, &empty_set, NULL); + + if (setsid() == -1) { + perror("setsid"); + } + + close(sigfd); + + execve(rc_path, rc_argv, rc_envp); + perror("execve"); + _exit(1); + } else { + struct signalfd_siginfo fdsi; + + reap(); + + for (;;) { + if (read(sigfd, &fdsi, sizeof(fdsi)) == sizeof(fdsi)) { + switch (fdsi.ssi_signo) { + case SIGCHLD: + reap(); + break; + } + } + } + } +} |
