154359Sroberto/*
2132451Sroberto * iosignal.c - input/output routines for ntpd.	The socket-opening code
354359Sroberto *		   was shamelessly stolen from ntpd.
454359Sroberto */
554359Sroberto
6182007Sroberto/*
7182007Sroberto * [Bug 158]
8182007Sroberto * Do the #includes differently, as under some versions of Linux
9182007Sroberto * sys/param.h has a #undef CONFIG_PHONE line in it.
10182007Sroberto *
11182007Sroberto * As we have ~40 CONFIG_ variables, I don't feel like renaming them
12182007Sroberto * every time somebody adds a new macro to some system header.
13182007Sroberto */
1454359Sroberto
15182007Sroberto#ifdef HAVE_CONFIG_H
16182007Sroberto# include <config.h>
17182007Sroberto#endif
18182007Sroberto
1954359Sroberto#include <stdio.h>
2054359Sroberto#include <signal.h>
2154359Sroberto#ifdef HAVE_SYS_PARAM_H
2254359Sroberto# include <sys/param.h>
2354359Sroberto#endif /* HAVE_SYS_PARAM_H */
2454359Sroberto#ifdef HAVE_SYS_IOCTL_H
2554359Sroberto# include <sys/ioctl.h>
2654359Sroberto#endif
2782498Sroberto
2854359Sroberto#include <arpa/inet.h>
2954359Sroberto
3054359Sroberto#if _BSDI_VERSION >= 199510
3154359Sroberto# include <ifaddrs.h>
3254359Sroberto#endif
3354359Sroberto
34182007Sroberto# ifdef __QNXNTO__
35182007Sroberto#  include <fcntl.h>
36182007Sroberto#  include <unix.h>
37182007Sroberto#  define FNDELAY O_NDELAY
38182007Sroberto# endif
39182007Sroberto
40182007Sroberto#include "ntp_machine.h"
41182007Sroberto#include "ntpd.h"
42182007Sroberto#include "ntp_io.h"
43182007Sroberto#include "ntp_if.h"
44182007Sroberto#include "ntp_stdlib.h"
45182007Sroberto#include "iosignal.h"
46182007Sroberto
4754359Sroberto#if defined(HAVE_SIGNALED_IO)
48280849Scystatic RETSIGTYPE sigio_handler	(int);
49280849Scy
50280849Scy/* consistency safegurad to catch BLOCK/UNBLOCK oversights */
5154359Srobertostatic int sigio_block_count = 0;
52280849Scy
53280849Scy/* main inputhandler to be called on SIGIO */
54280849Scystatic input_handler_t *input_handler_callback = NULL;
55280849Scy
56106163Sroberto# if defined(HAVE_SIGACTION)
57106163Sroberto/*
58106163Sroberto * If sigaction() is used for signal handling and a signal is
59106163Sroberto * pending then the kernel blocks the signal before it calls
60106163Sroberto * the signal handler.
61106163Sroberto *
62106163Sroberto * The variable below is used to take care that the SIGIO signal
63106163Sroberto * is not unintentionally unblocked inside the sigio_handler()
64106163Sroberto * if the handler executes a piece of code that is normally
65106163Sroberto * bracketed by BLOCKIO()/UNBLOCKIO() calls.
66106163Sroberto */
67106163Srobertostatic int sigio_handler_active = 0;
68106163Sroberto# endif
6954359Sroberto
7054359Sroberto/*
7154359Sroberto * SIGPOLL and SIGIO ROUTINES.
7254359Sroberto */
7354359Sroberto
7454359Sroberto
7554359Sroberto
7654359Sroberto/*
7754359Sroberto * TTY initialization routines.
7854359Sroberto */
7954359Srobertoint
8054359Srobertoinit_clock_sig(
8154359Sroberto	struct refclockio *rio
8254359Sroberto	)
8354359Sroberto{
8454359Sroberto# ifdef USE_TTY_SIGPOLL
8554359Sroberto	{
8654359Sroberto		/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
8754359Sroberto		if (ioctl(rio->fd, I_SETSIG, S_INPUT) < 0)
8854359Sroberto		{
8954359Sroberto			msyslog(LOG_ERR,
9054359Sroberto				"init_clock_sig: ioctl(I_SETSIG, S_INPUT) failed: %m");
9154359Sroberto			return 1;
9254359Sroberto		}
9354359Sroberto		return 0;
9454359Sroberto	}
9554359Sroberto# else
9654359Sroberto	/*
9754359Sroberto	 * Special cases first!
9854359Sroberto	 */
9954359Sroberto	/* Was: defined(SYS_HPUX) */
10054359Sroberto#  if defined(FIOSSAIOOWN) && defined(FIOSNBIO) && defined(FIOSSAIOSTAT)
10154359Sroberto#define CLOCK_DONE
10254359Sroberto	{
10354359Sroberto		int pgrp, on = 1;
10454359Sroberto
10554359Sroberto		/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
10654359Sroberto		pgrp = getpid();
10754359Sroberto		if (ioctl(rio->fd, FIOSSAIOOWN, (char *)&pgrp) == -1)
10854359Sroberto		{
109280849Scy			msyslog(LOG_ERR, "ioctl(FIOSSAIOOWN) fails for clock I/O: %m - EXITING");
11054359Sroberto			exit(1);
11154359Sroberto			/*NOTREACHED*/
11254359Sroberto		}
11354359Sroberto
11454359Sroberto		/*
11554359Sroberto		 * set non-blocking, async I/O on the descriptor
11654359Sroberto		 */
11754359Sroberto		if (ioctl(rio->fd, FIOSNBIO, (char *)&on) == -1)
11854359Sroberto		{
119280849Scy			msyslog(LOG_ERR, "ioctl(FIOSNBIO) fails for clock I/O: %m - EXITING");
12054359Sroberto			exit(1);
12154359Sroberto			/*NOTREACHED*/
12254359Sroberto		}
12354359Sroberto
12454359Sroberto		if (ioctl(rio->fd, FIOSSAIOSTAT, (char *)&on) == -1)
12554359Sroberto		{
126280849Scy			msyslog(LOG_ERR, "ioctl(FIOSSAIOSTAT) fails for clock I/O: %m - EXITING");
12754359Sroberto			exit(1);
12854359Sroberto			/*NOTREACHED*/
12954359Sroberto		}
13054359Sroberto		return 0;
13154359Sroberto	}
13254359Sroberto#  endif /* SYS_HPUX: FIOSSAIOOWN && FIOSNBIO && FIOSSAIOSTAT */
13354359Sroberto	/* Was: defined(SYS_AIX) && !defined(_BSD) */
13454359Sroberto#  if !defined(_BSD) && defined(_AIX) && defined(FIOASYNC) && defined(FIOSETOWN)
13554359Sroberto	/*
13654359Sroberto	 * SYSV compatibility mode under AIX.
13754359Sroberto	 */
13854359Sroberto#define CLOCK_DONE
13954359Sroberto	{
14054359Sroberto		int pgrp, on = 1;
14154359Sroberto
14254359Sroberto		/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
14354359Sroberto		if (ioctl(rio->fd, FIOASYNC, (char *)&on) == -1)
14454359Sroberto		{
14554359Sroberto			msyslog(LOG_ERR, "ioctl(FIOASYNC) fails for clock I/O: %m");
14654359Sroberto			return 1;
14754359Sroberto		}
14854359Sroberto		pgrp = -getpid();
14954359Sroberto		if (ioctl(rio->fd, FIOSETOWN, (char*)&pgrp) == -1)
15054359Sroberto		{
15154359Sroberto			msyslog(LOG_ERR, "ioctl(FIOSETOWN) fails for clock I/O: %m");
15254359Sroberto			return 1;
15354359Sroberto		}
15454359Sroberto
15554359Sroberto		if (fcntl(rio->fd, F_SETFL, FNDELAY|FASYNC) < 0)
15654359Sroberto		{
15754359Sroberto			msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails for clock I/O: %m");
15854359Sroberto			return 1;
15954359Sroberto		}
16054359Sroberto		return 0;
16154359Sroberto	}
16254359Sroberto#  endif /* AIX && !BSD: !_BSD && FIOASYNC && FIOSETOWN */
16354359Sroberto#  ifndef  CLOCK_DONE
16454359Sroberto	{
16554359Sroberto		/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
16654359Sroberto#	if defined(TIOCSCTTY) && defined(USE_FSETOWNCTTY)
16754359Sroberto		/*
16854359Sroberto		 * there are, however, always exceptions to the rules
16954359Sroberto		 * one is, that OSF accepts SETOWN on TTY fd's only, iff they are
17054359Sroberto		 * CTTYs. SunOS and HPUX do not semm to have this restriction.
17154359Sroberto		 * another question is: how can you do multiple SIGIO from several
17254359Sroberto		 * ttys (as they all should be CTTYs), wondering...
17354359Sroberto		 *
17454359Sroberto		 * kd 95-07-16
17554359Sroberto		 */
17654359Sroberto		if (ioctl(rio->fd, TIOCSCTTY, 0) == -1)
17754359Sroberto		{
17854359Sroberto			msyslog(LOG_ERR, "ioctl(TIOCSCTTY, 0) fails for clock I/O: %m");
17954359Sroberto			return 1;
18054359Sroberto		}
18154359Sroberto#	endif /* TIOCSCTTY && USE_FSETOWNCTTY */
18254359Sroberto
18354359Sroberto		if (fcntl(rio->fd, F_SETOWN, getpid()) == -1)
18454359Sroberto		{
18554359Sroberto			msyslog(LOG_ERR, "fcntl(F_SETOWN) fails for clock I/O: %m");
18654359Sroberto			return 1;
18754359Sroberto		}
18854359Sroberto
18954359Sroberto		if (fcntl(rio->fd, F_SETFL, FNDELAY|FASYNC) < 0)
19054359Sroberto		{
19154359Sroberto			msyslog(LOG_ERR,
19254359Sroberto				"fcntl(FNDELAY|FASYNC) fails for clock I/O: %m");
19354359Sroberto			return 1;
19454359Sroberto		}
19554359Sroberto		return 0;
19654359Sroberto	}
19754359Sroberto#  endif /* CLOCK_DONE */
19854359Sroberto# endif /* !USE_TTY_SIGPOLL  */
19954359Sroberto}
20054359Sroberto
20154359Sroberto
20254359Sroberto
20354359Srobertovoid
20454359Srobertoinit_socket_sig(
20554359Sroberto	int fd
20654359Sroberto	)
20754359Sroberto{
20854359Sroberto# ifdef USE_UDP_SIGPOLL
20954359Sroberto	{
21054359Sroberto		if (ioctl(fd, I_SETSIG, S_INPUT) < 0)
21154359Sroberto		{
21254359Sroberto			msyslog(LOG_ERR,
213280849Scy				"init_socket_sig: ioctl(I_SETSIG, S_INPUT) failed: %m - EXITING");
21454359Sroberto			exit(1);
21554359Sroberto		}
21654359Sroberto	}
21754359Sroberto# else /* USE_UDP_SIGPOLL */
21854359Sroberto	{
21954359Sroberto		int pgrp;
22054359Sroberto# ifdef FIOASYNC
22154359Sroberto		int on = 1;
22254359Sroberto# endif
22354359Sroberto
22454359Sroberto#  if defined(FIOASYNC)
22554359Sroberto		if (ioctl(fd, FIOASYNC, (char *)&on) == -1)
22654359Sroberto		{
227280849Scy			msyslog(LOG_ERR, "ioctl(FIOASYNC) fails: %m - EXITING");
22854359Sroberto			exit(1);
22954359Sroberto			/*NOTREACHED*/
23054359Sroberto		}
23154359Sroberto#  elif defined(FASYNC)
23254359Sroberto		{
23354359Sroberto			int flags;
23454359Sroberto
23554359Sroberto			if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
23654359Sroberto			{
237280849Scy				msyslog(LOG_ERR, "fcntl(F_GETFL) fails: %m - EXITING");
23854359Sroberto				exit(1);
23954359Sroberto				/*NOTREACHED*/
24054359Sroberto			}
24154359Sroberto			if (fcntl(fd, F_SETFL, flags|FASYNC) < 0)
24254359Sroberto			{
243280849Scy				msyslog(LOG_ERR, "fcntl(...|FASYNC) fails: %m - EXITING");
24454359Sroberto				exit(1);
24554359Sroberto				/*NOTREACHED*/
24654359Sroberto			}
24754359Sroberto		}
24854359Sroberto#  else
24954359Sroberto#	include "Bletch: Need asynchronous I/O!"
25054359Sroberto#  endif
25154359Sroberto
25254359Sroberto#  ifdef UDP_BACKWARDS_SETOWN
25354359Sroberto		pgrp = -getpid();
25454359Sroberto#  else
25554359Sroberto		pgrp = getpid();
25654359Sroberto#  endif
25754359Sroberto
25854359Sroberto#  if defined(SIOCSPGRP)
25954359Sroberto		if (ioctl(fd, SIOCSPGRP, (char *)&pgrp) == -1)
26054359Sroberto		{
261280849Scy			msyslog(LOG_ERR, "ioctl(SIOCSPGRP) fails: %m - EXITING");
26254359Sroberto			exit(1);
26354359Sroberto			/*NOTREACHED*/
26454359Sroberto		}
26554359Sroberto#  elif defined(FIOSETOWN)
26654359Sroberto		if (ioctl(fd, FIOSETOWN, (char*)&pgrp) == -1)
26754359Sroberto		{
268280849Scy			msyslog(LOG_ERR, "ioctl(FIOSETOWN) fails: %m - EXITING");
26954359Sroberto			exit(1);
27054359Sroberto			/*NOTREACHED*/
27154359Sroberto		}
27254359Sroberto#  elif defined(F_SETOWN)
27354359Sroberto		if (fcntl(fd, F_SETOWN, pgrp) == -1)
27454359Sroberto		{
275280849Scy			msyslog(LOG_ERR, "fcntl(F_SETOWN) fails: %m - EXITING");
27654359Sroberto			exit(1);
27754359Sroberto			/*NOTREACHED*/
27854359Sroberto		}
27954359Sroberto#  else
28054359Sroberto#	include "Bletch: Need to set process(group) to receive SIG(IO|POLL)"
28154359Sroberto#  endif
28254359Sroberto	}
28354359Sroberto# endif /* USE_UDP_SIGPOLL */
28454359Sroberto}
28554359Sroberto
286280849Scystatic RETSIGTYPE
28754359Srobertosigio_handler(
28854359Sroberto	int sig
28954359Sroberto	)
29054359Sroberto{
29154359Sroberto	int saved_errno = errno;
29254359Sroberto	l_fp ts;
29354359Sroberto
29454359Sroberto	get_systime(&ts);
295106163Sroberto
296106163Sroberto# if defined(HAVE_SIGACTION)
297106163Sroberto	sigio_handler_active++;
298106163Sroberto	if (sigio_handler_active != 1)  /* This should never happen! */
299106163Sroberto	    msyslog(LOG_ERR, "sigio_handler: sigio_handler_active != 1");
300106163Sroberto# endif
301106163Sroberto
302280849Scy	INSIST(input_handler_callback != NULL);
303280849Scy	(*input_handler_callback)(&ts);
304106163Sroberto
305106163Sroberto# if defined(HAVE_SIGACTION)
306106163Sroberto	sigio_handler_active--;
307106163Sroberto	if (sigio_handler_active != 0)  /* This should never happen! */
308106163Sroberto	    msyslog(LOG_ERR, "sigio_handler: sigio_handler_active != 0");
309106163Sroberto# endif
310106163Sroberto
31154359Sroberto	errno = saved_errno;
31254359Sroberto}
31354359Sroberto
31454359Sroberto/*
31554359Sroberto * Signal support routines.
31654359Sroberto */
31754359Sroberto# ifdef HAVE_SIGACTION
31854359Srobertovoid
319280849Scyset_signal(input_handler_t *input)
32054359Sroberto{
321280849Scy	INSIST(input != NULL);
322280849Scy
323280849Scy	input_handler_callback = input;
324280849Scy
325280849Scy	using_sigio = TRUE;
32654359Sroberto#  ifdef USE_SIGIO
32754359Sroberto	(void) signal_no_reset(SIGIO, sigio_handler);
32854359Sroberto# endif
32954359Sroberto#  ifdef USE_SIGPOLL
33054359Sroberto	(void) signal_no_reset(SIGPOLL, sigio_handler);
33154359Sroberto# endif
33254359Sroberto}
33354359Sroberto
33454359Srobertovoid
33554359Srobertoblock_io_and_alarm(void)
33654359Sroberto{
33754359Sroberto	sigset_t set;
33854359Sroberto
33954359Sroberto	if (sigemptyset(&set))
34054359Sroberto	    msyslog(LOG_ERR, "block_io_and_alarm: sigemptyset() failed: %m");
34154359Sroberto#  if defined(USE_SIGIO)
34254359Sroberto	if (sigaddset(&set, SIGIO))
34354359Sroberto	    msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGIO) failed: %m");
34454359Sroberto#  endif
34554359Sroberto#  if defined(USE_SIGPOLL)
34654359Sroberto	if (sigaddset(&set, SIGPOLL))
34754359Sroberto	    msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGPOLL) failed: %m");
34854359Sroberto#  endif
34954359Sroberto	if (sigaddset(&set, SIGALRM))
35054359Sroberto	    msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGALRM) failed: %m");
35154359Sroberto
35254359Sroberto	if (sigprocmask(SIG_BLOCK, &set, NULL))
35354359Sroberto	    msyslog(LOG_ERR, "block_io_and_alarm: sigprocmask() failed: %m");
35454359Sroberto}
35554359Sroberto
35654359Srobertovoid
35754359Srobertoblock_sigio(void)
35854359Sroberto{
359106163Sroberto	if ( sigio_handler_active == 0 )  /* not called from within signal handler */
360106163Sroberto	{
361106163Sroberto		sigset_t set;
36254359Sroberto
363106163Sroberto		++sigio_block_count;
364106163Sroberto		if (sigio_block_count > 1)
365106163Sroberto		    msyslog(LOG_INFO, "block_sigio: sigio_block_count > 1");
366106163Sroberto		if (sigio_block_count < 1)
367106163Sroberto		    msyslog(LOG_INFO, "block_sigio: sigio_block_count < 1");
36854359Sroberto
369106163Sroberto		if (sigemptyset(&set))
370106163Sroberto		    msyslog(LOG_ERR, "block_sigio: sigemptyset() failed: %m");
371106163Sroberto#	if defined(USE_SIGIO)
372106163Sroberto		if (sigaddset(&set, SIGIO))
373106163Sroberto		    msyslog(LOG_ERR, "block_sigio: sigaddset(SIGIO) failed: %m");
374106163Sroberto#	endif
375106163Sroberto#	if defined(USE_SIGPOLL)
376106163Sroberto		if (sigaddset(&set, SIGPOLL))
377106163Sroberto		    msyslog(LOG_ERR, "block_sigio: sigaddset(SIGPOLL) failed: %m");
378106163Sroberto#	endif
37954359Sroberto
380106163Sroberto		if (sigprocmask(SIG_BLOCK, &set, NULL))
381106163Sroberto		    msyslog(LOG_ERR, "block_sigio: sigprocmask() failed: %m");
382106163Sroberto	}
38354359Sroberto}
38454359Sroberto
38554359Srobertovoid
38654359Srobertounblock_io_and_alarm(void)
38754359Sroberto{
38854359Sroberto	sigset_t unset;
38954359Sroberto
39054359Sroberto	if (sigemptyset(&unset))
39154359Sroberto	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigemptyset() failed: %m");
39254359Sroberto
39354359Sroberto#  if defined(USE_SIGIO)
39454359Sroberto	if (sigaddset(&unset, SIGIO))
39554359Sroberto	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGIO) failed: %m");
39654359Sroberto#  endif
39754359Sroberto#  if defined(USE_SIGPOLL)
39854359Sroberto	if (sigaddset(&unset, SIGPOLL))
39954359Sroberto	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGPOLL) failed: %m");
40054359Sroberto#  endif
40154359Sroberto	if (sigaddset(&unset, SIGALRM))
40254359Sroberto	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGALRM) failed: %m");
40354359Sroberto
40454359Sroberto	if (sigprocmask(SIG_UNBLOCK, &unset, NULL))
40554359Sroberto	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigprocmask() failed: %m");
40654359Sroberto}
40754359Sroberto
40854359Srobertovoid
40954359Srobertounblock_sigio(void)
41054359Sroberto{
411106163Sroberto	if ( sigio_handler_active == 0 )  /* not called from within signal handler */
412106163Sroberto	{
413106163Sroberto		sigset_t unset;
41454359Sroberto
415106163Sroberto		--sigio_block_count;
416106163Sroberto		if (sigio_block_count > 0)
417106163Sroberto		    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count > 0");
418106163Sroberto		if (sigio_block_count < 0)
419106163Sroberto		    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count < 0");
42054359Sroberto
421106163Sroberto		if (sigemptyset(&unset))
422106163Sroberto		    msyslog(LOG_ERR, "unblock_sigio: sigemptyset() failed: %m");
42354359Sroberto
424106163Sroberto#	if defined(USE_SIGIO)
425106163Sroberto		if (sigaddset(&unset, SIGIO))
426106163Sroberto		    msyslog(LOG_ERR, "unblock_sigio: sigaddset(SIGIO) failed: %m");
427106163Sroberto#	endif
428106163Sroberto#	if defined(USE_SIGPOLL)
429106163Sroberto		if (sigaddset(&unset, SIGPOLL))
430106163Sroberto		    msyslog(LOG_ERR, "unblock_sigio: sigaddset(SIGPOLL) failed: %m");
431106163Sroberto#	endif
43254359Sroberto
433106163Sroberto		if (sigprocmask(SIG_UNBLOCK, &unset, NULL))
434106163Sroberto		    msyslog(LOG_ERR, "unblock_sigio: sigprocmask() failed: %m");
435106163Sroberto	}
43654359Sroberto}
43754359Sroberto
43854359Srobertovoid
43954359Srobertowait_for_signal(void)
44054359Sroberto{
44154359Sroberto	sigset_t old;
44254359Sroberto
44354359Sroberto	if (sigprocmask(SIG_UNBLOCK, NULL, &old))
44454359Sroberto	    msyslog(LOG_ERR, "wait_for_signal: sigprocmask() failed: %m");
44554359Sroberto
44654359Sroberto#  if defined(USE_SIGIO)
44754359Sroberto	if (sigdelset(&old, SIGIO))
44854359Sroberto	    msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGIO) failed: %m");
44954359Sroberto#  endif
45054359Sroberto#  if defined(USE_SIGPOLL)
45154359Sroberto	if (sigdelset(&old, SIGPOLL))
45254359Sroberto	    msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGPOLL) failed: %m");
45354359Sroberto#  endif
45454359Sroberto	if (sigdelset(&old, SIGALRM))
45554359Sroberto	    msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGALRM) failed: %m");
45654359Sroberto
45754359Sroberto	if (sigsuspend(&old) && (errno != EINTR))
45854359Sroberto	    msyslog(LOG_ERR, "wait_for_signal: sigsuspend() failed: %m");
45954359Sroberto}
46054359Sroberto
46154359Sroberto# else /* !HAVE_SIGACTION */
46254359Sroberto/*
46354359Sroberto * Must be an old bsd system.
46454359Sroberto * We assume there is no SIGPOLL.
46554359Sroberto */
46654359Sroberto
46754359Srobertovoid
46854359Srobertoblock_io_and_alarm(void)
46954359Sroberto{
47054359Sroberto	int mask;
47154359Sroberto
47254359Sroberto	mask = sigmask(SIGIO) | sigmask(SIGALRM);
47354359Sroberto	if (sigblock(mask))
47454359Sroberto	    msyslog(LOG_ERR, "block_io_and_alarm: sigblock() failed: %m");
47554359Sroberto}
47654359Sroberto
47754359Srobertovoid
47854359Srobertoblock_sigio(void)
47954359Sroberto{
48054359Sroberto	int mask;
48154359Sroberto
48254359Sroberto	++sigio_block_count;
48354359Sroberto	if (sigio_block_count > 1)
48454359Sroberto	    msyslog(LOG_INFO, "block_sigio: sigio_block_count > 1");
48554359Sroberto	if (sigio_block_count < 1)
48654359Sroberto	    msyslog(LOG_INFO, "block_sigio: sigio_block_count < 1");
48754359Sroberto
48854359Sroberto	mask = sigmask(SIGIO);
48954359Sroberto	if (sigblock(mask))
49054359Sroberto	    msyslog(LOG_ERR, "block_sigio: sigblock() failed: %m");
49154359Sroberto}
49254359Sroberto
49354359Srobertovoid
494280849Scyset_signal(input_handler_t *input)
49554359Sroberto{
496280849Scy	INSIST(input != NULL);
497280849Scy
498280849Scy	input_handler_callback = input;
499280849Scy
500280849Scy	using_sigio = TRUE;
50154359Sroberto	(void) signal_no_reset(SIGIO, sigio_handler);
50254359Sroberto}
50354359Sroberto
50454359Srobertovoid
50554359Srobertounblock_io_and_alarm(void)
50654359Sroberto{
50754359Sroberto	int mask, omask;
50854359Sroberto
50954359Sroberto	mask = sigmask(SIGIO) | sigmask(SIGALRM);
51054359Sroberto	omask = sigblock(0);
51154359Sroberto	omask &= ~mask;
51254359Sroberto	(void) sigsetmask(omask);
51354359Sroberto}
51454359Sroberto
51554359Srobertovoid
51654359Srobertounblock_sigio(void)
51754359Sroberto{
51854359Sroberto	int mask, omask;
51954359Sroberto
52054359Sroberto	--sigio_block_count;
52154359Sroberto	if (sigio_block_count > 0)
52254359Sroberto	    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count > 0");
52354359Sroberto	if (sigio_block_count < 0)
52454359Sroberto	    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count < 0");
52554359Sroberto	mask = sigmask(SIGIO);
52654359Sroberto	omask = sigblock(0);
52754359Sroberto	omask &= ~mask;
52854359Sroberto	(void) sigsetmask(omask);
52954359Sroberto}
53054359Sroberto
53154359Srobertovoid
53254359Srobertowait_for_signal(void)
53354359Sroberto{
53454359Sroberto	int mask, omask;
53554359Sroberto
53654359Sroberto	mask = sigmask(SIGIO) | sigmask(SIGALRM);
53754359Sroberto	omask = sigblock(0);
53854359Sroberto	omask &= ~mask;
53954359Sroberto	if (sigpause(omask) && (errno != EINTR))
54054359Sroberto	    msyslog(LOG_ERR, "wait_for_signal: sigspause() failed: %m");
54154359Sroberto}
54254359Sroberto
54354359Sroberto# endif /* HAVE_SIGACTION */
54454359Sroberto#else
54554359Srobertoint  NotAnEmptyCompilationUnit;
54654359Sroberto#endif
547