summaryrefslogtreecommitdiff
path: root/4init/4init.c
diff options
context:
space:
mode:
Diffstat (limited to '4init/4init.c')
-rw-r--r--4init/4init.c82
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;
+ }
+ }
+ }
+ }
+}