1c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H
2c0b746e5SOllivier Robert # include <config.h>
3c0b746e5SOllivier Robert #endif
4c0b746e5SOllivier Robert
5c0b746e5SOllivier Robert #include <stdio.h>
6c0b746e5SOllivier Robert #include <sys/types.h>
7c0b746e5SOllivier Robert #include <signal.h>
8c0b746e5SOllivier Robert
9c0b746e5SOllivier Robert #include "ntp_syslog.h"
10c0b746e5SOllivier Robert #include "ntp_stdlib.h"
11c0b746e5SOllivier Robert
122b15cb3dSCy Schubert static ctrl_c_fn ctrl_c_hook;
132b15cb3dSCy Schubert #ifndef SYS_WINNT
142b15cb3dSCy Schubert RETSIGTYPE sigint_handler(int);
152b15cb3dSCy Schubert #else
162b15cb3dSCy Schubert BOOL WINAPI console_event_handler(DWORD);
172b15cb3dSCy Schubert #endif
182b15cb3dSCy Schubert
192b15cb3dSCy Schubert
20c0b746e5SOllivier Robert #ifdef HAVE_SIGACTION
21c0b746e5SOllivier Robert
222b15cb3dSCy Schubert # ifdef SA_RESTART
232b15cb3dSCy Schubert # define Z_SA_RESTART SA_RESTART
242b15cb3dSCy Schubert # else
252b15cb3dSCy Schubert # define Z_SA_RESTART 0
262b15cb3dSCy Schubert # endif
272b15cb3dSCy Schubert
28c0b746e5SOllivier Robert void
signal_no_reset(int sig,void (* func)(int))29c0b746e5SOllivier Robert signal_no_reset(
30c0b746e5SOllivier Robert int sig,
31c0b746e5SOllivier Robert void (*func)(int)
32c0b746e5SOllivier Robert )
33c0b746e5SOllivier Robert {
34c0b746e5SOllivier Robert int n;
35c0b746e5SOllivier Robert struct sigaction vec;
36c0b746e5SOllivier Robert struct sigaction ovec;
37c0b746e5SOllivier Robert
382b15cb3dSCy Schubert ZERO(vec);
392b15cb3dSCy Schubert sigemptyset(&vec.sa_mask);
402b15cb3dSCy Schubert vec.sa_handler = func;
412b15cb3dSCy Schubert
422b15cb3dSCy Schubert /* Added for PPS clocks on Solaris 7 which get EINTR errors */
432b15cb3dSCy Schubert # ifdef SIGPOLL
442b15cb3dSCy Schubert if (SIGPOLL == sig)
452b15cb3dSCy Schubert vec.sa_flags = Z_SA_RESTART;
46c0b746e5SOllivier Robert # endif
472b15cb3dSCy Schubert # ifdef SIGIO
482b15cb3dSCy Schubert if (SIGIO == sig)
492b15cb3dSCy Schubert vec.sa_flags = Z_SA_RESTART;
502b15cb3dSCy Schubert # endif
512b15cb3dSCy Schubert
522b15cb3dSCy Schubert do
532b15cb3dSCy Schubert n = sigaction(sig, &vec, &ovec);
542b15cb3dSCy Schubert while (-1 == n && EINTR == errno);
552b15cb3dSCy Schubert if (-1 == n) {
56c0b746e5SOllivier Robert perror("sigaction");
57c0b746e5SOllivier Robert exit(1);
58c0b746e5SOllivier Robert }
59c0b746e5SOllivier Robert }
60c0b746e5SOllivier Robert
61c0b746e5SOllivier Robert #elif HAVE_SIGVEC
62c0b746e5SOllivier Robert
63c0b746e5SOllivier Robert void
signal_no_reset(int sig,RETSIGTYPE (* func)(int))64c0b746e5SOllivier Robert signal_no_reset(
65c0b746e5SOllivier Robert int sig,
66c0b746e5SOllivier Robert RETSIGTYPE (*func)(int)
67c0b746e5SOllivier Robert )
68c0b746e5SOllivier Robert {
69c0b746e5SOllivier Robert struct sigvec sv;
70c0b746e5SOllivier Robert int n;
71c0b746e5SOllivier Robert
722b15cb3dSCy Schubert ZERO(sv);
73c0b746e5SOllivier Robert sv.sv_handler = func;
74c0b746e5SOllivier Robert n = sigvec(sig, &sv, (struct sigvec *)NULL);
752b15cb3dSCy Schubert if (-1 == n) {
76c0b746e5SOllivier Robert perror("sigvec");
77c0b746e5SOllivier Robert exit(1);
78c0b746e5SOllivier Robert }
79c0b746e5SOllivier Robert }
80c0b746e5SOllivier Robert
81c0b746e5SOllivier Robert #elif HAVE_SIGSET
82c0b746e5SOllivier Robert
83c0b746e5SOllivier Robert void
signal_no_reset(int sig,RETSIGTYPE (* func)(int))84c0b746e5SOllivier Robert signal_no_reset(
85c0b746e5SOllivier Robert int sig,
86c0b746e5SOllivier Robert RETSIGTYPE (*func)(int)
87c0b746e5SOllivier Robert )
88c0b746e5SOllivier Robert {
89c0b746e5SOllivier Robert int n;
90c0b746e5SOllivier Robert
91c0b746e5SOllivier Robert n = sigset(sig, func);
922b15cb3dSCy Schubert if (-1 == n) {
93c0b746e5SOllivier Robert perror("sigset");
94c0b746e5SOllivier Robert exit(1);
95c0b746e5SOllivier Robert }
96c0b746e5SOllivier Robert }
97c0b746e5SOllivier Robert
98c0b746e5SOllivier Robert #else
99c0b746e5SOllivier Robert
100c0b746e5SOllivier Robert /* Beware! This implementation resets the signal to SIG_DFL */
101c0b746e5SOllivier Robert void
signal_no_reset(int sig,RETSIGTYPE (* func)(int))102c0b746e5SOllivier Robert signal_no_reset(
103c0b746e5SOllivier Robert int sig,
104c0b746e5SOllivier Robert RETSIGTYPE (*func)(int)
105c0b746e5SOllivier Robert )
106c0b746e5SOllivier Robert {
1072b15cb3dSCy Schubert #ifndef SIG_ERR
1082b15cb3dSCy Schubert # define SIG_ERR (-1)
109c0b746e5SOllivier Robert #endif
1102b15cb3dSCy Schubert if (SIG_ERR == signal(sig, func)) {
111c0b746e5SOllivier Robert perror("signal");
112c0b746e5SOllivier Robert exit(1);
113c0b746e5SOllivier Robert }
114c0b746e5SOllivier Robert }
115c0b746e5SOllivier Robert
116c0b746e5SOllivier Robert #endif
1172b15cb3dSCy Schubert
1182b15cb3dSCy Schubert #ifndef SYS_WINNT
1192b15cb3dSCy Schubert /*
1202b15cb3dSCy Schubert * POSIX implementation of set_ctrl_c_hook()
1212b15cb3dSCy Schubert */
1222b15cb3dSCy Schubert RETSIGTYPE
sigint_handler(int signum)1232b15cb3dSCy Schubert sigint_handler(
1242b15cb3dSCy Schubert int signum
1252b15cb3dSCy Schubert )
1262b15cb3dSCy Schubert {
1272b15cb3dSCy Schubert UNUSED_ARG(signum);
1282b15cb3dSCy Schubert if (ctrl_c_hook != NULL)
1292b15cb3dSCy Schubert (*ctrl_c_hook)();
1302b15cb3dSCy Schubert }
1312b15cb3dSCy Schubert
1322b15cb3dSCy Schubert void
set_ctrl_c_hook(ctrl_c_fn c_hook)1332b15cb3dSCy Schubert set_ctrl_c_hook(
1342b15cb3dSCy Schubert ctrl_c_fn c_hook
1352b15cb3dSCy Schubert )
1362b15cb3dSCy Schubert {
1372b15cb3dSCy Schubert RETSIGTYPE (*handler)(int);
1382b15cb3dSCy Schubert
1392b15cb3dSCy Schubert if (NULL == c_hook) {
1402b15cb3dSCy Schubert handler = SIG_DFL;
1412b15cb3dSCy Schubert signal_no_reset(SIGINT, handler);
142*4e1ef62aSXin LI ctrl_c_hook = c_hook;
143*4e1ef62aSXin LI } else {
144*4e1ef62aSXin LI ctrl_c_hook = c_hook;
145*4e1ef62aSXin LI handler = &sigint_handler;
146*4e1ef62aSXin LI signal_no_reset(SIGINT, handler);
147*4e1ef62aSXin LI }
1482b15cb3dSCy Schubert }
1492b15cb3dSCy Schubert #else /* SYS_WINNT follows */
1502b15cb3dSCy Schubert /*
1512b15cb3dSCy Schubert * Windows implementation of set_ctrl_c_hook()
1522b15cb3dSCy Schubert */
1532b15cb3dSCy Schubert BOOL WINAPI
console_event_handler(DWORD dwCtrlType)1542b15cb3dSCy Schubert console_event_handler(
1552b15cb3dSCy Schubert DWORD dwCtrlType
1562b15cb3dSCy Schubert )
1572b15cb3dSCy Schubert {
1582b15cb3dSCy Schubert BOOL handled;
1592b15cb3dSCy Schubert
1602b15cb3dSCy Schubert if (CTRL_C_EVENT == dwCtrlType && ctrl_c_hook != NULL) {
1612b15cb3dSCy Schubert (*ctrl_c_hook)();
1622b15cb3dSCy Schubert handled = TRUE;
1632b15cb3dSCy Schubert } else {
1642b15cb3dSCy Schubert handled = FALSE;
1652b15cb3dSCy Schubert }
1662b15cb3dSCy Schubert
1672b15cb3dSCy Schubert return handled;
1682b15cb3dSCy Schubert }
1692b15cb3dSCy Schubert void
set_ctrl_c_hook(ctrl_c_fn c_hook)1702b15cb3dSCy Schubert set_ctrl_c_hook(
1712b15cb3dSCy Schubert ctrl_c_fn c_hook
1722b15cb3dSCy Schubert )
1732b15cb3dSCy Schubert {
1742b15cb3dSCy Schubert BOOL install;
1752b15cb3dSCy Schubert
1762b15cb3dSCy Schubert if (NULL == c_hook) {
1772b15cb3dSCy Schubert ctrl_c_hook = NULL;
1782b15cb3dSCy Schubert install = FALSE;
1792b15cb3dSCy Schubert } else {
1802b15cb3dSCy Schubert ctrl_c_hook = c_hook;
1812b15cb3dSCy Schubert install = TRUE;
1822b15cb3dSCy Schubert }
1832b15cb3dSCy Schubert if (!SetConsoleCtrlHandler(&console_event_handler, install))
1842b15cb3dSCy Schubert msyslog(LOG_ERR, "Can't %s console control handler: %m",
1852b15cb3dSCy Schubert (install)
1862b15cb3dSCy Schubert ? "add"
1872b15cb3dSCy Schubert : "remove");
1882b15cb3dSCy Schubert }
1892b15cb3dSCy Schubert #endif /* SYS_WINNT */
190