xref: /freebsd/contrib/ntp/libntp/syssignal.c (revision 7847e04111f2c2b06b36f6d19a46d78814d7836d)
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