Quando esegui una pipe() tu crei 2 file, uno per l'input e uno per l'output.
Ora invocando la fork() crei una copia del processo e quindi il figlio ha la copia dei due file creati con la funzione pipe(), ora eseguendo una dup() redirigi i file come vuoi te ad esempio dup(pp[0]); redirige il file output del processo padre in quello del figlio.
Ora se esegui una execl() la funzione andrà a sovrascrivere il processo in uso che nel caso è il figlio, ora però questo processo mantiene gli I/O del processo chiamante e quindi se il figlio poteva ricevere l'input dal padre anche il processo caricato con execl potrà fare uguale.
Mi sembra che debba creare 3 processi, ovvero il padre creerà un figlio con il suo output che andrà a coincidere con l'input del figlio. Il figlio processa il messaggio e crea un nuovo processo ridirige I/O ed esegue la execl, questo perchè la execl sovrascrive il processo correte, quindi la riga sucessiva alla execl non verrà mai eseguita se non per errori durante la chiamata alla execl.
Per quello che per creare un nuovo processo n linux devi eseguire:
...
if ( 0 == fork() )
{
execl(......);
_exit(123);//questa riga viene eseguita solo in caso di errore della execl
}
...
Qui continua il padre.
Nel tuo caso potresti fare una cosa del genere:
...
int pp[2];
pipe(pp);
if ( 0 == fork() )
{
close(pp[1]); //il figlio non scrive al padre
dup2(0,pp[0]); // redirigo l'output del padre
int npp[2];
pipe(npp);
if ( 0 == fork() )
{
close(npp[1]); //il figliofiglio non scrive al figlio
dup2(0,npp[0]); // redirigo l'output del figlio
execl();//eseguo il processo
abort();
}
dup2(1,npp[1]); //l'output del figlio va al figliofiglio
char inp[80];
while (1)
{
fgets(inp,80,stdin);
if ( !strcmp(inp,"exit\n") ) return 0;
//processo il comando e lo reinvio al figlio figlio
printf("%s",inp);
}
}
dup2(1,pp[1]);// l'output del padre andrà al figlio.
close(pp[0]); il padre non prende l'input dal figlio
puts("comando");//invio i camndi al figlio che li processa e le reinvia al figliofioglio
...
puts("exit");//termino il figlio che in qualche modo terminerà il figliofiglio ad esempio con la kill
return 0;
Spero di aver capito bene, nel caso sia il padre a processare i comandi allora non avrai bisogno del figliofiglio ma solo del child.