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 12290000Sglebiusstatic ctrl_c_fn ctrl_c_hook; 13290000Sglebius#ifndef SYS_WINNT 14290000SglebiusRETSIGTYPE sigint_handler(int); 15290000Sglebius#else 16290000SglebiusBOOL WINAPI console_event_handler(DWORD); 17290000Sglebius#endif 18290000Sglebius 19290000Sglebius 2054359Sroberto#ifdef HAVE_SIGACTION 2154359Sroberto 22290000Sglebius# ifdef SA_RESTART 23290000Sglebius# define Z_SA_RESTART SA_RESTART 24290000Sglebius# else 25290000Sglebius# define Z_SA_RESTART 0 26290000Sglebius# endif 27290000Sglebius 2854359Srobertovoid 2954359Srobertosignal_no_reset( 3054359Sroberto int sig, 31290000Sglebius void (*func)(int) 3254359Sroberto ) 3354359Sroberto{ 3454359Sroberto int n; 3554359Sroberto struct sigaction vec; 36290000Sglebius struct sigaction ovec; 3754359Sroberto 38290000Sglebius ZERO(vec); 39290000Sglebius sigemptyset(&vec.sa_mask); 4054359Sroberto vec.sa_handler = func; 4154359Sroberto 42290000Sglebius /* Added for PPS clocks on Solaris 7 which get EINTR errors */ 4356746Sroberto# ifdef SIGPOLL 44290000Sglebius if (SIGPOLL == sig) 45290000Sglebius vec.sa_flags = Z_SA_RESTART; 4656746Sroberto# endif 4756746Sroberto# ifdef SIGIO 48290000Sglebius if (SIGIO == sig) 49290000Sglebius vec.sa_flags = Z_SA_RESTART; 5056746Sroberto# endif 5156746Sroberto 52290000Sglebius do 5354359Sroberto n = sigaction(sig, &vec, &ovec); 54290000Sglebius while (-1 == n && EINTR == errno); 55290000Sglebius if (-1 == n) { 5654359Sroberto perror("sigaction"); 5754359Sroberto exit(1); 5854359Sroberto } 5954359Sroberto} 6054359Sroberto 6154359Sroberto#elif HAVE_SIGVEC 6254359Sroberto 6354359Srobertovoid 6454359Srobertosignal_no_reset( 6554359Sroberto int sig, 66290000Sglebius RETSIGTYPE (*func)(int) 6754359Sroberto ) 6854359Sroberto{ 6954359Sroberto struct sigvec sv; 7054359Sroberto int n; 7154359Sroberto 72290000Sglebius ZERO(sv); 7354359Sroberto sv.sv_handler = func; 7454359Sroberto n = sigvec(sig, &sv, (struct sigvec *)NULL); 75290000Sglebius if (-1 == n) { 7654359Sroberto perror("sigvec"); 7754359Sroberto exit(1); 7854359Sroberto } 7954359Sroberto} 8054359Sroberto 8154359Sroberto#elif HAVE_SIGSET 8254359Sroberto 8354359Srobertovoid 8454359Srobertosignal_no_reset( 8554359Sroberto int sig, 86290000Sglebius RETSIGTYPE (*func)(int) 8754359Sroberto ) 8854359Sroberto{ 8954359Sroberto int n; 9054359Sroberto 9154359Sroberto n = sigset(sig, func); 92290000Sglebius 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, 104290000Sglebius RETSIGTYPE (*func)(int) 10554359Sroberto ) 10654359Sroberto{ 107290000Sglebius#ifndef SIG_ERR 108290000Sglebius# define SIG_ERR (-1) 109290000Sglebius#endif 11054359Sroberto if (SIG_ERR == signal(sig, func)) { 11154359Sroberto perror("signal"); 11254359Sroberto exit(1); 11354359Sroberto } 11454359Sroberto} 11554359Sroberto 11654359Sroberto#endif 117290000Sglebius 118290000Sglebius#ifndef SYS_WINNT 119290000Sglebius/* 120290000Sglebius * POSIX implementation of set_ctrl_c_hook() 121290000Sglebius */ 122290000SglebiusRETSIGTYPE 123290000Sglebiussigint_handler( 124290000Sglebius int signum 125290000Sglebius ) 126290000Sglebius{ 127290000Sglebius UNUSED_ARG(signum); 128290000Sglebius if (ctrl_c_hook != NULL) 129290000Sglebius (*ctrl_c_hook)(); 130290000Sglebius} 131290000Sglebius 132290000Sglebiusvoid 133290000Sglebiusset_ctrl_c_hook( 134290000Sglebius ctrl_c_fn c_hook 135290000Sglebius ) 136290000Sglebius{ 137290000Sglebius RETSIGTYPE (*handler)(int); 138290000Sglebius 139290000Sglebius if (NULL == c_hook) { 140290000Sglebius handler = SIG_DFL; 141290000Sglebius ctrl_c_hook = NULL; 142290000Sglebius } else { 143290000Sglebius handler = &sigint_handler; 144290000Sglebius ctrl_c_hook = c_hook; 145290000Sglebius } 146290000Sglebius signal_no_reset(SIGINT, handler); 147290000Sglebius} 148290000Sglebius#else /* SYS_WINNT follows */ 149290000Sglebius/* 150290000Sglebius * Windows implementation of set_ctrl_c_hook() 151290000Sglebius */ 152290000SglebiusBOOL WINAPI 153290000Sglebiusconsole_event_handler( 154290000Sglebius DWORD dwCtrlType 155290000Sglebius ) 156290000Sglebius{ 157290000Sglebius BOOL handled; 158290000Sglebius 159290000Sglebius if (CTRL_C_EVENT == dwCtrlType && ctrl_c_hook != NULL) { 160290000Sglebius (*ctrl_c_hook)(); 161290000Sglebius handled = TRUE; 162290000Sglebius } else { 163290000Sglebius handled = FALSE; 164290000Sglebius } 165290000Sglebius 166290000Sglebius return handled; 167290000Sglebius} 168290000Sglebiusvoid 169290000Sglebiusset_ctrl_c_hook( 170290000Sglebius ctrl_c_fn c_hook 171290000Sglebius ) 172290000Sglebius{ 173290000Sglebius BOOL install; 174290000Sglebius 175290000Sglebius if (NULL == c_hook) { 176290000Sglebius ctrl_c_hook = NULL; 177290000Sglebius install = FALSE; 178290000Sglebius } else { 179290000Sglebius ctrl_c_hook = c_hook; 180290000Sglebius install = TRUE; 181290000Sglebius } 182290000Sglebius if (!SetConsoleCtrlHandler(&console_event_handler, install)) 183290000Sglebius msyslog(LOG_ERR, "Can't %s console control handler: %m", 184290000Sglebius (install) 185290000Sglebius ? "add" 186290000Sglebius : "remove"); 187290000Sglebius} 188290000Sglebius#endif /* SYS_WINNT */ 189