Hola a todos.
Tengo que hacer un programa en c++ que ejecute cualquier nº de mandatos de la shell encadenados por tuberías. He conseguido hacerlo para una sola tubería, y para 2, pero cuando paso al caso general ('n' tuberías no consigo que funcione).
Os adjunto el código:
/**
Ejecuta los mandatos de la lista 'args' encadenados por tuberías.
'fd' vector de descriptores
inicial (se crea en el main y se le pasa a este metodo)
'i' número de iteraciones que llevo hechas. Con cada nuevo proceso
creado, se incrementa en 1.
'max' número de mandatos en el vector de argumentos ('args')
**/
int p1(char *args[],int fd[],int &i,const int &max){
//Voy a ejecutar un mandato, incremento i.
i++;
//Creo la tubería para el siguiente proceso.
pipe(fd);
//Creo el proceso
int pid=fork();
switch(pid){
case -1:
//si hay error....
exit(-1);
case 0:
//Soy el proceso hijo, lo que hago es:
//Creo otro vector de descriptores (para la tubería
//que mi hijo tendrá que heredar.
int fd2[2];
//Redirecciono mi salida estándar para que mi
//padre pueda leer la salida del mandato que voy
//a ejecutar
outRedir(fd);
//Si no soy el proceso que va a ejecutar el último mandato:
if(i<max){
//Repito lo anterior para crear mi tubería, mi proceso hijo etc.
p1(args,fd2,i,max);
//Si soy el proceso que va a ejecutar el último mandato:
}else{
//Ejecuto y salgo
execlp(args[max-1],args[max-1],NULL);
exit(0);
}
break;
default:
//Soy el proceso padre (pero era el hijo en la anterior llamada
//recursiva)
//Redirijo entrada
inRedir(fd2);
//ejecuto
execlp(args[i-1],args[i-1],NULL);
exit(0);
}
}
/**
Dado un vector de descriptores:
-Cierra el extremo de escritura
-Redirige stdin al extremo de lectura de la tuberia
-Stdin ya redireccionado, cierra el extremo de lectura
**/
void inRedir(int fd[]){
close(fd[1]);
dup2(fd[0],0);
close(fd[0]);
}
/**
Dado un vector de descriptores:
-Cierra el extremo de lectura
-Redirige extremo de escritura a stdout
-Stout ya redireccionado, cierra el extremo de escritura
**/
void outRedir(int fd[]){
close(fd[0]);
dup2(fd[1],1);
close(fd[1]);
}
Muchas gracias.
Hola de nuevo, he seguido intentándolo y creo que un problema era que en el fragmento de código del "default" uso 'fd2' cuando debería usar 'fd', esto es:
default:
//Soy el proceso padre (pero era el hijo en la anterior llamada
//recursiva)
//Redirijo entrada
inRedir(fd) //antes ponia esto ==== > inRedir(fd2);
//ejecuto
execlp(args[i-1],args[i-1],NULL);
exit(0);
Estoy ejecutando pasandole como mandatos ls, cat y wc para que haga: "ls | cat | wc". El error que me da es:
"wc: entrada estándar: Error de entrada/salida"
He segudido probando.
He cambiado el orden de los parámetros, en lugar de poner ls,cat y wc ahora pongo:
wc,cat y ls.
¿Me puede explicar alguien por qué pasa esto? No entiendo nada..
EDITO: lo he solucionado cambiando el execlp([i-1],[i-1],NULL) por
execlp([max-i],[max-i],NULL).
Sigo sin entender por qué pasa esto.
Ahora necesito ayuda para pasarlo de recursivo a iterativo, ¿alguien me puede ayudar? Gracias