1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-03 09:00:21 +00:00
freebsd/contrib/ntp/libntp/syssignal.c
Cy Schubert 2b15cb3d09 MFV ntp 4.2.8p1 (r258945, r275970, r276091, r276092, r276093, r278284)
Thanks to roberto for providing pointers to wedge this into HEAD.

Approved by:	roberto
2015-03-30 13:30:15 +00:00

189 lines
2.7 KiB
C

#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 */