/* Scrivere un programma C e Posix sotto Linux che implementi la seguente pipeline acquisita in input da riga di comando:
$ ls -al /usr/include | grep a*.h | sort -r |wc -l */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
int main (int argc, char *argv[])
{
pid_t pid2, pid3, pid4;
int i;
int TUBO1[2]; // tra p1 e p2
int TUBO2[2]; // tra p2 e p3
int TUBO3[2]; // tra p3 e p4
printf ("Stampo gli argomenti\n");
for (i=1; i<argc; i++)
{
printf ("%d) %s\n", i, argv[i]);
}
printf ("\n");
// apro la pipe 1
if (pipe (TUBO1)<0)
{
printf ("Errore nella pipe!\n");
exit(1);
}
// apro la pipe 2
if (pipe (TUBO2)<0)
{
printf ("Errore nella pipe!\n");
exit(2);
}
// apro la pipe 3
if (pipe (TUBO3)<0)
{
printf ("Errore nella pipe!\n");
exit(3);
}
switch (fork()) {
case -1: // errore nella fork
printf ("Errore nella fork!");
exit(4);
case 0:
/* Il primo processo figlio deve leggere dalla prima pipe e scrivere nella seconda, quindi chiude la terza in lettura/scrittura,
la prima in scrittura e la seconda in lettura */
printf("// SONO NEL PRIMO FIGLIO\n");
close (TUBO3[0]);
close (TUBO3[1]);
close (TUBO1[1]);
close (TUBO2[0]);
close(0);
dup2(TUBO1[0],0); // duplico il canale in lettura della prima pipe sullo standard input
close(1);
dup2(TUBO2[1],1); // duplico il canale in scrittura della seconda pipe sullo standard output
// grep a*.h
execlp(argv[4],argv[4],argv[5],NULL);
printf ("ERRORE NELLA EXEC!\n");
default:
switch (fork()){
case -1: // errore nella fork
printf ("Errore nella fork!");
exit(5);
case 0:
/* Il secondo processo deve leggere dalla seconda pipe e scrivere sulla terza, quindi chiude la prima pipe in lettura
/scrittura, la seconda in scrittura, la terza in lettura */
printf("// SONO NEL SECONDO FIGLIO\n");
close(TUBO1[0]);
close(TUBO1[1]);
close(TUBO2[1]);
close(TUBO3[0]);
close(0);
dup2(TUBO2[0],0); // duplico il canale in lettura della seconda pipe sullo standard input
close(1);
dup2(TUBO3[1],1); // duplico il canale in scrittura della terza pipe sullo standard output
// sort -r
execlp(argv[6],argv[6],argv[7],NULL);
printf ("ERRORE NELLA EXEC!\n");
default:
switch (fork ()){
case -1: // errore nella fork
printf ("Errore nella fork!\n");
exit(6);
case 0:
/* Il terzo figlio deve leggere dalla terza pipe, quindi chiudiamo la prima e la seconda in lettura/
scrittura, la terza in scrittura */
printf("// SONO NEL TERZO FIGLIO\n");
close(TUBO1[0]);
close(TUBO1[1]);
close (TUBO2[0]);
close (TUBO2[1]);
close(TUBO3[1]);
close(0);
dup2(TUBO3[0],0); // duplico il canale in lettura della terza pipe sullo standard input
execlp(argv[8],argv[8],argv[9],NULL);
printf ("Errore nella execlp!\n");
default:
/* Il processo padre deve soltanto scrivere sulla prima pipe, quindi chiudiamo la seconda e la terza
in lettura/scrittura, la prima in lettura */
printf ("// SONO NEL PADRE");
close (TUBO2[0]);
close (TUBO2[1]);
close (TUBO3[0]);
close (TUBO3[1]);
close (TUBO1[0]);
close(1);
dup2 (TUBO1[1], 1); // duplico il canale di scrittura della prima pipe sullo standard output
// ls -al /usr/include
execlp (argv[1], argv[1], argv[2], argv[3], NULL);
printf ("ERRORE NELLA EXEC!\n");
}
}
}
exit(0);
}