154359Sroberto#ifdef HAVE_CONFIG_H 254359Sroberto# include <config.h> 354359Sroberto#endif 454359Sroberto 554359Sroberto#include <stdio.h> 654359Sroberto#include <sys/types.h> 754359Sroberto#include <signal.h> 854359Sroberto 954359Sroberto#include "ntp_syslog.h" 1054359Sroberto#include "ntp_stdlib.h" 1154359Sroberto 12280849Scystatic ctrl_c_fn ctrl_c_hook; 13280849Scy#ifndef SYS_WINNT 14280849ScyRETSIGTYPE sigint_handler(int); 15280849Scy#else 16280849ScyBOOL WINAPI console_event_handler(DWORD); 17280849Scy#endif 18280849Scy 19280849Scy 2054359Sroberto#ifdef HAVE_SIGACTION 2154359Sroberto 22280849Scy# ifdef SA_RESTART 23280849Scy# define Z_SA_RESTART SA_RESTART 24280849Scy# else 25280849Scy# define Z_SA_RESTART 0 26280849Scy# endif 27280849Scy 2854359Srobertovoid 2954359Srobertosignal_no_reset( 3054359Sroberto int sig, 31280849Scy void (*func)(int) 3254359Sroberto ) 3354359Sroberto{ 3454359Sroberto int n; 3554359Sroberto struct sigaction vec; 36280849Scy struct sigaction ovec; 3754359Sroberto 38280849Scy ZERO(vec); 39280849Scy sigemptyset(&vec.sa_mask); 4054359Sroberto vec.sa_handler = func; 4154359Sroberto 42280849Scy /* Added for PPS clocks on Solaris 7 which get EINTR errors */ 4356746Sroberto# ifdef SIGPOLL 44280849Scy if (SIGPOLL == sig) 45280849Scy vec.sa_flags = Z_SA_RESTART; 4656746Sroberto# endif 4756746Sroberto# ifdef SIGIO 48280849Scy if (SIGIO == sig) 49280849Scy vec.sa_flags = Z_SA_RESTART; 5056746Sroberto# endif 5156746Sroberto 52280849Scy do 5354359Sroberto n = sigaction(sig, &vec, &ovec); 54280849Scy while (-1 == n && EINTR == errno); 55280849Scy if (-1 == n) { 5654359Sroberto perror("sigaction"); 5754359Sroberto exit(1); 5854359Sroberto } 5954359Sroberto} 6054359Sroberto 6154359Sroberto#elif HAVE_SIGVEC 6254359Sroberto 6354359Srobertovoid 6454359Srobertosignal_no_reset( 6554359Sroberto int sig, 66280849Scy RETSIGTYPE (*func)(int) 6754359Sroberto ) 6854359Sroberto{ 6954359Sroberto struct sigvec sv; 7054359Sroberto int n; 7154359Sroberto 72280849Scy ZERO(sv); 7354359Sroberto sv.sv_handler = func; 7454359Sroberto n = sigvec(sig, &sv, (struct sigvec *)NULL); 75280849Scy if (-1 == n) { 7654359Sroberto perror("sigvec"); 7754359Sroberto exit(1); 7854359Sroberto } 7954359Sroberto} 8054359Sroberto 8154359Sroberto#elif HAVE_SIGSET 8254359Sroberto 8354359Srobertovoid 8454359Srobertosignal_no_reset( 8554359Sroberto int sig, 86280849Scy RETSIGTYPE (*func)(int) 8754359Sroberto ) 8854359Sroberto{ 8954359Sroberto int n; 9054359Sroberto 9154359Sroberto n = sigset(sig, func); 92280849Scy if (-1 == n) { 9354359Sroberto perror("sigset"); 9454359Sroberto exit(1); 9554359Sroberto } 9654359Sroberto} 9754359Sroberto 9854359Sroberto#else 9954359Sroberto 10054359Sroberto/* Beware! This implementation resets the signal to SIG_DFL */ 10154359Srobertovoid 10254359Srobertosignal_no_reset( 10354359Sroberto int sig, 104280849Scy RETSIGTYPE (*func)(int) 10554359Sroberto ) 10654359Sroberto{ 107280849Scy#ifndef SIG_ERR 108280849Scy# define SIG_ERR (-1) 109280849Scy#endif 11054359Sroberto if (SIG_ERR == signal(sig, func)) { 11154359Sroberto perror("signal"); 11254359Sroberto exit(1); 11354359Sroberto } 11454359Sroberto} 11554359Sroberto 11654359Sroberto#endif 117280849Scy 118280849Scy#ifndef SYS_WINNT 119280849Scy/* 120280849Scy * POSIX implementation of set_ctrl_c_hook() 121280849Scy */ 122280849ScyRETSIGTYPE 123280849Scysigint_handler( 124280849Scy int signum 125280849Scy ) 126280849Scy{ 127280849Scy UNUSED_ARG(signum); 128280849Scy if (ctrl_c_hook != NULL) 129280849Scy (*ctrl_c_hook)(); 130280849Scy} 131280849Scy 132280849Scyvoid 133280849Scyset_ctrl_c_hook( 134280849Scy ctrl_c_fn c_hook 135280849Scy ) 136280849Scy{ 137280849Scy RETSIGTYPE (*handler)(int); 138280849Scy 139280849Scy if (NULL == c_hook) { 140280849Scy handler = SIG_DFL; 141338530Sdelphij signal_no_reset(SIGINT, handler); 142338530Sdelphij ctrl_c_hook = c_hook; 143280849Scy } else { 144338530Sdelphij ctrl_c_hook = c_hook; 145280849Scy handler = &sigint_handler; 146338530Sdelphij signal_no_reset(SIGINT, handler); 147280849Scy } 148280849Scy} 149280849Scy#else /* SYS_WINNT follows */ 150280849Scy/* 151280849Scy * Windows implementation of set_ctrl_c_hook() 152280849Scy */ 153280849ScyBOOL WINAPI 154280849Scyconsole_event_handler( 155280849Scy DWORD dwCtrlType 156280849Scy ) 157280849Scy{ 158280849Scy BOOL handled; 159280849Scy 160280849Scy if (CTRL_C_EVENT == dwCtrlType && ctrl_c_hook != NULL) { 161280849Scy (*ctrl_c_hook)(); 162280849Scy handled = TRUE; 163280849Scy } else { 164280849Scy handled = FALSE; 165280849Scy } 166280849Scy 167280849Scy return handled; 168280849Scy} 169280849Scyvoid 170280849Scyset_ctrl_c_hook( 171280849Scy ctrl_c_fn c_hook 172280849Scy ) 173280849Scy{ 174280849Scy BOOL install; 175280849Scy 176280849Scy if (NULL == c_hook) { 177280849Scy ctrl_c_hook = NULL; 178280849Scy install = FALSE; 179280849Scy } else { 180280849Scy ctrl_c_hook = c_hook; 181280849Scy install = TRUE; 182280849Scy } 183280849Scy if (!SetConsoleCtrlHandler(&console_event_handler, install)) 184280849Scy msyslog(LOG_ERR, "Can't %s console control handler: %m", 185280849Scy (install) 186280849Scy ? "add" 187280849Scy : "remove"); 188280849Scy} 189280849Scy#endif /* SYS_WINNT */ 190