/* Copyright (C) 1993,1994 by the author(s).
 
 This software is published in the hope that it will be useful, but
 WITHOUT ANY WARRANTY for any part of this software to work correctly
 or as described in the manuals. See the ShapeTools Public License
 for details.

 Permission is granted to use, copy, modify, or distribute any part of
 this software but only under the conditions described in the ShapeTools 
 Public License. A copy of this license is supposed to have been given
 to you along with ShapeTools in a file named LICENSE. Among other
 things, this copyright notice and the Public License must be
 preserved on all copies.
 */
/*
 * sighand.c -- ShapeTools toolkit library
 *
 * Authors: Axel Mahler (Axel.Mahler@cs.tu-berlin.de)
 *          Andreas Lampen (Andreas.Lampen@cs.tu-berlin.de)
 *  $Header: sighand.c[4.0] Mon Jul  5 18:36:25 1993 axel@cs.tu-berlin.de frozen $
 */

#include "atfs.h"
#include "sttk.h"

EXPORT struct stTransaction stThisTransaction = {"",0,0,0,{0}};

/*=========
 * quit
 *=========*/

LOCAL void quit () {
  signal (SIGQUIT, SIG_DFL);
  kill (getpid(), SIGQUIT);
}


/*========================
 * cleanup and exit
 *========================*/

EXPORT void stCleanup ()
{
  fflush (stdout);
  stRmRegisteredFiles ();
  af_cleanup();
}

EXPORT void stExit (i)
     int i;
{
  stCleanup();
  exit(i);
}

/*=====================
 * signal handlers
 *=====================*/

EXPORT Sigret_t (*stInterruptAction)(), (*stQuitAction)(), (*stTermAction)();

LOCAL Sigret_t die2 ()
{
  disableSig (SIGINT);
  signal (SIGINT, die2);
  enableSig ();
  if (stInterruptAction)
    stInterruptAction();
}

LOCAL Sigret_t die3 ()
{
  disableSig (SIGQUIT);     
  stLog ("Oh! Oh! ... received SIGQUIT -- goodbye.\n", ST_LOG_ERROR);
  if (stQuitAction)
    stQuitAction ();
  stCleanup ();
  enableSig ();
  quit ();
}

LOCAL Sigret_t die8 ()
{
  disableSig (SIGFPE);     
  stLog ("Oh! Oh! ... this was a floating exception -- goodbye.\n", ST_LOG_ERROR); 
  if (stQuitAction)
    stQuitAction ();
  stCleanup ();
  enableSig ();
  quit ();
}

LOCAL Sigret_t die10 ()
{
  disableSig (SIGBUS);     
  stLog ("Oh! Oh! ... this was a buserror -- goodbye.\n", ST_LOG_ERROR);
  stLog ("Dumping core...", ST_LOG_ERROR);
  if (stQuitAction)
    stQuitAction ();
  stCleanup ();
  enableSig ();
  quit ();
}

LOCAL Sigret_t die11 ()
{
  disableSig (SIGSEGV);     
  stLog ("Oh! Oh! ... this was a segmentation violation -- goodbye.\n", ST_LOG_ERROR);
  stLog ("Dumping core...", ST_LOG_ERROR);
  if (stQuitAction)
    stQuitAction ();
  stCleanup ();
  enableSig ();
  quit ();
}

LOCAL Sigret_t die13 ()
{
  disableSig (SIGPIPE);     
  stCleanup ();
  enableSig ();
  quit ();
}

LOCAL Sigret_t die15 ()
{
  stLog ("Aborted ... goodbye.\n", ST_LOG_MSGERR);
  disableSig (SIGTERM);     
  if (stTermAction)
    stTermAction ();
  stCleanup ();
  enableSig ();
  quit ();
}

/*================
 * catch signals
 *================*/

EXPORT void stCatchSigs ()
{
  /* Setup signal handlers for various signals.
   * On receipt of a signal, the 
   * original handler for this signal will be invoked after specified
   * action has been taken.
   */
  signal (SIGINT, die2);
  signal (SIGQUIT, die3);
  signal (SIGFPE, die8);
  signal (SIGBUS, die10);
  signal (SIGSEGV, die11);
  signal (SIGPIPE, die13);
  signal (SIGTERM, die15);
}

/*====================
 * abort transaction
 *====================*/

EXPORT void stAbortThis (domsg)
     int domsg;
{
  /* abort current execution phase and restore
   * a clean context for next phase
   */
  if (domsg)
    stLog ("...aborting", ST_LOG_MSGERR);
  stRmRegisteredFiles ();
  if (!stThisTransaction.tr_rc)
    stThisTransaction.tr_rc = TRUE;
  longjmp (stThisTransaction.tr_env, 1);
}
