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
12static ctrl_c_fn	ctrl_c_hook;
13#ifndef SYS_WINNT
14RETSIGTYPE sigint_handler(int);
15#else
16BOOL 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
28void
29signal_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
63void
64signal_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
83void
84signal_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 */
101void
102signal_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 */
122RETSIGTYPE
123sigint_handler(
124	int	signum
125	)
126{
127	UNUSED_ARG(signum);
128	if (ctrl_c_hook != NULL)
129		(*ctrl_c_hook)();
130}
131
132void
133set_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 */
152BOOL WINAPI
153console_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}
168void
169set_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