1 /* $NetBSD: syssignal.c,v 1.4 2016/01/08 21:35:39 christos Exp $ */ 2 3 #ifdef HAVE_CONFIG_H 4 # include <config.h> 5 #endif 6 7 #include <stdio.h> 8 #include <sys/types.h> 9 #include <signal.h> 10 11 #include "ntp_syslog.h" 12 #include "ntp_stdlib.h" 13 14 static ctrl_c_fn ctrl_c_hook; 15 #ifndef SYS_WINNT 16 RETSIGTYPE sigint_handler(int); 17 #else 18 BOOL WINAPI console_event_handler(DWORD); 19 #endif 20 21 22 #ifdef HAVE_SIGACTION 23 24 # ifdef SA_RESTART 25 # define Z_SA_RESTART SA_RESTART 26 # else 27 # define Z_SA_RESTART 0 28 # endif 29 30 void 31 signal_no_reset( 32 int sig, 33 void (*func)(int) 34 ) 35 { 36 int n; 37 struct sigaction vec; 38 struct sigaction ovec; 39 40 ZERO(vec); 41 sigemptyset(&vec.sa_mask); 42 vec.sa_handler = func; 43 44 /* Added for PPS clocks on Solaris 7 which get EINTR errors */ 45 # ifdef SIGPOLL 46 if (SIGPOLL == sig) 47 vec.sa_flags = Z_SA_RESTART; 48 # endif 49 # ifdef SIGIO 50 if (SIGIO == sig) 51 vec.sa_flags = Z_SA_RESTART; 52 # endif 53 54 do 55 n = sigaction(sig, &vec, &ovec); 56 while (-1 == n && EINTR == errno); 57 if (-1 == n) { 58 perror("sigaction"); 59 exit(1); 60 } 61 } 62 63 #elif HAVE_SIGVEC 64 65 void 66 signal_no_reset( 67 int sig, 68 RETSIGTYPE (*func)(int) 69 ) 70 { 71 struct sigvec sv; 72 int n; 73 74 ZERO(sv); 75 sv.sv_handler = func; 76 n = sigvec(sig, &sv, (struct sigvec *)NULL); 77 if (-1 == n) { 78 perror("sigvec"); 79 exit(1); 80 } 81 } 82 83 #elif HAVE_SIGSET 84 85 void 86 signal_no_reset( 87 int sig, 88 RETSIGTYPE (*func)(int) 89 ) 90 { 91 int n; 92 93 n = sigset(sig, func); 94 if (-1 == n) { 95 perror("sigset"); 96 exit(1); 97 } 98 } 99 100 #else 101 102 /* Beware! This implementation resets the signal to SIG_DFL */ 103 void 104 signal_no_reset( 105 int sig, 106 RETSIGTYPE (*func)(int) 107 ) 108 { 109 #ifndef SIG_ERR 110 # define SIG_ERR (-1) 111 #endif 112 if (SIG_ERR == signal(sig, func)) { 113 perror("signal"); 114 exit(1); 115 } 116 } 117 118 #endif 119 120 #ifndef SYS_WINNT 121 /* 122 * POSIX implementation of set_ctrl_c_hook() 123 */ 124 RETSIGTYPE 125 sigint_handler( 126 int signum 127 ) 128 { 129 UNUSED_ARG(signum); 130 if (ctrl_c_hook != NULL) 131 (*ctrl_c_hook)(); 132 } 133 134 void 135 set_ctrl_c_hook( 136 ctrl_c_fn c_hook 137 ) 138 { 139 RETSIGTYPE (*handler)(int); 140 141 if (NULL == c_hook) { 142 handler = SIG_DFL; 143 ctrl_c_hook = NULL; 144 } else { 145 handler = &sigint_handler; 146 ctrl_c_hook = c_hook; 147 } 148 signal_no_reset(SIGINT, handler); 149 } 150 #else /* SYS_WINNT follows */ 151 /* 152 * Windows implementation of set_ctrl_c_hook() 153 */ 154 BOOL WINAPI 155 console_event_handler( 156 DWORD dwCtrlType 157 ) 158 { 159 BOOL handled; 160 161 if (CTRL_C_EVENT == dwCtrlType && ctrl_c_hook != NULL) { 162 (*ctrl_c_hook)(); 163 handled = TRUE; 164 } else { 165 handled = FALSE; 166 } 167 168 return handled; 169 } 170 void 171 set_ctrl_c_hook( 172 ctrl_c_fn c_hook 173 ) 174 { 175 BOOL install; 176 177 if (NULL == c_hook) { 178 ctrl_c_hook = NULL; 179 install = FALSE; 180 } else { 181 ctrl_c_hook = c_hook; 182 install = TRUE; 183 } 184 if (!SetConsoleCtrlHandler(&console_event_handler, install)) 185 msyslog(LOG_ERR, "Can't %s console control handler: %m", 186 (install) 187 ? "add" 188 : "remove"); 189 } 190 #endif /* SYS_WINNT */ 191