--------------------------------------------------------------------------------
Thoughts about different UNIX-IPC,
Nico Schottelius, 2005-04-28 (Last Modified: 2005-06-11)
--------------------------------------------------------------------------------

Howto cinit communicates with
   a) cinit-forks
   b) any other program

a) cinit-forks

a.1) shared memory

Access could generally be done with shared memory. The problem with
that is, that -lrt is required, which implicits -lpthread, which
makes linking staticly problematic (at least for glibc).

a.2) pipes

A maximum of ~510 pipes could be used ( (1024-3)/2 ),
1024 is the maximum opened file deskriptors,
minus 3 (stdin/stdout/stderr) already opened, divided
by two, because two fds needed per client.

Pipes cannot be used easily through forks of forks.

a.3) fifos

FIFOs are easy to use, but you would need to create two FIFOs
for _every_ service, as with only two FIFOs we cannot reliable
detect, _who_ is writting to us currently and who wants to read.

The same limit as above is true for fifo, too: A maximum of ~510
services.

a.4) system-v-ipc

No documentation found nor tested.

a.5) sockets

Are indeed a very clean way. There's only one problem:
bind() fails on read-only mounted devices:

   - The socket either does not exists and cannot be created
   - or the socket exists, but bind() refuses to reuse it
     (error: Address already in use)

Imho bind() should even honour the socket-option SO_REUSEADDR,
which allows to re-use a socket, if there's no other program bound to.

As far as I can see, SO_REUSEADDR is only honoured, if socket is of
type PF_INET (we use PF_UNIX) and POSIX does only specify how to
check for support, but not that sockets have to be able to use
SO_REUSEADDR (see posix.aardvark.bug.report).

That way, we are forced to mount a temporarily filesystem on
/etc/cinit/tmp and create the socket below this directory. This is not
the clean and easy solution one would wish. Still, sockets
seem to be the cleanest and most reliable way to have IPC for
this situation.

See socket(2), bind(2), listen(2), accept(2), socket(7) and unix(7)
for help.

b) any other program

What you can do is to tell cinit to
   - reboot,
   - halt,
   - poweroff,
   - update itself (hot-reboot)
   - and to start a rescue mode (see using.rescue).

Simple send cinit a signal, what to do:
   HUP: reboot
   USR1: halt
   USR2: rescue
   TERM: poweroff
   CONT: update

See signal(2) and signal(7) for help and serv/sig_reboot.c for implementation.
--------------------------------------------------------------------------------
