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 signal_no_reset(SIGINT, handler); 142 ctrl_c_hook = c_hook; 143 } else { 144 ctrl_c_hook = c_hook; 145 handler = &sigint_handler; 146 signal_no_reset(SIGINT, handler); 147 } 148 } 149 #else /* SYS_WINNT follows */ 150 /* 151 * Windows implementation of set_ctrl_c_hook() 152 */ 153 BOOL WINAPI 154 console_event_handler( 155 DWORD dwCtrlType 156 ) 157 { 158 BOOL handled; 159 160 if (CTRL_C_EVENT == dwCtrlType && ctrl_c_hook != NULL) { 161 (*ctrl_c_hook)(); 162 handled = TRUE; 163 } else { 164 handled = FALSE; 165 } 166 167 return handled; 168 } 169 void 170 set_ctrl_c_hook( 171 ctrl_c_fn c_hook 172 ) 173 { 174 BOOL install; 175 176 if (NULL == c_hook) { 177 ctrl_c_hook = NULL; 178 install = FALSE; 179 } else { 180 ctrl_c_hook = c_hook; 181 install = TRUE; 182 } 183 if (!SetConsoleCtrlHandler(&console_event_handler, install)) 184 msyslog(LOG_ERR, "Can't %s console control handler: %m", 185 (install) 186 ? "add" 187 : "remove"); 188 } 189 #endif /* SYS_WINNT */ 190