#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <stdlib.h>
#define True 1
#define False 0

#ifdef MAKE_SIGILL
#define GEN_SIGILL { char x [5] = { 0xf0, 0x0f, 0xc7, 0xc8 }; \
   { void (*f)() = (void*)x; f(); }; }
#else
#define GEN_SIGILL { raise(SIGILL); }
#endif

static jmp_buf env_sigill;
static void handler_sigill ( int x ) { longjmp(env_sigill,1); }

int main(int argc, char* argv[]) {


   sigset_t         saved_set, tmp_set;
   struct sigaction saved_act, tmp_act;

   int have_fp, have_vmx;

   // additional code
   int input_fp=0, input_vmx=0, redo_procmask=0;
   if(argc>=2) { redo_procmask=atoi(argv[1]); }
   if(argc>=3) { input_fp=atoi(argv[2]); }
   if(argc>=4) { input_vmx=atoi(argv[3]); }
   // end additional code

   sigemptyset(&tmp_set);
   sigaddset(&tmp_set, SIGILL);

   sigprocmask(SIG_UNBLOCK, &tmp_set, &saved_set);

   sigaction(SIGILL, NULL, &saved_act);
   tmp_act = saved_act;

   tmp_act.sa_flags &= ~SA_RESETHAND;
   tmp_act.sa_flags &= ~SA_SIGINFO;
   tmp_act.sa_flags |= SA_NODEFER;

   tmp_act.sa_handler = handler_sigill;
   sigaction(SIGILL, &tmp_act, NULL);

   have_fp = True;
   if (setjmp(env_sigill)) {
      if(redo_procmask) sigprocmask(SIG_UNBLOCK, &tmp_set, NULL);
      have_fp = False;
   } else {
      if(!input_fp) GEN_SIGILL;
   }

   tmp_act.sa_handler = handler_sigill;
   sigaction(SIGILL, &tmp_act, NULL);

   have_vmx = True;
   if (setjmp(env_sigill)) {
      if(redo_procmask) sigprocmask(SIG_UNBLOCK, &tmp_set, NULL);
      have_vmx = False;
   } else {
      if(!input_vmx) GEN_SIGILL;
   }

   sigaction(SIGILL, &saved_act, NULL);
   sigprocmask(SIG_SETMASK, &saved_set, NULL);

   printf("redo_procmask=%i\n", redo_procmask ? 1 : 0);
   printf("fp:  input=%i found=%i\nvmx: input=%i found=%i\n", 
         input_fp, have_fp, input_vmx, have_vmx);

   return(0);
}
