/*TESTO:
    Si realizzi un programma in C che abbia il seguente comportamento:
    - il processo genera un ﬁglio
    - il ﬁglio trasmette al padre un numero casuale compreso tra 0 e 50
    - il padre genera un altro numero casuale (sempre tra 0 e 50), lo somma a quello ricevuto, e lo
      rispedisce al ﬁglio visualizzando
      <proprio PID>:        <numero casuale estratto> <somma inviata>
    - il ﬁglio fa la stessa cosa: genera un altro numero casuale (sempre tra 0 e 50), lo somma a quello
      ricevuto, e lo rispedisce al padre visualizzando
      <proprio PID>:        <numero casuale estratto> <somma inviata>
    - lo scambio di messaggi deve procedere ﬁnchè il numero da inviare risulta maggiore di 1000. Non
      appena un processo ottiene una somma superiore a 1000, deve inviare un segnale SIGUSR1
      all’altro processo, il quale alla ricezione termina visualizzando il numero di messaggi ricevuti.
    - Dopo aver inviato il segnale SIGUSR1 il processo termina visualizzando il valore ﬁnale della
      somma (che sarà superiore a 1000).

Si utilizzi la gestione affidabile dei segnali.
*/


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <netdb.h>

int cont = 0;

void handler(int signo)
{

    if (signo==SIGUSR1)  {

        printf("Sono il processo %d e termino in seguito alla ricezione di un segnale,e ho ricevuto  %d messaggi\n",getpid(),cont);
        exit(0);
    } else
        printf("Segnale non gestito");
}

int main()
{

    int pidp,pidf;
    int p1[2];
    int p2[2];
    int numerocasuale,somma,numeropadre;
    struct sigaction sig;

    printf("Sono il processo padre con pid %d\n",getpid());
    pidp=getpid();

    //creazione pipe
    if (pipe(p1)<0)  {
        perror("Pipe error");
        exit(-1);
    }

    if (pipe(p2)<0)  {
        perror("Pipe error");
        exit(-1);
    }

    //gestione affidabile dei segnali
    sig.sa_handler=handler;
    sigemptyset(&sig.sa_mask);
    sig.sa_flags=0;
    sigaction(SIGUSR1,&sig,NULL);

    //il padre crea il processo figlio
    if ((pidf=fork())<0)  {
        perror("Errore di fork");
        exit(-1);
    }

    if (pidf==0)  {    //codice figlio

        close(p1[0]);
        close(p2[1]);
        srand(getpid());   //inizializzo il generatore di numeri casuali

        somma=rand()%50;
        if(write(p1[1],&somma,sizeof(somma))<0) {

            perror("Errore di scrittura");
            exit(-1);
        }

        do {

            if(read(p2[0],&somma,sizeof(somma))<0)  {

                perror("Errore in lettura");
                exit(-1);
            }

            cont++;
            numerocasuale=rand()%50;
            somma+=numerocasuale;

            printf("Pid %d: numero casuale %d  somma inviata %d\n",getpid(),numerocasuale,somma);

            if(write(p1[1],&somma,sizeof(somma))<0)  {

              perror("Errore in scrittura");
              exit(-1);
            }

        } while(somma<=1000);

        kill(getppid(),SIGUSR1);
        printf("Sono il processo figlio %d e il valore finale di somma è %d\n",getpid(),somma);
        exit(0);
    } else { //processo padre

        close(p1[1]);
        close(p2[0]);

        do {

            if(read(p1[0],&somma,sizeof(somma))<0)  {
                perror("Errore in lettura");
                exit(-1);
            }

            cont++;
            numeropadre=rand()%50;
            somma+=numeropadre;

            printf("Pid %d: numero casuale %d  somma inviata %d\n",getpid(),numeropadre,somma);

            if(write(p2[1],&somma,sizeof(somma))<0)  {

                perror("Errore in scrittura");
                exit(-1);
            }

        } while(somma<=1000);

        kill(pidf,SIGUSR1);
        printf("Sono il processo padre %d e il valore finale di somma è %d\n",getpid(),somma);
        exit(0);
    }

    return 0;
}
