/* unchristened custom init by Pegasus Epsilon <pegasus@pimpninjas.org> */
#include <unistd.h> /* fork(), exec(), getuid() */
#include <sys/types.h> /* wait(), getuid() */
#include <sys/wait.h> /* wait() */
#include <sys/prctl.h> /* prctl() */
#include <stdlib.h> /* exit() */
#include <stdarg.h> /* va_list, va_start(), vprintf(), va_end() */
#include <stdio.h> /* vprintf(), putchar(), fflush(), perror() */
#include <errno.h> /* errno */
#include <string.h> /* strcpy() */
/* specify your stage2 here */
#define STAGE2 "/sbin/stage2"
/* if we fail to start the above, then we start the below instead. */
#define SHELL "/bin/sh"
#define MYNAME "init"
/* possible names:
* big bang
* prime mover
* minute disturbance
* quantum foam
* ...
*/
/* let us create a puts/printf hybrid */
void say (const char *restrict const fmt, ...) {
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
putchar('\n');
fflush(stdout);
va_end(args);
}
int spawn (const char *path, char *const name) {
if (fork()) {
int status;
if (0 > wait(&status) && ECHILD != errno) perror(name);
return status;
} else {
execl(path, name, NULL);
perror(name); /* on success, "%s: Success\n" is printed. */
exit(0);
}
}
int main (int argc, char **argv) {
(void)(argc); /* stfu gcc */
/* we care about being root */
if (getuid()) {
say("must be superuser");
exit(0);
}
/* we don't care about being PID1 - it's a silly thing to check
* either we are PID1 and we will reap processes, or something
* is misconfigured - but that's not our problem.
*/
if (fork()) { /* parent - become death */
int status;
strcpy(argv[0], "death");
prctl(PR_SET_NAME, argv[0]);
/* by default, SIGCHLD is set to SIG_IGN
* this means that wait() should wait for all
* children to terminate and then fail with ECHILD
*/
while (0 < wait(&status));
if (ECHILD != errno) perror(MYNAME);
else say("%s exiting", MYNAME);
} else { /* child - become life */
strcpy(argv[0], "life");
prctl(PR_SET_NAME, argv[0]);
/* since we are the child, our parent above
* will not terminate until we do.
* infinite loop means we should not terminate
* until something kills us
*/
for (;;) {
spawn(STAGE2, "stage2");
spawn(SHELL, "rescue");
}
}
}