/* $Id: SignalHandler,v 1.1.1.1 2008/11/28 17:57:26 kiesling Exp $ -*-c-mode-*-*/

/*
  This file is part of ctalk.
  Copyright  2005-2008  Robert Kiesling, ctalk@ctalklang.org.
  Permission is granted to copy this software provided that this copyright
  notice is included in all source code modules.

  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 of the License, or (at your option) any later version.

  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
*/

/*
 *   SignalHandler Class
 */

#if defined(__sparc__) && defined(__svr4__)
#define __EXTENSIONS__
#endif
#include <signal.h>

/*
 *  Attributes for signal handlers.
 */
#define SIG_DEFAULT (1 << 0)
#define SIG_IGNORE  (1 << 1)
#define SIG_METHOD  (1 << 2)

SignalEvent class SignalHandler;

SignalHandler instanceVariable attributes Integer SIG_DEFAULT;
SignalHandler instanceVariable handler Symbol 0x0;

SignalHandler instanceMethod new (char *__newHandlerName) {

  SignalHandler super new __newHandlerName;

  __ctalkInstanceVarsFromClassObject (__newHandlerName);

  methodReturnObject(__newHandlerName)
}

SignalHandler instanceMethod setSigNo (Integer signo) {
  self addInstanceVariable "sigNo", signo;
  methodReturnSelf
}

SignalHandler instanceMethod setSigHup (void) {
  Integer new sigNoVar;
  sigNoVar = SIGHUP;
  self addInstanceVariable "sigNo", sigNoVar;
  methodReturnSelf
}

SignalHandler instanceMethod setSigInt (void) {
  Integer new sigNoVar;
  sigNoVar = SIGINT;
  self addInstanceVariable "sigNo", sigNoVar;
  methodReturnSelf
}

SignalHandler instanceMethod setSigQuit (void) {
  Integer new sigNoVar;
  sigNoVar = SIGQUIT;
  self addInstanceVariable "sigNo", sigNoVar;
  methodReturnSelf
}

SignalHandler instanceMethod setSigIll (void) {
  Integer new sigNoVar;
  sigNoVar = SIGILL;
  self addInstanceVariable "sigNo", sigNoVar;
  methodReturnSelf
}

SignalHandler instanceMethod setSigAbrt (void) {
  Integer new sigNoVar;
  sigNoVar = SIGABRT;
  self addInstanceVariable "sigNo", sigNoVar;
  methodReturnSelf
}

SignalHandler instanceMethod setSigFpe (void) {
  Integer new sigNoVar;
  sigNoVar = SIGFPE;
  self addInstanceVariable "sigNo", sigNoVar;
  methodReturnSelf
}

SignalHandler instanceMethod setSigSegv (void) {
  Integer new sigNoVar;
  sigNoVar = SIGSEGV;
  self addInstanceVariable "sigNo", sigNoVar;
  methodReturnSelf
}

SignalHandler instanceMethod setSigPipe (void) {
  Integer new sigNoVar;
  sigNoVar = SIGPIPE;
  self addInstanceVariable "sigNo", sigNoVar;
  methodReturnSelf
}

SignalHandler instanceMethod setSigAlrm (void) {
  Integer new sigNoVar;
  sigNoVar = SIGALRM;
  self addInstanceVariable "sigNo", sigNoVar;
  methodReturnSelf
}

SignalHandler instanceMethod setSigTerm (void) {
  Integer new sigNoVar;
  sigNoVar = SIGTERM;
  self addInstanceVariable "sigNo", sigNoVar;
  methodReturnSelf
}

SignalHandler instanceMethod setSigUsr1 (void) {
  Integer new sigNoVar;
  sigNoVar = SIGUSR1;
  self addInstanceVariable "sigNo", sigNoVar;
  methodReturnSelf
}

SignalHandler instanceMethod setSigUsr2 (void) {
  Integer new sigNoVar;
  sigNoVar = SIGUSR2;
  self addInstanceVariable "sigNo", sigNoVar;
  methodReturnSelf
}

SignalHandler instanceMethod setSigChld (void) {
  Integer new sigNoVar;
  sigNoVar = SIGCHLD;
  self addInstanceVariable "sigNo", sigNoVar;
  methodReturnSelf
}

