:: Re: [DNG] Custom OS initiator. In n…
Top Page
Delete this message
Reply to this message
Author: Irrwahn
Date:  
To: dng
Subject: Re: [DNG] Custom OS initiator. In need of some hints...
On Tue, 14 Jun 2016 09:33:59 +0200, Irrwahn Grausewitz wrote:

[Sorry for piggy-backing on my own post here.]

Just for the fun of it, here's a more elaborate discussion
of Felker's minimal init code:

> #define _XOPEN_SOURCE 700
> #include <signal.h>
> #include <unistd.h>


Add
#include <sys/wait.h>
here to satisfy the compiler's demand for a proper prototype
for the wait() function.

>
> int main()


Better make that
int main(void)
to be C standard compliant. Better safe than sorry.

> {
>     sigset_t set;
>     int status;


If we are not running as PID 1, do nothing and exit returning
an error code:

>     if (getpid() != 1) return 1;


Fill set, so it includes all signals known to the system.
Then block all the signals in the set:

>     sigfillset(&set);
>     sigprocmask(SIG_BLOCK, &set, 0);


Now Fork the process. If fork() returned non-zero, we're
either 1) in the parent process, or 2) fork() itself failed.
In either case we enter an endless loop with the only purpose
of waiting for potential child processes status changes (e.g.
termination), colloquially referred to as "reaping children":

>     if (fork()) for (;;) wait(&status);


This point in the code we only reach, if fork() returned
zero, which means we are now in the forked-off child process,
thus no longer PID1. We now unblock all signals, as we want
to be able to receive them:

>     sigprocmask(SIG_UNBLOCK, &set, 0);


Now create a new session and a new process group in that
session, and make our process (the first and currently only
child of PID1) the leader of both the session and the process
group:

>     setsid();


Set the process group ID to be the same as its process ID:

>     setpgid(0, 0);


Replace the current process image by the program "/etc/rc".
We (the only child of PID1) are now no longer the init
program, but effectively have become the rc program:

>     return execve("/etc/rc", (char *[]){ "rc", 0 }, (char *[]){ 0 });


NOTE: Execve only ever returns on error! So the return
statement itself should never be executed under normal
circumstances.

> }


CAVEAT: This minimal version is strictly speaking missing
some error checking. This is forgivable however, since
most of the errors theoretical possible this early in system
startup would indicate something is really, *really*, *REALLY*
wrong, and there's about nothing we could do about it. So
giving a hoot and go rambling on, in this case, is actually
a sensible decision. One could argue that in case fork() fails,
it would be reasonable to exit and thus let the kernel panic,
but that's merely a matter of taste and preference.

Regards
Urban