[C con Clase] problema con pipes

KdeFuego kdefuego en gmail.com
Dom Jun 3 19:14:36 CEST 2007


Hola, he recurrido a ustedes porque aun no puedo solucionar un problema que tengo con el manejo de pipes, espero puedan ayudarme.
La idea del programa es implementar la comunicacion entre 4 procesos usando pipes...
Los cuatro procesos posibles son encriptar, desencriptar, comprimir y descomprimir.
Los archivos binarios del encriptador y desencriptador se pueden descargar del siguiente enlace: http://eibi.utalca.cl/~ajendrex/KdeFuego/SSOO/
estos para ejecutarse leen por defecto de la entrada estandar, y necesitan como primer parametro una clave (cualquier palabra)...

En el código se hacen todos los correspondientes cierres para que
el segundo pipe funcione; este es implementado para cuando hay mas de un comando para ejecutar, que en este caso hay n+1 (siendo n la cantidad de comandos que quiere ejecutar el usuario, y 1 por el cat que ejecuta nuestro programa para dar de entrada al primer pipe el contenido del archivo que nos entregaria eventualmente el usuario(por favor crear el archivo.txt para pruebas).
El primer pipe funciona de maravilla, osea, cuando el usuario quiere realizar
solo una acción, no se tienen problemas (siempre que la entrada sea la adecuada, para desencriptar y descomprimir).
El problema nace cuando se ejecuta el proceso hijo, el cual esta implementado
dentro de un ciclo for, esto para ejecutar los i-1 procesos que desee el usuario
(-1 porque el padre ejecutará el ultimo).
En el código que se envia se pide ejecutar el encriptador y el compresor, el
asunto es que (al parecer)  el encriptador no está leyendo desde la tuberia,
porque se queda esperando infinitamente su entrada, siendo que la tubería tiene
el contenido del archivo.txt...

en fin, el codigo debería funcionar y no funciona...
Espero tengan la gran sugerencia que necesito para que esto funcione. Gracias de antemano.


#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>

int main()
{
	char nombre_archivo[30] = {"prueba.txt"};
        char comandos[20] = {"ec"};
	char clave[10] = {"clave"};

	int salida = open("salida.txt", O_WRONLY);
	
	int Nprocesos = strlen(comandos);
	int i, status, lectura, escritura;

	int fd[2][2];
	pid_t pid;

	if(pipe(fd[0]) < 0)
	{
		perror("Error al crear la tuberia");
		exit(0);
	}
	if(pipe(fd[1]) < 0)
	{
		perror("Error al crear la tuberia");
		exit(0);
	}

	pid = fork();

	if(pid == -1)
	{
		perror("Error en el fork -1");
		exit(0);
	}
	
	if(!pid)
	{
		close(fd[0][0]);
		close(STDOUT_FILENO);
		dup(fd[0][1]);
		close(fd[0][1]);
		execlp("cat", "cat", nombre_archivo, NULL);/*entrada a la tuberia, lo que este en el archivo dado por el usuario*/
	}

	while(wait(&status) != pid);
	for(i = 0; i < Nprocesos - 1; i++)
	{
		pid = fork();
		if(pid == -1)
		{
			perror("Error en el fork");
			exit(0);
		}
		if(!pid) /* Caso del proceso hijo */
		{

			lectura = i%2;
			escritura = (i+1)%2;

			close(fd[lectura][1]);
			close(STDIN_FILENO);
			dup(fd[lectura][0]);
			close(fd[lectura][0]);

                	close(fd[escritura][0]);
			close(STDOUT_FILENO);
			dup(fd[escritura][1]);
			close(fd[escritura][1]);
			
			if(comandos[i] == 'e')/*va a encriptar*/
			{				
				execlp("./encriptador", "./encriptador", clave, NULL); 
			}else
			{
				if(comandos[i] == 'd')/*va a desencriptar*/
				{
				execlp("./desencriptador", "./desencriptador", clave, NULL); 
				}else
				{
					if(comandos[i] == 'c')/*va a comprimir*/
					{
						execlp("gzip", "gzip", "-f", NULL); 
					}else if(comandos[i] == 'u');/*va a descomprimir*/
					{
						execlp("zcat", "zcat", NULL); 			
					}
				}
			}

				perror("error en el exec\n");
				exit(0);
		}
		while(wait(&status) != pid);/*el padre ejecutará el último comando*/
	}
		lectura = i%2;
		escritura = (i+1)%2;		

		close(fd[escritura][0]);
		close(fd[escritura][1]);

		close(fd[lectura][1]);
		close(STDIN_FILENO);
		dup(fd[lectura][0]);
		close(fd[lectura][0]);

			if(comandos[i] == 'e')
			{
				execlp("./encriptador", "./encriptador", clave, NULL); 
			}else
			{
				if(comandos[i] == 'd')
				{				
				execlp("./desencriptador", "./desencriptador", clave, NULL); 
				}else
				{
					if(comandos[i] == 'c')
					{
						execlp("gzip", "gzip", "-f", NULL); 
					}else if(comandos[i] == 'u')
					{
						execlp("zcat", "zcat", NULL); 			
					}
				}
			}
}




Más información sobre la lista de distribución Cconclase