xref: /netbsd-src/external/bsd/ntp/dist/libntp/syssignal.c (revision cdfa2a7ef92791ba9db70a584a1d904730e6fb46)
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
signal_no_reset(int sig,void (* func)(int))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
signal_no_reset(int sig,RETSIGTYPE (* func)(int))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
signal_no_reset(int sig,RETSIGTYPE (* func)(int))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
signal_no_reset(int sig,RETSIGTYPE (* func)(int))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
sigint_handler(int signum)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
set_ctrl_c_hook(ctrl_c_fn c_hook)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
console_event_handler(DWORD dwCtrlType)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
set_ctrl_c_hook(ctrl_c_fn c_hook)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