//  Pour la gestion des signaux a travers des exceptions
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include "psighand.h"
#include "pexceptions.h"

static bool sigprstate[6] = {false, false, false, false, false, false};

void SophyaProcessSignal(int s);

/* Nouvelle-Fonction */
/*!\ingroup  SysTools 
   Configures signal handling. When the flag is true, an exception 
   \b CaughtSignalExc is thrown with the excpetion id set to the 
   signal id. With the flag is false, the default signal handling
   is restored.
   \param cfpe : Floating point exception \c SIGFPE
   \param csegv : Segmentation fault \c SIGSEGV
   \param cint : Interrupt signal \c SIGINT
   \param cquit : Quit signal \c SIGINT
   \param cusr1 : User signal 1 \c SIGUSR1
   \param cusr2 : User signal 1 \c SIGUSR2
*/
void SOPHYA::SophyaConfigureSignalhandling(bool cfpe, bool csegv, bool cint, bool cquit, bool cusr1, bool cusr2) 
{
  struct sigaction ae, ad;

  ae.sa_handler = SophyaProcessSignal;
  ad.sa_handler = SIG_DFL;
  memset( &(ae.sa_mask), 0, sizeof(sigset_t) ); 
  ae.sa_flags = 0;
  memset( &(ad.sa_mask), 0, sizeof(sigset_t) ); 
  ad.sa_flags = 0;
#ifdef  OSF1
  ae.sa_flags = SA_RESTART;
  ad.sa_mask = 0;
#endif

// SIGFPE 
  if (sigprstate[0] != cfpe) {
    if (cfpe)   { 
      sigaction(SIGFPE, &ae, NULL);
      puts("SophyaConfigureSignalhandling(): Activating SIGFPE handling (-> throw) ...");
      }
    else  { 
      sigaction(SIGFPE, &ad, NULL);
      puts("SophyaConfigureSignalhandling(): Back to default SIGFPE handling ...");
      }
    sigprstate[0] = cfpe;
    }
// SIGSEGV 
  if (sigprstate[1] != csegv) {
    if (csegv)   { 
      sigaction(SIGSEGV, &ae, NULL);
      puts("SophyaConfigureSignalhandling(): Activating SIGSEGV handling (-> throw) ...");
      }
    else  { 
      sigaction(SIGSEGV, &ad, NULL);
      puts("SophyaConfigureSignalhandling(): Back to default SIGSEGV handling ...");
      }
    sigprstate[1] = csegv;
    }

// SIGINT
  if (sigprstate[2] != cint) {
    if (cint)   { 
      sigaction(SIGINT, &ae, NULL);
      puts("SophyaConfigureSignalhandling(): Activating SIGINT handling (-> throw) ...");
      }
    else  { 
      sigaction(SIGINT, &ad, NULL);
      puts("SophyaConfigureSignalhandling(): Back to default SIGINT handling ...");
      }
    sigprstate[2] = cint; 
    }
  
// SIGQUIT
  if (sigprstate[3] != cquit) {
    if (cquit)   { 
      sigaction(SIGQUIT, &ae, NULL);
      puts("SophyaConfigureSignalhandling(): Activating SIGQUIT handling (-> throw) ...");
      }
    else  { 
      sigaction(SIGQUIT, &ad, NULL);
      puts("SophyaConfigureSignalhandling(): Back to default SIGQUIT handling ...");
      }
    sigprstate[3] = cquit; 
    }
  
// SIGUSR1
  if (sigprstate[4] != cusr1) {
    if (cusr1)   { 
      sigaction(SIGUSR1, &ae, NULL);
      puts("SophyaConfigureSignalhandling(): Activating SIGUSR1 handling (-> throw) ...");
      }
    else  { 
      sigaction(SIGUSR1, &ad, NULL);
      puts("SophyaConfigureSignalhandling(): Back to default SIGUSR1 handling ...");
      }
    sigprstate[4] = cusr1;
    }
// SIGUSR2
  if (sigprstate[5] != cusr2) {
    if (cusr2)   { 
      sigaction(SIGUSR2, &ae, NULL);
      puts("SophyaConfigureSignalhandling(): Activating SIGUSR2 handling (-> throw) ...");
      }
    else  { 
      sigaction(SIGUSR2, &ad, NULL);
      puts("SophyaConfigureSignalhandling(): Back to default SIGUSR2 handling ...");
      }
    sigprstate[5] = cusr2;
    }    
}
/* Nouvelle-Fonction */
void SophyaProcessSignal(int s)
{
string msg;
switch(s)
  {
  case SIGFPE :
    puts("SophyaProcessSignal: ###Signal SIGFPE catched, throw catchedSIGFPE ###");
    msg = "Caught SIGFPE";
    throw ( CaughtSignalExc(msg, s) );
  case SIGSEGV :
    puts("SophyaProcessSignal: ###Signal SIGSEGV catched, throw catchedSIGSEGV ###");
    msg = "Caught SIGSEGV";
    throw ( CaughtSignalExc(msg, s) );
  case SIGINT :
    puts("SophyaProcessSignal: ###Signal SIGINT catched, throw catchedSIGINT ###");
    msg = "Caught SIGINT";
    throw ( CaughtSignalExc(msg, s) );
  case SIGQUIT :
    puts("SophyaProcessSignal: ###Signal SIGQUIT catched, throw catchedSIGQUIT ###");
    msg = "Caught SIGQUIT";
    throw ( CaughtSignalExc(msg, s) );
  case SIGUSR1 :
    puts("SophyaProcessSignal: ###Signal SIGUSR1 catched, throw catchedSIGUSR1 ###");
    msg = "Caught SIGUSR1";
    throw ( CaughtSignalExc(msg, s) );
  case SIGUSR2 :
    puts("SophyaProcessSignal: ###Signal SIGUSR2 catched, throw catchedSIGUSR2 ###");
    msg = "Caught SIGUSR2";
    throw ( CaughtSignalExc(msg, s) );
  default :
    printf("SophyaProcessSignal: ###Signal %d catched, throw  inconsistentErr ### \n", s);
    msg = "Caught SIG???";
    throw ( CaughtSignalExc(msg, s) );
  }

// return;
}
