it seems the only two distros that haven't adopted it as the default yet are Slackware and Gentoo
There is a debian fork called Devuan. The reason for the fork was the decision to use systemd instead of a sane init. (via heise.de)
While searching that, I found http://without-systemd.org/. You may guess what content is hosted there. ;.-)
Update:
From there, I followed a link to
A history of modern init systems featuring a really compact init implementation in less than 100 lines:
# MIT license.
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define LEN(x) (sizeof (x) / sizeof *(x))
static void sigpoweroff(void);
static void sigreap(void);
static void sigreboot(void);
static void spawn(char *const []);
static struct {
int sig;
void (*handler)(void);
} sigmap[] = {
{ SIGUSR1, sigpoweroff },
{ SIGCHLD, sigreap },
{ SIGINT, sigreboot },
};
static char *const rcinitcmd[] = { "/bin/rc.init", NULL };
static char *const rcrebootcmd[] = { "/bin/rc.shutdown", "reboot", N
+ULL };
static char *const rcpoweroffcmd[] = { "/bin/rc.shutdown", "poweroff",
+ NULL };
static sigset_t set;
int
main(void)
{
int sig;
size_t i;
if (getpid() != 1)
return 1;
chdir("/");
sigfillset(&set);
sigprocmask(SIG_BLOCK, &set, NULL);
spawn(rcinitcmd);
while (1) {
sigwait(&set, &sig);
for (i = 0; i < LEN(sigmap); i++) {
if (sigmap[i].sig == sig) {
sigmap[i].handler();
break;
}
}
}
/* not reachable */
return 0;
}
static void
sigpoweroff(void)
{
spawn(rcpoweroffcmd);
}
static void
sigreap(void)
{
while (waitpid(-1, NULL, WNOHANG) > 0)
;
}
static void
sigreboot(void)
{
spawn(rcrebootcmd);
}
static void
spawn(char *const argv[])
{
pid_t pid;
pid = fork();
if (pid < 0) {
perror("fork");
} else if (pid == 0) {
sigprocmask(SIG_UNBLOCK, &set, NULL);
setsid();
execvp(argv[0], argv);
perror("execvp");
_exit(1);
}
}
I think it looks quite good, there are only two things I'm missing here:
- Sanitising of the output: This init relies on the kernel to provide a sane set of stdin, stdout, stderr. Technically, setting up the standard handles could be done in rc.init and rc.shutdown, but errors this init wants to report via perror() are written to whatever the kernel has set up as handle 2. Compare with busybox init: It calls console_init() and set_sane_term() as first actions.
- Handling for all kernel signals. Keyboard request (usually mapped to Alt+UpArrow) results in a SIGWINCH signal sent to init. Easy to add to the sigmap[] variable, add a new handler that starts yet another program.
rc.shutdown is started by two signals, you have to look at the command line parameters to get the difference. I would have prefered one program per signal. For the reboot and shutdown signals, I could either use two different tiny scripts that would execute the same shutdown script with the two command lines, or I could just symlink one to the other and use argv[0] to decide what to do.
Everything else could be done by other programs, as explained in the second part of Re^14: CPAN failed install.
Alexander
--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)