#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <err.h>
#include "../lpi.h"

void sig_handler(int signo);
extern int NSIGS;           // implemented in ../defs.c
extern struct sig sigs[];     // implemented in ../defs.c

int
main(int argc, char *argv[])
{
    pid_t pid, ret_pid;
    int status;
    struct sigaction sa;

    if (argc >= 2 && strcmp(argv[1], "-h") == 0) {
        fprintf(stderr, "usage: %s [yes]\n", argv[0]);
        exit(EXIT_SUCCESS);
    }

    for (int i = 0; i < NSIGS; i++) {
        signal(sigs[i].no, sig_handler);
        // ignore SIGKILL and SIGSTOP errors.
    }

    if ((pid = fork()) == 0) {
        printf("PID=%ld waits for signal\n", (long) getpid());
        while (1)
            pause();
        /* CONTROL NEVER REACHES HERE */
        exit(5);
    }

    if (pid == -1)
        err(EXIT_FAILURE, "fork");

    sa.sa_handler = sig_handler;

    /*
     * very important for resuming interrupted system calls
     */
    sa.sa_flags = SA_RESTART;

    if (argc >= 2 && strcmp(argv[1], "yes") == 0)
        sa.sa_flags |= SA_NOCLDSTOP;

    if (sigaction(SIGCHLD, &sa, NULL) == -1)
        err(EXIT_FAILURE, "sigaction");

    printf("PID=%ld created PID=%ld\n", (long) getpid(), (long) pid);
    fflush(stdout);

    if ((ret_pid = wait(&status)) ==(pid_t) -1)
        err(EXIT_FAILURE, "wait");

    printf("PID=%ld exitted with code %d\n", (long) ret_pid,
            WEXITSTATUS(status));
    printf("PID=%ld exiting...\n", (long) getpid());
    exit(EXIT_SUCCESS);
}

void
sig_handler(int signo)
{
    printf("PID=%ld caught signal %d %s\n",
            (long) getpid(), signo, getSigname(signo));
}
