#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);
}