/*
 * The Spar Library - a maths applications framework 
 * Copyright (C) 2000,2001 Davide Angelocola <davide178@inwind.it>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 *
 */

#include <spar/sl_application.h>

#include <stdio.h>

#if defined (HAVE_TERMIO_H)
#define TERMINAL_SUPPORT  1
#include <termio.h>
#elif defined (HAVE_TERMIOS_H)
#define TERMINAL_SUPPORT  1
#include <termios.h>
#elif defined (HAVE_TERMCAP_H)
#define TERMINAL_SUPPORT  1
#include <termcap.h>
#else
#define TERMINAL_SUPPORT 0
#endif

#include <signal.h>

#if (RETSIGTYPE == void)
#define SIGHANDLER_RETURN return
#else
#define SIGHANDLER_RETURN return (signal)
#endif

typedef RETSIGTYPE (*_sighandler) (int);
#define SL_SIGHANDLER(x)	RETSIGTYPE (x) (int signal)


extern void sl_application_exit (int _exit_code);

/* 
 *  sl will install its own signal handlers for
 *  	o SIGINT	(ctrl-C) 
 *  	o SIGTERM 
 *  	o SIGQUIT 
 *  	o SIGALRM 
 *  	o SIGTSTP 
 */

SL_SIGHANDLER (_ignore_this_signal)
{
  SIGHANDLER_RETURN;
}

SL_SIGHANDLER (_handle_this_signal)
{
  sl_application_exit (0);

  SIGHANDLER_RETURN;
}

/*
 *  Terminal support for this applications
 *
 *  This code is always present because it clean the memory
 *  on many signal interrupt (such as SIGINT, SIGSTOP, ecc)
 *  and set some other terminal option (such as disable the
 *  CTRL-D control char). 
 */

static void
_install_handler (void)
{
  struct sigaction setup_action;
  sigset_t block_mask;

  /* 
   *  Setting the block mask 
   */
  sigemptyset (&block_mask);
  sigaddset (&block_mask, SIGINT);
  sigaddset (&block_mask, SIGQUIT);

  /* 
   *  Setting action handler 
   */
  setup_action.sa_handler = sl_application_exit;
  setup_action.sa_mask = block_mask;
  setup_action.sa_flags = 0;
  sigaction (SIGTSTP, &setup_action, 0);

  return;
}

static struct termios _old_term;
static struct termios _new_term;

void
_restore_term (void)
{
  tcsetattr (fileno (stdin), TCSANOW, &_old_term);
}

/*
 *  Inits some terminal parameter such as:
 *  	o  inibiths the use of CTRL-D key
 *  	o  installs signals handlers
 *  	o  saves the old terminal configuration
 */
void
_init_term (void)
{
  _install_handler ();

  /*
   *  Setting signals handlers
   */
  signal (SIGINT, _handle_this_signal);
  signal (SIGQUIT, _handle_this_signal);
  signal (SIGKILL, _handle_this_signal);
  signal (SIGTERM, _handle_this_signal);
  signal (SIGALRM, _ignore_this_signal);
  signal (SIGTSTP, _ignore_this_signal);

#ifdef HAVE_TCGETATTR
  tcgetattr (fileno (stdin), &_old_term);
  _new_term = _old_term;
  _new_term.c_cc[VEOF] = 1;	/* don't allow CTRL-D */

  if ((tcsetattr (fileno (stdin), TCSAFLUSH, &_new_term)) < 0)
    {
      _restore_term ();
      sl_application_exit (SL_SUCCESS);
    }
#else
  sl_writeln ("%s: %s: ", __FILE__, __FUNCTION__);
  sl_writeln ("Failed to change terminal attributes: tcgetattr() is missing.");
  sl_writeln ("CTRL-D not handled: beware from use this control key."); 
#endif

  return;
}


syntax highlighted by Code2HTML, v. 0.9.1