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

void sigusr1_handler(int signo)
{
  printf("Figlio %d ricevuto il segnale SIGUSR1. INIZIO ATTIVITA\n",getpid()); 
}

void sigusr2_handler(int signo)
{ 
  printf("Figlio %d ricevuto il segnale SIGUSR2. INIZIO ATTIVITA\n",getpid()); 
}

void body_padre(int N,int Pa1[2],int Pa2[2])
{
  int pid,status,i; 

  for(i=1; i<=N/2;i++)
    write(Pa1[1],&i,sizeof (int));
  printf("Il padre ha scritto i numeri sulla pipe Pa\n");
  for(i=(N/2+1); i<=N;i++)
    write(Pa2[1],&i,sizeof (int));
  printf("Il padre ha scritto i numeri sulla pipe Pb\n");

  while ((pid=waitpid(-1, &status, 0)) > 0)  
  {
    if (WIFEXITED(status)) /* ritorna 1 se il figlio ha terminato correttamente */
      printf("Il figlio %d ha terminato correttamente con exit status=%d\n",
              pid, WEXITSTATUS(status));
    else
      printf("Il figlio %d non ha terminato correttamente\n",pid);
  }
  exit(0);
}


void body_figlio(int N,int pipe[2],char *nomefile)
{
  int n,fd,i;
  char number[10];
  
  if ((fd=open(nomefile,O_WRONLY|O_CREAT|O_TRUNC,0644))<0)
    {
      perror("Creazione file");
      exit(-1);
    }
  for (i=1;i<=N/2;i++)
    {
      read(pipe[0],&n,sizeof (int));
      sprintf(number,"%d\n",n);
      write(fd,number, strlen (number));
    }
  printf("Il figlio %d ha scritto sul file %s\n",getpid(),nomefile);
  close(fd);
  exit(0);
}

int main(int argc, char *argv[])
{
  int N;
  int pid1,pid2;
  int Pa1[2];
  int Pa2[2];
  
  sigset_t set,oldset,zeromask;
  struct sigaction action1,action2;
 
  /* Controllo argomenti */
  if(argc!=2)
    {
      fprintf(stderr,"Uso: %s numero_intero\n",argv[0]);
      exit(-1);
    }

  N=atoi(argv[1]);

  /* Gestione segnali */
  sigemptyset(&zeromask);

  sigemptyset(&action1.sa_mask);
  action1.sa_handler = sigusr1_handler;
  action1.sa_flags = 0;

  sigemptyset( &set );
  sigaddset(&set,SIGUSR1);
  sigaddset(&set,SIGUSR2);
  sigprocmask(SIG_BLOCK,&set,&oldset);

  if (sigaction(SIGUSR1,&action1,NULL))
    {
      perror("sigaction per SIGUSR1");
    }
  
  sigemptyset(&action2.sa_mask);
  action2.sa_handler = sigusr2_handler;
  action2.sa_flags = 0;
  if (sigaction(SIGUSR2,&action2,NULL))
    {
      perror("sigaction per SIGUSR2");
    }

  /* Creazione Pipe */
  if(pipe(Pa1)<0)
    {
      perror("Creazione pipe Pa1");
      exit(-1);
    }
  if(pipe(Pa2)<0)
    {
      perror("Creazione pipe Pa2");
      exit(-1);
    }

  /* Creazione processi figli */
  if ((pid2=fork())==0)
    {
      sigsuspend(&zeromask);
      body_figlio(N,Pa2,"numeri-p12.txt");
    }
  else
    if ((pid1=fork())==0)
      {
	sigsuspend(&zeromask);
	kill(pid2,SIGUSR2);
	body_figlio(N,Pa1,"numeri-p11.txt");
      }
  else 
    {
      kill(pid1,SIGUSR1);
      body_padre(N,Pa1,Pa2);
    }
}
