#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <err.h>
#include <errno.h>
#include <signal.h>
#include "../lpi.h"

#define SYNC_SIG    SIGUSR1

static void
handler(int sig)
{
}

int
main(int argc, char *argv[])
{
    pid_t childPid;
    sigset_t blockMask, origMask, emptyMask;
    struct sigaction sa;

    setbuf(stdout, NULL);       /* disable buffering of stdout */

    sigemptyset(&blockMask);
    sigaddset(&blockMask, SYNC_SIG);
    if (sigprocmask(SIG_BLOCK, &blockMask, &origMask) == -1)
        err(EXIT_FAILURE, "sigprocmask");

    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    sa.sa_handler = handler;
    if (sigaction(SYNC_SIG, &sa, NULL) == -1)
        err(EXIT_FAILURE, "sigaction");

    switch (childPid = fork()) {
    case -1:
        err(EXIT_FAILURE, "fork");

    case 0:                     /* child */
        printf("[%s %ld] child started - doing some work\n",
                currTime("%T"), (long) getpid());
        sleep(2);
        printf("[%s %ld] child about to signal parent\n",
                currTime("%T"), (long) getpid());
        if (kill(getppid(), SYNC_SIG) == -1)
            err(EXIT_FAILURE, "kill");
        _exit(EXIT_SUCCESS);

    default:                    /* parent */
        printf("[%s %ld] parent about to wait for signal\n",
                currTime("%T"), (long) getpid());
        sigemptyset(&emptyMask);
        if (sigsuspend(&emptyMask) == -1 && errno != EINTR)
            err(EXIT_FAILURE, "sigsuspend");
        printf("[%s %ld] parent got signal\n", currTime("%T"), (long) getpid());

        /*
         * به نظر لازم نیست. sigsuspend بعد از بازگشت خودش سیگنال‌های
         * بلاک شده قبلی را restore می‌کند.
        if (sigprocmask(SIG_SETMASK, &origMask, NULL) == -1)
            err(EXIT_FAILURE, "sigprocmask");
        */
        exit(EXIT_SUCCESS);
    }

    exit(EXIT_SUCCESS);
}
