summaryrefslogtreecommitdiff
path: root/libntp/syssignal.c
blob: 5e496a95f26db16b3b2e18f516e0b7ed156636c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <stdio.h>
#include <sys/types.h>
#include <signal.h>

#include "ntp_syslog.h"
#include "ntp_stdlib.h"

static ctrl_c_fn	ctrl_c_hook;
#ifndef SYS_WINNT
RETSIGTYPE sigint_handler(int);
#else
BOOL WINAPI console_event_handler(DWORD);
#endif


#ifdef HAVE_SIGACTION

# ifdef SA_RESTART
#  define Z_SA_RESTART		SA_RESTART
# else
#  define Z_SA_RESTART		0
# endif

void
signal_no_reset(
	int sig,
	void (*func)(int)
	)
{
	int n;
	struct sigaction vec;
	struct sigaction ovec;

	ZERO(vec);
	sigemptyset(&vec.sa_mask);
	vec.sa_handler = func;

	/* Added for PPS clocks on Solaris 7 which get EINTR errors */
# ifdef SIGPOLL
	if (SIGPOLL == sig)
		vec.sa_flags = Z_SA_RESTART;
# endif
# ifdef SIGIO
	if (SIGIO == sig)
		vec.sa_flags = Z_SA_RESTART;
# endif

	do
		n = sigaction(sig, &vec, &ovec);
	while (-1 == n && EINTR == errno);
	if (-1 == n) {
		perror("sigaction");
		exit(1);
	}
}

#elif  HAVE_SIGVEC

void
signal_no_reset(
	int sig,
	RETSIGTYPE (*func)(int)
	)
{
	struct sigvec sv;
	int n;

	ZERO(sv);
	sv.sv_handler = func;
	n = sigvec(sig, &sv, (struct sigvec *)NULL);
	if (-1 == n) {
		perror("sigvec");
		exit(1);
	}
}

#elif  HAVE_SIGSET

void
signal_no_reset(
	int sig,
	RETSIGTYPE (*func)(int)
	)
{
	int n;

	n = sigset(sig, func);
	if (-1 == n) {
		perror("sigset");
		exit(1);
	}
}

#else

/* Beware!	This implementation resets the signal to SIG_DFL */
void
signal_no_reset(
	int sig,
	RETSIGTYPE (*func)(int)
	)
{
#ifndef SIG_ERR
# define SIG_ERR	(-1)
#endif
	if (SIG_ERR == signal(sig, func)) {
		perror("signal");
		exit(1);
	}
}

#endif

#ifndef SYS_WINNT
/*
 * POSIX implementation of set_ctrl_c_hook()
 */
RETSIGTYPE
sigint_handler(
	int	signum
	)
{
	UNUSED_ARG(signum);
	if (ctrl_c_hook != NULL)
		(*ctrl_c_hook)();
}

void
set_ctrl_c_hook(
	ctrl_c_fn	c_hook
	)
{
	RETSIGTYPE (*handler)(int);

	if (NULL == c_hook) {
		handler = SIG_DFL;
		ctrl_c_hook = NULL;
	} else {
		handler = &sigint_handler;
		ctrl_c_hook = c_hook;
	}
	signal_no_reset(SIGINT, handler);
}
#else	/* SYS_WINNT follows */
/*
 * Windows implementation of set_ctrl_c_hook()
 */
BOOL WINAPI 
console_event_handler(  
	DWORD	dwCtrlType
	)
{
	BOOL handled;

	if (CTRL_C_EVENT == dwCtrlType && ctrl_c_hook != NULL) {
		(*ctrl_c_hook)();
		handled = TRUE;
	} else {
		handled = FALSE;
	}

	return handled;
}
void
set_ctrl_c_hook(
	ctrl_c_fn	c_hook
	)
{
	BOOL install;

	if (NULL == c_hook) {
		ctrl_c_hook = NULL;
		install = FALSE;
	} else {
		ctrl_c_hook = c_hook;
		install = TRUE;
	}
	if (!SetConsoleCtrlHandler(&console_event_handler, install))
		msyslog(LOG_ERR, "Can't %s console control handler: %m",
			(install)
			    ? "add"
			    : "remove");
}
#endif	/* SYS_WINNT */