syssignal.c revision 338531
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		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 */
153BOOL WINAPI
154console_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}
169void
170set_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