Umm, I don't want to try and teach Mark or anyone else how to suck eggs or anything.

But I think we have a slight mis-understanding somewhere.

My understanding is that the exec family of functions do not return any return code - unless they fail (in which case the code after the exec* call is then executed, so any return code test is really unnecssary - in the normal case the code after the exec* call never gets run, in the exeption case, it does).

However, the normal method of starting a process is to call the fork() function first, which makes two identical copies of the running process.

The fork() call should return the PID of the new process to the caller (i.e. the kernel), and the child process get a 0 return value from the same fork call.
Thats how the two identical processes running the same identical code can work out which is which after the fork() call.
(fork() may need to replaced with kfork() when the parent process is the kernel, I don't know).

If the fork() call does not return the PID to the parent then I guess the parent has a problem in that it cannot identify the process ID of the new process just created (which then procedes to call execve(...) ), so it doesn't then know the PID to wait for until it exits.

The only way around that would be by using a shared resource (e.g. shared file descriptor) or something similar to allow the two process to conduct a private IPC conversation to allow the child process to indicate to the parent process, its Process ID (the parent can open open a regular file before the fork and ensure it stays open), then the child can (after the fork) move the shared file pointer via lseek to a integer offset that represents the PID of the child - which the parent can also request via a lseek call is one such not so elegant but effective way of doing this that I have used in the past).

The other question I have is how does the current kernel lauch the init process it does after boot?
And can we not use that code, wrapped up in a nice routine?