/*
* iosignal.c - input/output routines for ntpd. The socket-opening code
* was shamelessly stolen from ntpd.
*/
/*
* [Bug 158]
* Do the #includes differently, as under some versions of Linux
* sys/param.h has a #undef CONFIG_PHONE line in it.
*
* As we have ~40 CONFIG_ variables, I don't feel like renaming them
* every time somebody adds a new macro to some system header.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <signal.h>
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif /* HAVE_SYS_PARAM_H */
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#include <arpa/inet.h>
#if _BSDI_VERSION >= 199510
# include <ifaddrs.h>
#endif
# ifdef __QNXNTO__
# include <fcntl.h>
# include <unix.h>
# define FNDELAY O_NDELAY
# endif
/* consistency safegurad to catch BLOCK/UNBLOCK oversights */
static int sigio_block_count = 0;
/* main inputhandler to be called on SIGIO */
static input_handler_t *input_handler_callback = NULL;
# if defined(HAVE_SIGACTION)
/*
* If sigaction() is used for signal handling and a signal is
* pending then the kernel blocks the signal before it calls
* the signal handler.
*
* The variable below is used to take care that the SIGIO signal
* is not unintentionally unblocked inside the sigio_handler()
* if the handler executes a piece of code that is normally
* bracketed by BLOCKIO()/UNBLOCKIO() calls.
*/
static int sigio_handler_active = 0;
# endif
/*
* SIGPOLL and SIGIO ROUTINES.
*/
/*
* TTY initialization routines.
*/
int
init_clock_sig(
struct refclockio *rio
)
{
# ifdef USE_TTY_SIGPOLL
{
/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
if (ioctl(rio->fd, I_SETSIG, S_INPUT) < 0)
{
msyslog(LOG_ERR,
"init_clock_sig: ioctl(I_SETSIG, S_INPUT) failed: %m");
return 1;
}
return 0;
}
# else
/*
* Special cases first!
*/
/* Was: defined(SYS_HPUX) */
# if defined(FIOSSAIOOWN) && defined(FIOSNBIO) && defined(FIOSSAIOSTAT)
#define CLOCK_DONE
{
int pgrp, on = 1;
/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
pgrp = getpid();
if (ioctl(rio->fd, FIOSSAIOOWN, (char *)&pgrp) == -1)
{
msyslog(LOG_ERR, "ioctl(FIOSSAIOOWN) fails for clock I/O: %m - EXITING");
exit(1);
/*NOTREACHED*/
}
/*
* set non-blocking, async I/O on the descriptor
*/
if (ioctl(rio->fd, FIOSNBIO, (char *)&on) == -1)
{
msyslog(LOG_ERR, "ioctl(FIOSNBIO) fails for clock I/O: %m - EXITING");
exit(1);
/*NOTREACHED*/
}
/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
if (ioctl(rio->fd, FIOASYNC, (char *)&on) == -1)
{
msyslog(LOG_ERR, "ioctl(FIOASYNC) fails for clock I/O: %m");
return 1;
}
pgrp = -getpid();
if (ioctl(rio->fd, FIOSETOWN, (char*)&pgrp) == -1)
{
msyslog(LOG_ERR, "ioctl(FIOSETOWN) fails for clock I/O: %m");
return 1;
}
if (fcntl(rio->fd, F_SETFL, FNDELAY|FASYNC) < 0)
{
msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails for clock I/O: %m");
return 1;
}
return 0;
}
# endif /* AIX && !BSD: !_BSD && FIOASYNC && FIOSETOWN */
# ifndef CLOCK_DONE
{
/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
# if defined(TIOCSCTTY) && defined(USE_FSETOWNCTTY)
/*
* there are, however, always exceptions to the rules
* one is, that OSF accepts SETOWN on TTY fd's only, iff they are
* CTTYs. SunOS and HPUX do not semm to have this restriction.
* another question is: how can you do multiple SIGIO from several
* ttys (as they all should be CTTYs), wondering...
*
* kd 95-07-16
*/
if (ioctl(rio->fd, TIOCSCTTY, 0) == -1)
{
msyslog(LOG_ERR, "ioctl(TIOCSCTTY, 0) fails for clock I/O: %m");
return 1;
}
# endif /* TIOCSCTTY && USE_FSETOWNCTTY */
if (fcntl(rio->fd, F_SETOWN, getpid()) == -1)
{
msyslog(LOG_ERR, "fcntl(F_SETOWN) fails for clock I/O: %m");
return 1;
}
# if defined(SIOCSPGRP)
if (ioctl(fd, SIOCSPGRP, (char *)&pgrp) == -1)
{
msyslog(LOG_ERR, "ioctl(SIOCSPGRP) fails: %m - EXITING");
exit(1);
/*NOTREACHED*/
}
# elif defined(FIOSETOWN)
if (ioctl(fd, FIOSETOWN, (char*)&pgrp) == -1)
{
msyslog(LOG_ERR, "ioctl(FIOSETOWN) fails: %m - EXITING");
exit(1);
/*NOTREACHED*/
}
# elif defined(F_SETOWN)
if (fcntl(fd, F_SETOWN, pgrp) == -1)
{
msyslog(LOG_ERR, "fcntl(F_SETOWN) fails: %m - EXITING");
exit(1);
/*NOTREACHED*/
}
# else
# include "Bletch: Need to set process(group) to receive SIG(IO|POLL)"
# endif
}
# endif /* USE_UDP_SIGPOLL */
}
static RETSIGTYPE
sigio_handler(
int sig
)
{
int saved_errno = errno;
l_fp ts;
get_systime(&ts);
# if defined(HAVE_SIGACTION)
sigio_handler_active++;
if (sigio_handler_active != 1) /* This should never happen! */
msyslog(LOG_ERR, "sigio_handler: sigio_handler_active != 1");
# endif
# if defined(HAVE_SIGACTION)
sigio_handler_active--;
if (sigio_handler_active != 0) /* This should never happen! */
msyslog(LOG_ERR, "sigio_handler: sigio_handler_active != 0");
# endif
errno = saved_errno;
}
/*
* Signal support routines.
*/
# ifdef HAVE_SIGACTION
void
set_signal(input_handler_t *input)
{
INSIST(input != NULL);