SignalHandler instanceMethod setSigCont (void) {
  Integer new sigNoVar;
  sigNoVar = SIGCONT;
  self addInstanceVariable "sigNo", sigNoVar;
  methodReturnSelf
}

SignalHandler instanceMethod setSigTstp (void) {
  Integer new sigNoVar;
  sigNoVar = SIGTSTP;
  self addInstanceVariable "sigNo", sigNoVar;
  methodReturnSelf
}

SignalHandler instanceMethod setSigTtin (void) {
  Integer new sigNoVar;
  sigNoVar = SIGTTIN;
  self addInstanceVariable "sigNo", sigNoVar;
  methodReturnSelf
}

SignalHandler instanceMethod setSigTtou (void) {
  Integer new sigNoVar;
  sigNoVar = SIGTTOU;
  self addInstanceVariable "sigNo", sigNoVar;
  methodReturnSelf
}

SignalHandler instanceMethod ignoreSignal (void) {
  Integer new attrVar;
  OBJECT *signo_var, *attr_var;
  int signo;

  signo_var = self sigNo;
  signo = __ctalk_to_c_int (signo_var);
  if (signo <= 0) {
    _warning ("Invalid signal number %d.\n", signo);
  }
#if defined(__sparc__) && defined(__svr4__)
  sigignore (signo);
#else
  signal (signo, SIG_IGN);
#endif
  attrVar = SIG_IGNORE;
  self addInstanceVariable "attributes", attrVar;
  methodReturnSelf
}

SignalHandler instanceMethod defaultHandler (void) {
  Integer new attrVar;
  OBJECT *signo_var, *attr_var;
  int signo;

  signo_var = self sigNo;
  signo = __ctalk_to_c_int (signo_var);
  if (signo <= 0) {
    _warning ("Invalid signal number %d.\n", signo);
  }
#if defined(__sparc__) && defined(__svr4__)
  sigrelse (signo);
#else
  signal (signo, SIG_DFL);
#endif
  attrVar = SIG_DEFAULT;
  self addInstanceVariable "attributes", attrVar;
  methodReturnSelf
}

SignalHandler instanceMethod installHandler (OBJECT *(*sigfn)()) {
  Integer new attrVar;
  OBJECT *(*fn)(), *rcvr_obj, *signo_var;
  METHOD *self_method, *arg_method;
  int signo;
  struct sigaction s, old_s;
  fn = (OBJECT *(*)())__ctalkRtGetMethodFn ();
  rcvr_obj = __ctalkRtReceiverObject ();

  if (((self_method = __ctalkFindInstanceMethodByFn (&rcvr_obj, fn, 0))
      == NULL) &&
      ((self_method = __ctalkFindClassMethodByFn (&rcvr_obj, fn, 0))
       == NULL)) {
    __ctalkCriticalExceptionInternal (NULL, undefined_method_x, 
			      "from installHandler (Class SignalHandler)");
    return NULL;
  }
  if (((arg_method = __ctalkFindInstanceMethodByName (&rcvr_obj, 
			      self_method->args[0] -> __o_name, 0))
      == NULL) &&
      ((arg_method = __ctalkFindClassMethodByName (&rcvr_obj, 
				 self_method->args[0]->__o_name, 0))
       == NULL)) {
    __ctalkCriticalExceptionInternal (NULL, undefined_method_x, 
				      "from map (Class Array)");
    return NULL;
  }
  signo_var = self sigNo;
  signo = __ctalk_to_c_int (signo_var);
  s.sa_handler = (void (*)())arg_method -> cfunc;
  s.sa_flags = 0;
  sigaction (signo, &s, &old_s);
  attrVar = SIG_METHOD;
  self addInstanceVariable "attributes", attrVar;
  methodReturnSelf
}

SignalHandler instanceMethod raiseSignal (void) {
  OBJECT *signo_var;
  int signo;
  signo_var = self sigNo;
  signo = __ctalk_to_c_int(signo_var);
  raise (signo);
  methodReturnSelf
}

SignalHandler instanceMethod signalProcessID (int processid) {
  OBJECT *signo_var;
  int signo;
  signo_var = self sigNo;
  signo = __ctalk_to_c_int(signo_var);
  kill (__ctalk_to_c_int(ARG(0)), signo);
  methodReturnSelf
}
