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

// Manejador para que P2 despierte sin morir
void manejador(int sig) { }

int main() {
    pid_t pid1, pid2, pid3;
    int status;

    // --- P CREA A P1 ---
    pid1 = fork();
    switch (pid1) {
        case -1:
            perror("Error fork P1");
            exit(EXIT_FAILURE);
        case 0:
            // CÓDIGO P1
            srand(time(NULL) ^ getpid());
            int num = rand() % 10;
            printf("Soy P1 (PID: %d, PPID: %d). Genero: %d\n", getpid(), getppid(), num);
            exit(num); 
        default:
            pid2 = fork();
            switch (pid2) {
                case -1:
                    perror("Error fork P2");
                    exit(EXIT_FAILURE);
                case 0:
                    // CÓDIGO P2
                    printf("Soy P2 (PID: %d, PPID: %d)\n", getpid(), getppid());
                    signal(SIGUSR1, manejador);

                    // P2 CREA A P3 (Anidado)
                    pid3 = fork();
                    switch (pid3) {
                        case -1:
                            perror("Error fork P3");
                            exit(EXIT_FAILURE);
                        case 0:
                            // CÓDIGO P3
                            printf("Soy P3 (PID: %d, PPID: %d)\n", getpid(), getppid());
                            kill(getppid(), SIGUSR1);
                            printf("P3 enviado señal, bloqueándose...\n");
                            pause();
                            exit(0);
                        default:
                            // P2 ESPERA SEÑAL Y LUEGO RECOGE A P3
                            printf("P2 bloqueado esperando señal...\n");
                            pause();
                            wait(NULL); 
                            exit(0);
                    }
                default:
                    // PADRE P RECOGE A SUS HIJOS (P1 y P2)
                    // Recoger P1 para obtener el número
                    
                    waitpid(pid1, &status, 0);
                    if (WIFEXITED(status)) {
                        printf("Padre P: P1 devolvió el valor %d\n", WEXITSTATUS(status));
                    }
                    // Recoger P2
                    waitpid(pid2, NULL, 0);
                    printf("Padre P: Todos recogidos. Fin.\n");
            }
    }
    return 0;
}