/* ========================================================================== */
/*! \file
 * \brief Signal handlers
 *
 * Copyright (c) 2012-2020 by the developers. See the LICENSE file for details.
 *
 * If nothing else is specified, function return zero to indicate success
 * and a negative value to indicate an error.
 */


/* ========================================================================== */
/* Include headers */

#include "posix.h"  /* Include this first beause of feature test macro */

#include "config.h"
#include "main.h"
#include "sighandler.h"
#include "ui.h"


/* ========================================================================== */
/*! \addtogroup MAIN */
/*! @{ */


/* ========================================================================== */
/* Constants */

/*! \brief Message prefix for MAIN module */
#define MAIN_ERR_PREFIX  "MAIN: "


/* ========================================================================== */
/* Variables */

/*! \brief Program abort request flag */
static volatile posix_sig_atomic_t  sighandler_abort = 0;


/* ========================================================================== */
/* Signal handler */

static void  sighandler_handler(int  signum)
{
   /* Set global flag to schedule save config & exit */
   sighandler_abort = 1;

   /* Note: The UI wakes up automatically due to the signal */
}


/* ========================================================================== */
/*! \brief Install signal handlers
 *
 * Ignored signals: SIGHUP, SIGPIPE
 *
 * Signals that trigger save exit: SIGTERM, SIGQUIT, SIGINT
 *
 * \return
 * - 0 on success
 * - Negative value on error
 */

int  sighandler_install(void)
{
   int  res = 0;
   int  rv;
   struct_posix_sigaction  sa;

   posix_sigemptyset(&sa.sa_mask);
   sa.sa_flags = 0;

   /* Signals mapped to 'sighandler_handler()' */
   sa.sa_handler = sighandler_handler;
   rv = posix_sigaction(POSIX_SIGINT, &sa, (struct_posix_sigaction*) NULL);
   if(!rv)
   {
      rv = posix_sigaction(POSIX_SIGQUIT, &sa, (struct_posix_sigaction*) NULL);
   }
   if(!rv)
   {
      rv = posix_sigaction(POSIX_SIGTERM, &sa, (struct_posix_sigaction*) NULL);
   }

   /* Signals that should be ignored */
   sa.sa_handler = POSIX_SIG_IGN;
   if(!rv)
   {
      rv = posix_sigaction(POSIX_SIGHUP, &sa, (struct_posix_sigaction*) NULL);
   }
   if(!rv)
   {
      rv = posix_sigaction(POSIX_SIGPIPE, &sa, (struct_posix_sigaction*) NULL);
   }

   /* Check for error */
   if(rv)
   {
      PRINT_ERROR("Installation of signal handlers failed");
      res = -1;
   }

   return(res);
}


/* ========================================================================== */
/*! \brief Prepare for \c exec()
 *
 * Restore default state for ignored signals.
 *
 * \return
 * - 0 on success
 * - Negative value on error
 */

int  sighandler_exec_prepare(void)
{
   int  res = 0;
   int  rv;
   struct_posix_sigaction  sa;

   posix_sigemptyset(&sa.sa_mask);
   sa.sa_flags = 0;

   /* Signals that should be ignored */
   sa.sa_handler = POSIX_SIG_DFL;
   rv = posix_sigaction(POSIX_SIGHUP, &sa, (struct_posix_sigaction*) NULL);
   if(!rv)
   {
      rv = posix_sigaction(POSIX_SIGPIPE, &sa, (struct_posix_sigaction*) NULL);
   }

   /* Check for error */
   if(rv)
   {
      PRINT_ERROR("Restore of default signal handlers failed");
      res = -1;
   }

   return(res);
}


/* ========================================================================== */
/*! \brief Check abort flag
 *
 * \return
 * - False if abort flag is not set
 * - True if abort flag is set
 */

int  sighandler_check_abort(void)
{
   return((int) sighandler_abort);
}


/*! @} */

/* EOF */
