#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <err.h>

void printStack_tFields(const char *structName, stack_t *sigstack);
void handler(int sig);

int
main(int argc, char *argv[])
{
    stack_t sigstack1;
    stack_t sigstack2;
    struct sigaction sa1;
    struct sigaction sa2;

    sigstack1.ss_sp = malloc(SIGSTKSZ);
    sigstack1.ss_size = SIGSTKSZ;
    sigstack1.ss_flags = 0;

    if (sigaltstack(&sigstack1, NULL) == -1)
        err(EXIT_FAILURE, "sigaltstack");

    printStack_tFields("sigstack1", &sigstack1);
    printf("----------------------------------\n");

    sa1.sa_handler = handler;
    sa1.sa_flags = SA_ONSTACK;
    sigemptyset(&sa1.sa_mask);

    if (sigaction(SIGUSR1, &sa1, NULL) == -1)
        err(EXIT_FAILURE, "sigaction - SIGUSR1");

    sa2.sa_handler = handler;
    sa2.sa_flags = 0;
    sigemptyset(&sa2.sa_mask);

    if (sigaction(SIGUSR2, &sa2, NULL) == -1)
        err(EXIT_FAILURE, "sigaction - SIGUSR2");

    raise(SIGUSR1);
    printf("----------------------------------\n");
    raise(SIGUSR2);

    printf("\ndisable alternate signal stack with ss_flags=SS_DISABLE\n\n");
    sigstack1.ss_flags = SS_DISABLE;
    if (sigaltstack(&sigstack1, NULL) == -1)
        err(EXIT_FAILURE, "sigaltstack - 2");
    raise(SIGUSR1);
    printf("----------------------------------\n");
    raise(SIGUSR2);
    exit(EXIT_SUCCESS);
}

void
printStack_tFields(const char *structName, stack_t *sigstack)
{
    printf("%s.ss_sp   : %p\n", structName, sigstack->ss_sp);
    printf("%s.ss_size : %ld\n", structName, sigstack->ss_size);
    printf("%s.ss_flags: %x", structName, sigstack->ss_flags);

    if (sigstack->ss_flags == SS_ONSTACK)
        printf(" (SS_ONSTACK)");
    if (sigstack->ss_flags == SS_DISABLE)
        printf(" (SS_DISABLE)");
    printf("\n");
}

void
handler(int sig)
{
    stack_t sigstack;

    printf("caught signal %d (%s)\n", sig, strsignal(sig));
    if (sigaltstack(NULL, &sigstack) == 1)
        warn("sigaltstack in handler");
    else
        printStack_tFields("sigstack", &sigstack);
}
