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