#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 pid,status; 

  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_figlio1(int N,int pipe[2],char *nomefile)
{
  int n,fd,i;
  char number[10];
  sigset_t zeromask;
  
  if ((fd=open(nomefile,O_WRONLY|O_CREAT|O_TRUNC,0644))<0)
    {
      perror("Creazione file");
      exit(-1);
    }
  for (i=1;i<=N;i++)
    {
      n=2*i;
      write(pipe[1],&n,sizeof (int));
    }
  sigemptyset(&zeromask);
  sigsuspend(&zeromask);
    
  for (i=1;i<=N;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);
}

void body_figlio2(int N,int pipe[2],char *nomefile, int pid1)
{
  int n,fd,i;
  char number[10];
  sigset_t zeromask;
  
  if ((fd=open(nomefile,O_WRONLY|O_CREAT|O_TRUNC,0644))<0)
    {
      perror("Creazione file");
      exit(-1);
    }
 
  for (i=1;i<=N;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);
 
  kill(pid1,SIGUSR2);
  for (i=0;i<N;i++)
    {
      n=2*i+1;
      write(pipe[1],&n, sizeof (int));
    }
  close(fd);
  exit(0);
}

int main(int argc, char *argv[])
{
  int N;
  int pid1,pid2;
  int Pa[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(Pa)<0)
    {
      perror("Creazione pipe Pa");
      exit(-1);
    }
 

  /* Creazione processi figli */
  if ((pid1=fork())==0)
    {
      sigsuspend(&zeromask);
      body_figlio1(N,Pa,"numeri-dispari.txt");
    }
  else
    if ((pid2=fork())==0) 
      body_figlio2(N,Pa,"numeri-pari.txt",pid1);    
    else 
      {
	kill(pid1,SIGUSR1);
	body_padre();
      }
}
