/*TESTO

Si realizzi in ambiente Unix/C la seguente interazione tra processi:

-un processo determina il proprio pid P e procede a generare processi figli fintanto che il pid di un figlio Pf non assume valore 
 maggiore od uguale del pid del padre P maggiorato di 5 (cioe' Pf>=P+5). Discutere in quali condizioni il pid di un figlio e' maggiore
 del pid del padre;
-ogni processo figlio cosi' generato visualizza il proprio pid;
-il processo figlio con pid minore invia un segnale a tutti gli altri processi e poi termina visualizzando un messaggio di terminazione;
-gli altri figli non appena ricevono il segnale visualizzano un messaggio e terminano;
-il padre termina dopo che sono terminati tutti i figli







--SOLUZIONE--

Per quanto riguarda la domanda: il pid del figlio NON e' sempre maggiore di quello del padre. Infatti, dato che il pid e' rappresentato con 16 bit, puo'
accadere che si arrivi al pid 65536, dopo di che si ricomincia da 0 con il primo pid disponibile. Quindi, se per esempio il padre ha pid 65530 potrebbe generare 
due figli, uno 65533, uno 65536, e poi un terzo con pid, per esempio, 100 quindi minore di quello del padre.

PERO'... questa era la risposta alla domanda. Per lo svolgimento degli altri punti del compito era possibile fare un'ipotesi semplificativa (scrivendolo nel compito):
si suppone di non raggiungere mai il limite di 65536, e quindi si assumere che i pid dei figli siamo sempre maggiori di quelli del padre e sempre crescenti. 
Questa ipotesi NON viene penalizzata nel giudizio, era lecita. 

**La soluzione riportata qui sotto si basa su questa ipotesi.** 

In fondo c'e' una piccola nota con un abbozzo di soluzione nel caso piu' generale di pid non crescenti.
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>




//Funzione di gestione segnali
void handler(int signo)
{
  if(signo==SIGINT)
    {
      printf("Processo figlio %d ha ricevuto un SIGINT ed esce\n",getpid());
      exit(0);
    }
}


int main()
{
  struct sigaction sig;
  sigset_t newmask;
  int p[2],pid,i,j,status;
  //questo vettore conterra' i pid dei figli. Visto che li assumiamo crescenti, essi non saranno mai piu di 5...
  int pidV[5]; 

  //creo la pipe che usera' il padre per mandare i pid di tutti i figli al figlio con pid minore
  if(pipe(p)<0) 
    {
      perror("pipe");
      exit(-1);
    }

  //stampo il pid del padre
  printf("Sono il padre con pid %d\n",getpid());

  //Genero il primo figlio, quello che avra pid MINORE
  if((pidV[0]=fork())<0) //genero il primo figlio
    {
      perror("fork primo figlio");
      exit(-1);
    }
  if(pidV[0]==0) 
    {//CODICE DEL PRIMO FIGLIO

      //chiudo la pipe in scrittura
      close(p[1]);

      //stampo il pid
      printf("Sono il figlio %d\n",getpid());

      do{
	if(read(p[0],&pid,sizeof(pid))<0)
	  {
	    perror("read pid");
	    exit(-1);
	  }
	//se ho ricevuto il mio pid vuole dire che ho termianto e posso uscire
	//in pratica faro' in modo che il padre mi mandi i pid di tutti i figli in sequenza, ma con
	//quello del figlio minore per ultimo. Il figlio minore li leggere uno per uno con
	//la read, e manda un SIGINT fin tanto che non legge il suo pid, che e' il segnale che
	//i pid sono finiti e puo' uscire
	if(pid==getpid())
	  break;

	//mando un SIGINT al figlio pid
	kill(pid,SIGINT);
      }
      while(1);
      printf("Figlio %d con pid minore esce\n",getpid());

      exit(0);
    }


  //CODICE DEL PADRE

  //chiudo la pipe in lettura
  close(p[0]);

  //Genero gli altri figli
  i=1;
  do
    {
      if((pidV[i]=fork())<0) //genero il figlio
	{
	  perror("fork primo figlio");
	  exit(-1);
	}
      if(pidV[i]==0)
	{
	  //CODICE FIGLI

	  //non mi servono le pipe;
	  close(p[0]);
	  close(p[1]);

          //blocco il segnale SIGINT
          sigemptyset(&newmask);
          sigaddset(&newmask,SIGINT);
          sigprocmask(SIG_BLOCK,&newmask,NULL);

	  //installo il gestore del segnale SIGINT
	  sig.sa_handler = handler;
	  sigemptyset(&sig.sa_mask);
	  sig.sa_flags=0;
	  sigaction(SIGINT,&sig,NULL);

	  //stampo il pid
	  printf("Sono il figlio %d\n",getpid());

	  //mi sospendo in attesa di qualunqe segnale
	  sigsuspend(&(sig.sa_mask));
       
	  //fine codice figli
	}
      //aspettiamo un po', nel frattempo potreste lanciare qualche processo (tipo un browser), giusto per non avere sempre i pid in perfetta sequenza...
      sleep(2);
    }
  while(pidV[i++]<(getpid()+5) && i<5);

  //CODICE PADRE
  //mando al figlio minore i pid di tutti i figli, lui compreso. Il suo pid pero' sara' l'ultimo... occhio agli indici!
  for(j=i-1;j>=0;j--)
    write(p[1],&(pidV[j]),sizeof(pidV[j]));

  //aspetto i figli che ho generato...
  for(j=0;j<i;j++)
    wait(&status);

  return 0;
}
 

/*
SOLUZIONE CASO GENERALE

Si poteva procedere in questo modo: tutti i figli vengono generati nello stesso modo in un ciclo do-while come quello a riga 121. Il padre, una volta raggiunta 
la condizione di uscita, guarda quale dei figli ha il pid piu' piccolo e gli manda un SIGUSR1, e poi fa una write sulla pipe uguale a quella alla riga 157. Avro' 
precedentemente installato il gestore SIGUSR1 per tutti i figli, nel quale e' contenuto qualcosa di questo tipo:

if(signo==SIGUSR1)
{
do{
  if(read(p[0],&pid,sizeof(pid))<0)
  {
   perror("read pid");
   exit(-1);
  }

  if(pid==getpid())
    break;

  //mando un SIGINT al figlio pid
  kill(pid,SIGINT);
  }
while(1);
printf("Figlio %d con pid minore esce\n",getpid());

exit(0);    
}

Cioe' esattamente quello che fa il primo figlio nella soluzione precedente. Ovviamente si dovranno dichiarere tutte le variabili necessaria globabli, ecc. ecc.

Il ciclo di generazione figli cambia in questo modo: si elimina tutta la parte dalla riga 76 alla 111 (generazione del primo figlio), si parte con i=0 e si
toglie la condizione i<5. Naturalmente e' necessario usare un vettore pidV molto piu' grande, direi che, per quello detto all'inizio, di 65536 dovrebbe bastare.
Se a qualcuno interssa mi faccia sapere, che possiamo guardare questa soluzione in dettaglio.

*/


