Hi,
Im trying to do a simple program which fork. The parent process sends data to the child process via a pipe and collect data from the child via an other pipe.
The child process redirect the input and output and call execvp with the command specified by the user when he run the program (argv[]).
My program work well with basic commands like ls or echo but is stuck somewhere when i use commands that needs basic interaction with the user like tr a-z A-Z.
I also use poll() in the parent process to monitor between stdin and what the child process send but I don't think this is the problem. I think it's more about a broken pipe or a write that block.
I spent all day looking all over the internet looking for a solution. Any help would be appreciated thanks
Code:
void executerCommande( char *commande[], int descripteur, char* option )
{
int tubeEntree[2];
int tubeSortie[2];
int erreur;
erreur = pipe( tubeEntree );
if ( erreur == -1 )
{
printf( "Erreur lors de la création du tube %s\n", strerror( errno ) );
exit( 1 );
}
erreur = pipe( tubeSortie );
if ( erreur == -1 )
{
printf( "Erreur lors de la création du tube %s\n", strerror( errno ) );
exit( 1 );
}
pid_t pid = fork();
if ( pid == -1 ) // erreur
{
perror( "fork a échoué" );
exit( 1 );
}
else if ( pid == 0 ) // child
{
close( tubeEntree[1] ); // closing writing end of tube from parent to child
close( tubeSortie[0] ); // closing reading end of tube from child to parent
dup2( tubeSortie[1], 1 ); // redirecting stdout to writing end of tube from child to parent
close( tubeSortie[1] ); // fermeture du doublon
dup2( tubeEntree[0], 0 ); // redirecting stdin to reading end of tube from parent to child
close( tubeEntree[0] ); // fermeture du doublon
execvp( commande[0], commande );
}
else // parent
{
int evenement;
int commandeTerminee = 0;
char tampon [256];
struct pollfd entrees[2];
entrees[0].fd = 0; // check stdin
entrees[0].events = POLLIN | POLLPRI; // surveiller pour des données normales ou prioritaires
entrees[0].revents = 0;
entrees[1].fd = tubeSortie[0]; // check reading end of tube from child to parent
entrees[1].events = POLLIN | POLLPRI; // surveiller pour des données normales ou prioritaires
entrees[1].revents = 0;
close( tubeEntree[0] ); // closing reading end of tube from parent to child
close( tubeSortie[1] ); // closing writing end of tube from child to parent
while ( commandeTerminee == 0 )
{
entrees[0].revents = 0;
entrees[1].revents = 0;
evenement = poll( entrees, 2, 0 );
if ( evenement == -1 )
{
printf( "Erreur lors du poll %s\n", strerror( errno ) );
exit( 1 );
}
if ( ( entrees[0].revents & POLLIN ) || ( entrees[0].revents & POLLPRI ) )
{
memset(tampon, '\0', 256);
read( entrees[0].fd, tampon, 256 );
erreur = write ( tubeEntree[1], tampon, strlen( tampon ) );
if ( erreur == -1 )
{
printf( "Erreur lors de l'écriture dans le tube d'entrée %s\n", strerror( errno ) );
exit( 1 );
}
}
if ( ( entrees[1].revents & POLLIN ) || ( entrees[1].revents & POLLPRI ) )
{
do {
memset(tampon, '\0', 256);
erreur = read( entrees[1].fd, tampon, 256 );
if ( erreur == -1 )
{
printf( "Erreur lors de la lecture du tube de sortie %s\n", strerror ( errno ) );
exit( 1 );
}
printf( "%s", tampon );
} while (erreur != 0);
}
if ( entrees[1].revents & POLLHUP )
{
printf( "recu terminaison\n" );
commandeTerminee = 1;
}
}
pid = wait( NULL );
}
}