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 12285612Sdelphijstatic ctrl_c_fn ctrl_c_hook; 13285612Sdelphij#ifndef SYS_WINNT 14285612SdelphijRETSIGTYPE sigint_handler(int); 15285612Sdelphij#else 16285612SdelphijBOOL WINAPI console_event_handler(DWORD); 17285612Sdelphij#endif 18285612Sdelphij 19285612Sdelphij 2054359Sroberto#ifdef HAVE_SIGACTION 2154359Sroberto 22285612Sdelphij# ifdef SA_RESTART 23285612Sdelphij# define Z_SA_RESTART SA_RESTART 24285612Sdelphij# else 25285612Sdelphij# define Z_SA_RESTART 0 26285612Sdelphij# endif 27285612Sdelphij 2854359Srobertovoid 2954359Srobertosignal_no_reset( 3054359Sroberto int sig, 31285612Sdelphij void (*func)(int) 3254359Sroberto ) 3354359Sroberto{ 3454359Sroberto int n; 3554359Sroberto struct sigaction vec; 36285612Sdelphij struct sigaction ovec; 3754359Sroberto 38285612Sdelphij ZERO(vec); 39285612Sdelphij sigemptyset(&vec.sa_mask); 4054359Sroberto vec.sa_handler = func; 4154359Sroberto 42285612Sdelphij /* Added for PPS clocks on Solaris 7 which get EINTR errors */ 4356746Sroberto# ifdef SIGPOLL 44285612Sdelphij if (SIGPOLL == sig) 45285612Sdelphij vec.sa_flags = Z_SA_RESTART; 4656746Sroberto# endif 4756746Sroberto# ifdef SIGIO 48285612Sdelphij if (SIGIO == sig) 49285612Sdelphij vec.sa_flags = Z_SA_RESTART; 5056746Sroberto# endif 5156746Sroberto 52285612Sdelphij do 5354359Sroberto n = sigaction(sig, &vec, &ovec); 54285612Sdelphij while (-1 == n && EINTR == errno); 55285612Sdelphij if (-1 == n) { 5654359Sroberto perror("sigaction"); 5754359Sroberto exit(1); 5854359Sroberto } 5954359Sroberto} 6054359Sroberto 6154359Sroberto#elif HAVE_SIGVEC 6254359Sroberto 6354359Srobertovoid 6454359Srobertosignal_no_reset( 6554359Sroberto int sig, 66285612Sdelphij RETSIGTYPE (*func)(int) 6754359Sroberto ) 6854359Sroberto{ 6954359Sroberto struct sigvec sv; 7054359Sroberto int n; 7154359Sroberto 72285612Sdelphij ZERO(sv); 7354359Sroberto sv.sv_handler = func; 7454359Sroberto n = sigvec(sig, &sv, (struct sigvec *)NULL); 75285612Sdelphij if (-1 == n) { 7654359Sroberto perror("sigvec"); 7754359Sroberto exit(1); 7854359Sroberto } 7954359Sroberto} 8054359Sroberto 8154359Sroberto#elif HAVE_SIGSET 8254359Sroberto 8354359Srobertovoid 8454359Srobertosignal_no_reset( 8554359Sroberto int sig, 86285612Sdelphij RETSIGTYPE (*func)(int) 8754359Sroberto ) 8854359Sroberto{ 8954359Sroberto int n; 9054359Sroberto 9154359Sroberto n = sigset(sig, func); 92285612Sdelphij 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, 104285612Sdelphij RETSIGTYPE (*func)(int) 10554359Sroberto ) 10654359Sroberto{ 107285612Sdelphij#ifndef SIG_ERR 108285612Sdelphij# define SIG_ERR (-1) 109285612Sdelphij#endif 11054359Sroberto if (SIG_ERR == signal(sig, func)) { 11154359Sroberto perror("signal"); 11254359Sroberto exit(1); 11354359Sroberto } 11454359Sroberto} 11554359Sroberto 11654359Sroberto#endif 117285612Sdelphij 118285612Sdelphij#ifndef SYS_WINNT 119285612Sdelphij/* 120285612Sdelphij * POSIX implementation of set_ctrl_c_hook() 121285612Sdelphij */ 122285612SdelphijRETSIGTYPE 123285612Sdelphijsigint_handler( 124285612Sdelphij int signum 125285612Sdelphij ) 126285612Sdelphij{ 127285612Sdelphij UNUSED_ARG(signum); 128285612Sdelphij if (ctrl_c_hook != NULL) 129285612Sdelphij (*ctrl_c_hook)(); 130285612Sdelphij} 131285612Sdelphij 132285612Sdelphijvoid 133285612Sdelphijset_ctrl_c_hook( 134285612Sdelphij ctrl_c_fn c_hook 135285612Sdelphij ) 136285612Sdelphij{ 137285612Sdelphij RETSIGTYPE (*handler)(int); 138285612Sdelphij 139285612Sdelphij if (NULL == c_hook) { 140285612Sdelphij handler = SIG_DFL; 141338531Sdelphij signal_no_reset(SIGINT, handler); 142338531Sdelphij ctrl_c_hook = c_hook; 143285612Sdelphij } else { 144338531Sdelphij ctrl_c_hook = c_hook; 145285612Sdelphij handler = &sigint_handler; 146338531Sdelphij signal_no_reset(SIGINT, handler); 147285612Sdelphij } 148285612Sdelphij} 149285612Sdelphij#else /* SYS_WINNT follows */ 150285612Sdelphij/* 151285612Sdelphij * Windows implementation of set_ctrl_c_hook() 152285612Sdelphij */ 153285612SdelphijBOOL WINAPI 154285612Sdelphijconsole_event_handler( 155285612Sdelphij DWORD dwCtrlType 156285612Sdelphij ) 157285612Sdelphij{ 158285612Sdelphij BOOL handled; 159285612Sdelphij 160285612Sdelphij if (CTRL_C_EVENT == dwCtrlType && ctrl_c_hook != NULL) { 161285612Sdelphij (*ctrl_c_hook)(); 162285612Sdelphij handled = TRUE; 163285612Sdelphij } else { 164285612Sdelphij handled = FALSE; 165285612Sdelphij } 166285612Sdelphij 167285612Sdelphij return handled; 168285612Sdelphij} 169285612Sdelphijvoid 170285612Sdelphijset_ctrl_c_hook( 171285612Sdelphij ctrl_c_fn c_hook 172285612Sdelphij ) 173285612Sdelphij{ 174285612Sdelphij BOOL install; 175285612Sdelphij 176285612Sdelphij if (NULL == c_hook) { 177285612Sdelphij ctrl_c_hook = NULL; 178285612Sdelphij install = FALSE; 179285612Sdelphij } else { 180285612Sdelphij ctrl_c_hook = c_hook; 181285612Sdelphij install = TRUE; 182285612Sdelphij } 183285612Sdelphij if (!SetConsoleCtrlHandler(&console_event_handler, install)) 184285612Sdelphij msyslog(LOG_ERR, "Can't %s console control handler: %m", 185285612Sdelphij (install) 186285612Sdelphij ? "add" 187285612Sdelphij : "remove"); 188285612Sdelphij} 189285612Sdelphij#endif /* SYS_WINNT */ 190