Si, esto sería un pequeño shell de una práctica de la facultad donde se utiliza esto:
Esto crea tantos hijos como ordenes hay, y luego cada hijo hace hace un exec para cambiarse por el programa que realmente nos interesa poner en su lugar.
Esto se plantea como que el shell crea 2 hijos cuando tu le pides ejecutar "ls -la | grep root"
el primer hijo se hace un exec a "ls -la" y el segundo a "grep root"
for(i=0;i<nordenes;i++){
forkpid=fork();
if(forkpid==0){
redirigir_entrada(i);
redirigir_salida(i);
cerrar_fd();
if(-1==execvp(ordenes[i],args[i]))
}
else if(forkpid==-1){
return ERROR;
}
else{
}
}
cerrar_fd();
Pero antes de ese código se preparan los canales de esta forma:
cmdfd es una estructura que contiene dos enteros, infd y outfd.
for(i=0;i<ncmd-1;i++){
pipe(fds);
cmdfd[i].outfd=fds[1];
cmdfd[i+1].infd=fds[0];
}
Para las órdenes que haya, se crean n-1 tuberias.
(revisa la referencia de pipe y dup2)
y redirigir la entrada o salida sería esto:
int redirigir_entrada(int i){
if(cmdfd[i].infd!=0){ //evitar redirigir la entrada estándar sobre si misma, perdida de tiempo.
if(-1!=dup2(cmdfd[i].infd,0))
return OK;
return ERROR;
}
return OK;
}
int redirigir_salida(int i){
if(cmdfd[i].outfd!=1){ //evitar redirigir la salida estándar sobre si misma, perdida de tiempo
if(-1!=dup2(cmdfd[i].outfd,1))
return OK;
return ERROR;
}
return OK;
}
int cerrar_fd(){
int i;
for(i=3;i<=nds+2;i++){ //nds +2 es el numero del último descriptor de fichero activo.
close(i);
}
return OK;
}
Posiblemente encuentres por ahí un código más claro, pero lo básico es:
Preparar canales
Crear hijos
Cerrar canales del padre si no se tiene que comunicar con los hijos
Que los hijos se redirijan las entradas / salidas y cerrar los descriptores sobrantes
A correr.
EDIT: editados los comentarios del código.