#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/types.h>
#include <sys/resource.h>

sigjmp_buf mainloop;

volatile int pass = 0;

void
stackoverflow_handler (int sig)
{
  pass++;
  printf ("Stack overflow %d caught.\n", pass);
  siglongjmp (mainloop, pass);
}

int
recurse (int n)
{
  printf ("%p\n", &n);
  if (n >= 0)
    return n + recurse (n + 1);
  else
    return 0;
}

int
main ()
{
  char mystack[16384];
  struct rlimit rl;
  stack_t ss;
  struct sigaction action;

  rl.rlim_cur = rl.rlim_max = 0x100000;	/* 1 MB */
  setrlimit (RLIMIT_STACK, &rl);
  ss.ss_sp = mystack;
  ss.ss_size = sizeof (mystack);
  ss.ss_flags = 0;
  if (sigaltstack (&ss, (stack_t *) 0) < 0)
    exit (0);

  action.sa_handler = stackoverflow_handler;
  action.sa_flags = SA_ONSTACK;
  sigemptyset (&action.sa_mask);
  if (sigaction (SIGSEGV, &action, 0) < 0)
    exit (0);

  switch (sigsetjmp (mainloop, 1))
    {
    case 0:
    case 1:
      printf ("Starting recursion pass %d.\n", pass + 1);
      recurse (0);
      printf ("no endless recursion?!\n");
      exit (1);

    case 2:
      printf ("Test passed.\n");
      exit (0);

    default:
      abort ();
    }
}

