#ifdef HAVE_CONFIG_H # include #endif #include #include #include #include "ntp_syslog.h" #include "ntp_stdlib.h" static ctrl_c_fn ctrl_c_hook; #ifndef SYS_WINNT RETSIGTYPE sigint_handler(int); #else BOOL WINAPI console_event_handler(DWORD); #endif #ifdef HAVE_SIGACTION # ifdef SA_RESTART # define Z_SA_RESTART SA_RESTART # else # define Z_SA_RESTART 0 # endif void signal_no_reset( int sig, void (*func)(int) ) { int n; struct sigaction vec; struct sigaction ovec; ZERO(vec); sigemptyset(&vec.sa_mask); vec.sa_handler = func; /* Added for PPS clocks on Solaris 7 which get EINTR errors */ # ifdef SIGPOLL if (SIGPOLL == sig) vec.sa_flags = Z_SA_RESTART; # endif # ifdef SIGIO if (SIGIO == sig) vec.sa_flags = Z_SA_RESTART; # endif do n = sigaction(sig, &vec, &ovec); while (-1 == n && EINTR == errno); if (-1 == n) { perror("sigaction"); exit(1); } } #elif HAVE_SIGVEC void signal_no_reset( int sig, RETSIGTYPE (*func)(int) ) { struct sigvec sv; int n; ZERO(sv); sv.sv_handler = func; n = sigvec(sig, &sv, (struct sigvec *)NULL); if (-1 == n) { perror("sigvec"); exit(1); } } #elif HAVE_SIGSET void signal_no_reset( int sig, RETSIGTYPE (*func)(int) ) { int n; n = sigset(sig, func); if (-1 == n) { perror("sigset"); exit(1); } } #else /* Beware! This implementation resets the signal to SIG_DFL */ void signal_no_reset( int sig, RETSIGTYPE (*func)(int) ) { #ifndef SIG_ERR # define SIG_ERR (-1) #endif if (SIG_ERR == signal(sig, func)) { perror("signal"); exit(1); } } #endif #ifndef SYS_WINNT /* * POSIX implementation of set_ctrl_c_hook() */ RETSIGTYPE sigint_handler( int signum ) { UNUSED_ARG(signum); if (ctrl_c_hook != NULL) (*ctrl_c_hook)(); } void set_ctrl_c_hook( ctrl_c_fn c_hook ) { RETSIGTYPE (*handler)(int); if (NULL == c_hook) { handler = SIG_DFL; ctrl_c_hook = NULL; } else { handler = &sigint_handler; ctrl_c_hook = c_hook; } signal_no_reset(SIGINT, handler); } #else /* SYS_WINNT follows */ /* * Windows implementation of set_ctrl_c_hook() */ BOOL WINAPI console_event_handler( DWORD dwCtrlType ) { BOOL handled; if (CTRL_C_EVENT == dwCtrlType && ctrl_c_hook != NULL) { (*ctrl_c_hook)(); handled = TRUE; } else { handled = FALSE; } return handled; } void set_ctrl_c_hook( ctrl_c_fn c_hook ) { BOOL install; if (NULL == c_hook) { ctrl_c_hook = NULL; install = FALSE; } else { ctrl_c_hook = c_hook; install = TRUE; } if (!SetConsoleCtrlHandler(&console_event_handler, install)) msyslog(LOG_ERR, "Can't %s console control handler: %m", (install) ? "add" : "remove"); } #endif /* SYS_WINNT */