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
signal_no_reset(int sig,void (* func)(int))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
signal_no_reset(int sig,RETSIGTYPE (* func)(int))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
signal_no_reset(int sig,RETSIGTYPE (* func)(int))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
signal_no_reset(int sig,RETSIGTYPE (* func)(int))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
sigint_handler(int signum)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
set_ctrl_c_hook(ctrl_c_fn c_hook)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
console_event_handler(DWORD dwCtrlType)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
set_ctrl_c_hook(ctrl_c_fn c_hook)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