You're going to have to call pipe() once for each "link" between the processes.
Either do it all beforehand :
Code:
pipes = malloc(2 * sizeof(int) * (num_processes-1))
for (i = 0; i < 2*(num_processes-1); i+=2)
pipe(pipes + i);
pipes[n] would be the read pipe, pipes[n+1] would be the write pipe for each even n value. Each process is only going to write to one pipe and read from another - the rest it should close. Kind of a pain to keep track of, but closest to what your first example is doing.
or each time you fork off another process :
Code:
int pipes[2];
while (1)
{
pipe(pipes);
fork();
if (child)
{
dup() read pipe
close unused pipe
if no more children to create, exec()
}
else if parent
{
dup() write pipe
close unused pipe
exec()
}
}
This is just the basic 2-process case wrapped in a loop. It's also untested pseudo-code, but hopefully it's close to accurate.
The main thing to keep in mind is that each call to pipe() is going to ignore and overwrite what was in the arguments when you passed them in. Copy them to local vars or use dup()/dup2() before calling pipe() if you need to save the results of the previous pipe() call.