Abuelo, hijos, nietos y médico en C con hilos

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
void manejadora1(int sig);
void manejadora2(int sig);
int calculaAleatorios(int min, int max);

void NIETOS();
void HIJOS(int estado, int enfermo, int suma, int pid);
void ABUELO(int estado, int enfermo, int suma);

int main(int argc, char*argv[]){

 //Comienza el abuelo
 //codigo para que el aleatorio varie
 srand(time(NULL));
 pid_t pid;
 //El abuelo crea al doctor
 pid=fork();
 if(pid==-1){
  //si la llamada al fork da error
  perror("Error en la llamada a fork\n");
 }else if(pid!=0){

  //Esta es la parte del abuelo
  pid_t pidHijos;
  struct sigaction sa,sa2;
  sa.sa_handler=manejadora2;//manejadora dos que se llama si el medico no esta disponible
  //que imprime que no esta disponible, y acaba el programa
  sa2.sa_handler=manejadora1;//la manejadora uno que no hace nada
  if(sigaction(SIGUSR1,&sa,NULL)==-1){//cambiamos el comportamiento de la señal sigusr1
   //si da error
   perror("Error en la llamada a sigaction\n");
   exit(-1);
  }
  if(sigaction(SIGUSR2,&sa2,NULL)==-1){//cambiamos el comportamiento de la señal sigusr1
   //si da error
   perror("Error en la llamada a sigaction\n");
   exit(-1);
  }
  //duerme un segundo, para que se ejecute el programa correctamente, si no se me peta
  sleep(1);
  //Enviamos la señal sigusr1 al doctor, le pregunta si esta disponible
  if(kill(pid,SIGUSR1)!=0){
   perror("Error en la llamada a kill\n");
   exit(-1);
  }
  //Esperamos su respuesta
  pause();
  int i,j; //variables de los for
  for(i=0;i<2;i++){
   //Creamos a los hijos
   pid=fork();
   if(pid==-1){
    perror("Error en la llamada a fork\n");
    exit(-1);
   }else if(pid==0){
    //aqui va cada hijo, que crea tres nietos
    
    for(j=0;j<3;j++){
     //Creamos a los nietos
     pidHijos=fork();
     
     switch(pidHijos){
      case -1:
       perror("Error en la llamada a fork\n");
       break;
      case 0:
       //NIETOS
       j=3;
       i=2;  
       break;
     }
    }
    i=2;
   }
  }
  if(pid==0){
   if(pidHijos==0){
    //NIETOS, son todos aquellos que tienen pidHijos 0
    NIETOS();
   }else{//si no tienen el pidHijos 0, es que es el padre
    //da igual el valor de pidHijos ya que todos los padres, o hijos del abuelo, hacen lo mismo
    int estado;
    int enfermo;
    int suma=0;
    //llamamos a la funcion que ejecutaran los hijos
    HIJOS(estado,enfermo,suma, pidHijos);
   }
  }else{
   //ABUELO
   int estado;
   int enfermo;
   int suma=0;
   ABUELO(estado, enfermo, suma);
  }

 }else{

  //Llamamos al medico
  int aleatorio, pidabuelo;
  struct sigaction sa;
  //llamamos a la manejadora1, para cambiar el comportamiento de la señal despues
  sa.sa_handler=manejadora1;
  //cambiamos el funcionamiento de sigusr1
  if(sigaction(SIGUSR1,&sa,NULL)==-1){
   //si da error
   perror("Error en la llamada a sigaction\n");
   exit(-1);
  }
  //Esperamos la llamada del abuelo
  pause();
  //consigues el pid del padre, en este caso el abuelo
  pidabuelo=getppid();
  //calculamos el aleatorio para saber si esta disponible o no
  aleatorio=calculaAleatorios(0,1);

  switch(aleatorio){
   case 0:
    //si el aleatorio es 0 envia al abuelo sigursr1, significa que no esta disponible
    if(kill(pidabuelo,SIGUSR1)!=0){
     perror("Error en la llamada a kill\n");
     exit(-1);
    }
    break;
   default:
    //si el aleatorio es distinto de 0 envia al abuelo sigurs2, significa que esta disponible
    if(kill(pidabuelo,SIGUSR2)!=0){
     perror("Error en la llamada a kill\n");
     exit(-1);
    }
    break;
  }

 } 

 return 0;

}

void manejadora1(int sig){

}
void manejadora2(int sig){

 //cuando el medico no esta disponible
 printf("Mis nietos no pueden salir porque el medico no esta disponible\n");
 exit(0);

}
int calculaAleatorios(int min, int max){

 return rand() % (max-min+1) + min;

}
void NIETOS(){
 
 int aleatorio;
 srand(getpid());
 sleep(calculaAleatorios(2,6));
 aleatorio=calculaAleatorios(0,1);
 printf("Nieto con pid %d y ppid %d: %d\n",getpid(),getppid(), aleatorio);
 //exit(calculaAleatorios(0,1));
 exit(aleatorio);

}
void HIJOS(int estado, int enfermo, int suma, int pid){

 printf("Comienza hijo de pid: %d.\n", pid);
 //Esperamos por todos los nietos
 if(wait(&estado)!=-1){
  enfermo=WEXITSTATUS(estado);
  suma=suma+enfermo;
 }
 if(wait(&estado)!=-1){
  enfermo=WEXITSTATUS(estado);
  suma=suma+enfermo;
 }
 if(wait(&estado)!=-1){
  enfermo=WEXITSTATUS(estado);
  suma=suma+enfermo;
 }
 printf("Numero de nietos enfermos: %d\n",suma);
 exit(suma);

}
void ABUELO(int estado, int enfermo, int suma){
/*
 while(wait(&estado)!=-1){
  enfermo=WEXITSTATUS(estado);
  suma=suma+enfermo;
 }
 //daria lo mismo hacerlo con el while que de forma individual
*/
 if(wait(&estado)!=-1){
  enfermo=WEXITSTATUS(estado);
  suma=suma+enfermo;
 }
 if(wait(&estado)!=-1){
  enfermo=WEXITSTATUS(estado);
  suma=suma+enfermo;
 }
 
 if(wait(&estado)!=-1){
  enfermo=WEXITSTATUS(estado);
  suma=suma+enfermo;
 }
 printf("El número de nietos enfermos que deben ir al doctor es %d\n",suma);

}