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