// -*- c++ -*- //--------------------------------------------------------------------------- // SigHandler.cpp //--------------------------------------------------------------------------- // Copyright (C) 1997-2002 Vladislav Grinchenko // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. //--------------------------------------------------------------------------- #include #include "assa/Assure.h" #include "assa/SigHandler.h" using namespace ASSA; #if !defined(WIN32) /*--- static variables ---*/ EventHandler* SigHandler::m_signal_handlers [NSIG]; int SigHandler:: in_range (int signum_) { trace_with_mask("SigHandler::in_range", SIGHAND); if ( signum_ >= 1 && signum_ < NSIG) { return 0; } else { DL((SIGHAND,"signum_ %d is out of range [1;%d]\n", NSIG)); return -1; } } EventHandler * SigHandler:: handler (int signum_, EventHandler* newh_) { trace_with_mask("SigHandler::handler(int, EH*)", SIGHAND); if (in_range(signum_) == -1) return 0; EventHandler* oh = m_signal_handlers[signum_]; m_signal_handlers[signum_] = newh_; return oh; } EventHandler * SigHandler:: handler (int signum_) { trace_with_mask("SigHandler::handler", SIGHAND); if ( in_range (signum_) == -1 ) return 0; return m_signal_handlers[signum_]; } int SigHandler:: install (int signum_, EventHandler *new_hand_, SigAction *new_disp_, EventHandler **old_hand_, SigAction *old_disp_) { trace_with_mask("SigHandler::install", SIGHAND); if (in_range (signum_) == -1) return -1; /*--- replace old Event Handler ptr with new one in my internal dispatch table, returning the old one. ---*/ EventHandler* eh = handler(signum_, new_hand_); /*--- if I am given place to store, save old handler ---*/ if (old_hand_ != 0) *old_hand_ = eh; /*--- retrieve old disposition ---*/ if (old_disp_ != 0) { old_disp_->retrieve_action (signum_); old_disp_->handler ((C_SIG_HANDLER) SIG_DFL); } /*--- if new disposition is NULL, use null action instead ---*/ SigAction null_sa; if (new_disp_ == 0) new_disp_ = &null_sa; /*--- install my dispatcher ---*/ new_disp_->handler((C_SIG_HANDLER) SigHandler::dispatch); return new_disp_->register_action(signum_, old_disp_); } int SigHandler:: remove (int signum_, EventHandler* /* eh_ */, SigAction *new_disp_, SigAction *old_disp_) { trace_with_mask("SigHandler::remove", SIGHAND); if (in_range(signum_) == -1) return -1; /*--- We need default disposition here if user forgot to give us one. ---*/ SigAction sa ((C_SIG_HANDLER) SIG_DFL); if (new_disp_ == 0) { new_disp_ = &sa; } m_signal_handlers[signum_] = 0; return new_disp_->register_action (signum_, old_disp_); } void SigHandler:: dispatch (int signum_) { trace_with_mask("SigHandler::dispatch", SIGHAND); /*--- save errno ---*/ int my_errno = errno; EventHandler *eh = m_signal_handlers[signum_]; if (eh != 0 && eh->handle_signal(signum_) == -1) { /*--- we are in trouble, fall back to defaults ---*/ SigAction defact((C_SIG_HANDLER) SIG_DFL); m_signal_handlers[signum_] = 0; defact.register_action(signum_); } /*--- restore errno ---*/ errno = my_errno; } #endif // !defined(WIN32)