xref: /netbsd-src/external/bsd/ntp/dist/libntp/iosignal.c (revision cdfa2a7ef92791ba9db70a584a1d904730e6fb46)
1*cdfa2a7eSchristos /*	$NetBSD: iosignal.c,v 1.5 2020/05/25 20:47:24 christos Exp $	*/
2abb0f93cSkardel 
3abb0f93cSkardel /*
4abb0f93cSkardel  * iosignal.c - input/output routines for ntpd.	The socket-opening code
5abb0f93cSkardel  *		   was shamelessly stolen from ntpd.
6abb0f93cSkardel  */
7abb0f93cSkardel 
8abb0f93cSkardel /*
9abb0f93cSkardel  * [Bug 158]
10abb0f93cSkardel  * Do the #includes differently, as under some versions of Linux
11abb0f93cSkardel  * sys/param.h has a #undef CONFIG_PHONE line in it.
12abb0f93cSkardel  *
13abb0f93cSkardel  * As we have ~40 CONFIG_ variables, I don't feel like renaming them
14abb0f93cSkardel  * every time somebody adds a new macro to some system header.
15abb0f93cSkardel  */
16abb0f93cSkardel 
17abb0f93cSkardel #ifdef HAVE_CONFIG_H
18abb0f93cSkardel # include <config.h>
19abb0f93cSkardel #endif
20abb0f93cSkardel 
21abb0f93cSkardel #include <stdio.h>
22abb0f93cSkardel #include <signal.h>
23abb0f93cSkardel #ifdef HAVE_SYS_PARAM_H
24abb0f93cSkardel # include <sys/param.h>
25abb0f93cSkardel #endif /* HAVE_SYS_PARAM_H */
26abb0f93cSkardel #ifdef HAVE_SYS_IOCTL_H
27abb0f93cSkardel # include <sys/ioctl.h>
28abb0f93cSkardel #endif
29abb0f93cSkardel 
30abb0f93cSkardel #include <arpa/inet.h>
31abb0f93cSkardel 
32abb0f93cSkardel #if _BSDI_VERSION >= 199510
33abb0f93cSkardel # include <ifaddrs.h>
34abb0f93cSkardel #endif
35abb0f93cSkardel 
36abb0f93cSkardel # ifdef __QNXNTO__
37abb0f93cSkardel #  include <fcntl.h>
38abb0f93cSkardel #  include <unix.h>
39abb0f93cSkardel #  define FNDELAY O_NDELAY
40abb0f93cSkardel # endif
41abb0f93cSkardel 
42abb0f93cSkardel #include "ntp_machine.h"
43abb0f93cSkardel #include "ntpd.h"
44abb0f93cSkardel #include "ntp_io.h"
45abb0f93cSkardel #include "ntp_if.h"
46abb0f93cSkardel #include "ntp_stdlib.h"
47abb0f93cSkardel #include "iosignal.h"
48abb0f93cSkardel 
49abb0f93cSkardel #if defined(HAVE_SIGNALED_IO)
508585484eSchristos static RETSIGTYPE sigio_handler	(int);
518585484eSchristos 
528585484eSchristos /* consistency safegurad to catch BLOCK/UNBLOCK oversights */
53abb0f93cSkardel static int sigio_block_count = 0;
548585484eSchristos 
558585484eSchristos /* main inputhandler to be called on SIGIO */
568585484eSchristos static input_handler_t *input_handler_callback = NULL;
578585484eSchristos 
58abb0f93cSkardel # if defined(HAVE_SIGACTION)
59abb0f93cSkardel /*
60abb0f93cSkardel  * If sigaction() is used for signal handling and a signal is
61abb0f93cSkardel  * pending then the kernel blocks the signal before it calls
62abb0f93cSkardel  * the signal handler.
63abb0f93cSkardel  *
64abb0f93cSkardel  * The variable below is used to take care that the SIGIO signal
65abb0f93cSkardel  * is not unintentionally unblocked inside the sigio_handler()
66abb0f93cSkardel  * if the handler executes a piece of code that is normally
67abb0f93cSkardel  * bracketed by BLOCKIO()/UNBLOCKIO() calls.
68abb0f93cSkardel  */
69abb0f93cSkardel static int sigio_handler_active = 0;
70abb0f93cSkardel # endif
71abb0f93cSkardel 
72abb0f93cSkardel /*
73abb0f93cSkardel  * SIGPOLL and SIGIO ROUTINES.
74abb0f93cSkardel  */
75abb0f93cSkardel 
76abb0f93cSkardel 
77abb0f93cSkardel 
78abb0f93cSkardel /*
79abb0f93cSkardel  * TTY initialization routines.
80abb0f93cSkardel  */
81abb0f93cSkardel int
init_clock_sig(struct refclockio * rio)82abb0f93cSkardel init_clock_sig(
83abb0f93cSkardel 	struct refclockio *rio
84abb0f93cSkardel 	)
85abb0f93cSkardel {
86abb0f93cSkardel # ifdef USE_TTY_SIGPOLL
87abb0f93cSkardel 	{
88abb0f93cSkardel 		/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
89abb0f93cSkardel 		if (ioctl(rio->fd, I_SETSIG, S_INPUT) < 0)
90abb0f93cSkardel 		{
91abb0f93cSkardel 			msyslog(LOG_ERR,
92abb0f93cSkardel 				"init_clock_sig: ioctl(I_SETSIG, S_INPUT) failed: %m");
93abb0f93cSkardel 			return 1;
94abb0f93cSkardel 		}
95abb0f93cSkardel 		return 0;
96abb0f93cSkardel 	}
97abb0f93cSkardel # else
98abb0f93cSkardel 	/*
99abb0f93cSkardel 	 * Special cases first!
100abb0f93cSkardel 	 */
101abb0f93cSkardel 	/* Was: defined(SYS_HPUX) */
102abb0f93cSkardel #  if defined(FIOSSAIOOWN) && defined(FIOSNBIO) && defined(FIOSSAIOSTAT)
103abb0f93cSkardel #define CLOCK_DONE
104abb0f93cSkardel 	{
105abb0f93cSkardel 		int pgrp, on = 1;
106abb0f93cSkardel 
107abb0f93cSkardel 		/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
108abb0f93cSkardel 		pgrp = getpid();
109abb0f93cSkardel 		if (ioctl(rio->fd, FIOSSAIOOWN, (char *)&pgrp) == -1)
110abb0f93cSkardel 		{
1118585484eSchristos 			msyslog(LOG_ERR, "ioctl(FIOSSAIOOWN) fails for clock I/O: %m - EXITING");
112abb0f93cSkardel 			exit(1);
113abb0f93cSkardel 			/*NOTREACHED*/
114abb0f93cSkardel 		}
115abb0f93cSkardel 
116abb0f93cSkardel 		/*
117abb0f93cSkardel 		 * set non-blocking, async I/O on the descriptor
118abb0f93cSkardel 		 */
119abb0f93cSkardel 		if (ioctl(rio->fd, FIOSNBIO, (char *)&on) == -1)
120abb0f93cSkardel 		{
1218585484eSchristos 			msyslog(LOG_ERR, "ioctl(FIOSNBIO) fails for clock I/O: %m - EXITING");
122abb0f93cSkardel 			exit(1);
123abb0f93cSkardel 			/*NOTREACHED*/
124abb0f93cSkardel 		}
125abb0f93cSkardel 
126abb0f93cSkardel 		if (ioctl(rio->fd, FIOSSAIOSTAT, (char *)&on) == -1)
127abb0f93cSkardel 		{
1288585484eSchristos 			msyslog(LOG_ERR, "ioctl(FIOSSAIOSTAT) fails for clock I/O: %m - EXITING");
129abb0f93cSkardel 			exit(1);
130abb0f93cSkardel 			/*NOTREACHED*/
131abb0f93cSkardel 		}
132abb0f93cSkardel 		return 0;
133abb0f93cSkardel 	}
134abb0f93cSkardel #  endif /* SYS_HPUX: FIOSSAIOOWN && FIOSNBIO && FIOSSAIOSTAT */
135abb0f93cSkardel 	/* Was: defined(SYS_AIX) && !defined(_BSD) */
136abb0f93cSkardel #  if !defined(_BSD) && defined(_AIX) && defined(FIOASYNC) && defined(FIOSETOWN)
137abb0f93cSkardel 	/*
138abb0f93cSkardel 	 * SYSV compatibility mode under AIX.
139abb0f93cSkardel 	 */
140abb0f93cSkardel #define CLOCK_DONE
141abb0f93cSkardel 	{
142abb0f93cSkardel 		int pgrp, on = 1;
143abb0f93cSkardel 
144abb0f93cSkardel 		/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
145abb0f93cSkardel 		if (ioctl(rio->fd, FIOASYNC, (char *)&on) == -1)
146abb0f93cSkardel 		{
147abb0f93cSkardel 			msyslog(LOG_ERR, "ioctl(FIOASYNC) fails for clock I/O: %m");
148abb0f93cSkardel 			return 1;
149abb0f93cSkardel 		}
150abb0f93cSkardel 		pgrp = -getpid();
151abb0f93cSkardel 		if (ioctl(rio->fd, FIOSETOWN, (char*)&pgrp) == -1)
152abb0f93cSkardel 		{
153abb0f93cSkardel 			msyslog(LOG_ERR, "ioctl(FIOSETOWN) fails for clock I/O: %m");
154abb0f93cSkardel 			return 1;
155abb0f93cSkardel 		}
156abb0f93cSkardel 
157abb0f93cSkardel 		if (fcntl(rio->fd, F_SETFL, FNDELAY|FASYNC) < 0)
158abb0f93cSkardel 		{
159abb0f93cSkardel 			msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails for clock I/O: %m");
160abb0f93cSkardel 			return 1;
161abb0f93cSkardel 		}
162abb0f93cSkardel 		return 0;
163abb0f93cSkardel 	}
164abb0f93cSkardel #  endif /* AIX && !BSD: !_BSD && FIOASYNC && FIOSETOWN */
165abb0f93cSkardel #  ifndef  CLOCK_DONE
166abb0f93cSkardel 	{
167abb0f93cSkardel 		/* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
168abb0f93cSkardel #	if defined(TIOCSCTTY) && defined(USE_FSETOWNCTTY)
169abb0f93cSkardel 		/*
170abb0f93cSkardel 		 * there are, however, always exceptions to the rules
171abb0f93cSkardel 		 * one is, that OSF accepts SETOWN on TTY fd's only, iff they are
172abb0f93cSkardel 		 * CTTYs. SunOS and HPUX do not semm to have this restriction.
173abb0f93cSkardel 		 * another question is: how can you do multiple SIGIO from several
174abb0f93cSkardel 		 * ttys (as they all should be CTTYs), wondering...
175abb0f93cSkardel 		 *
176abb0f93cSkardel 		 * kd 95-07-16
177abb0f93cSkardel 		 */
178abb0f93cSkardel 		if (ioctl(rio->fd, TIOCSCTTY, 0) == -1)
179abb0f93cSkardel 		{
180abb0f93cSkardel 			msyslog(LOG_ERR, "ioctl(TIOCSCTTY, 0) fails for clock I/O: %m");
181abb0f93cSkardel 			return 1;
182abb0f93cSkardel 		}
183abb0f93cSkardel #	endif /* TIOCSCTTY && USE_FSETOWNCTTY */
184abb0f93cSkardel 
185abb0f93cSkardel 		if (fcntl(rio->fd, F_SETOWN, getpid()) == -1)
186abb0f93cSkardel 		{
187abb0f93cSkardel 			msyslog(LOG_ERR, "fcntl(F_SETOWN) fails for clock I/O: %m");
188abb0f93cSkardel 			return 1;
189abb0f93cSkardel 		}
190abb0f93cSkardel 
191abb0f93cSkardel 		if (fcntl(rio->fd, F_SETFL, FNDELAY|FASYNC) < 0)
192abb0f93cSkardel 		{
193abb0f93cSkardel 			msyslog(LOG_ERR,
194abb0f93cSkardel 				"fcntl(FNDELAY|FASYNC) fails for clock I/O: %m");
195abb0f93cSkardel 			return 1;
196abb0f93cSkardel 		}
197abb0f93cSkardel 		return 0;
198abb0f93cSkardel 	}
199abb0f93cSkardel #  endif /* CLOCK_DONE */
200abb0f93cSkardel # endif /* !USE_TTY_SIGPOLL  */
201abb0f93cSkardel }
202abb0f93cSkardel 
203abb0f93cSkardel 
204abb0f93cSkardel 
205abb0f93cSkardel void
init_socket_sig(int fd)206abb0f93cSkardel init_socket_sig(
207abb0f93cSkardel 	int fd
208abb0f93cSkardel 	)
209abb0f93cSkardel {
210abb0f93cSkardel # ifdef USE_UDP_SIGPOLL
211abb0f93cSkardel 	{
212abb0f93cSkardel 		if (ioctl(fd, I_SETSIG, S_INPUT) < 0)
213abb0f93cSkardel 		{
214abb0f93cSkardel 			msyslog(LOG_ERR,
2158585484eSchristos 				"init_socket_sig: ioctl(I_SETSIG, S_INPUT) failed: %m - EXITING");
216abb0f93cSkardel 			exit(1);
217abb0f93cSkardel 		}
218abb0f93cSkardel 	}
219abb0f93cSkardel # else /* USE_UDP_SIGPOLL */
220abb0f93cSkardel 	{
221abb0f93cSkardel 		int pgrp;
222abb0f93cSkardel # ifdef FIOASYNC
223abb0f93cSkardel 		int on = 1;
224abb0f93cSkardel # endif
225abb0f93cSkardel 
226abb0f93cSkardel #  if defined(FIOASYNC)
227abb0f93cSkardel 		if (ioctl(fd, FIOASYNC, (char *)&on) == -1)
228abb0f93cSkardel 		{
2298585484eSchristos 			msyslog(LOG_ERR, "ioctl(FIOASYNC) fails: %m - EXITING");
230abb0f93cSkardel 			exit(1);
231abb0f93cSkardel 			/*NOTREACHED*/
232abb0f93cSkardel 		}
233abb0f93cSkardel #  elif defined(FASYNC)
234abb0f93cSkardel 		{
235abb0f93cSkardel 			int flags;
236abb0f93cSkardel 
237abb0f93cSkardel 			if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
238abb0f93cSkardel 			{
2398585484eSchristos 				msyslog(LOG_ERR, "fcntl(F_GETFL) fails: %m - EXITING");
240abb0f93cSkardel 				exit(1);
241abb0f93cSkardel 				/*NOTREACHED*/
242abb0f93cSkardel 			}
243abb0f93cSkardel 			if (fcntl(fd, F_SETFL, flags|FASYNC) < 0)
244abb0f93cSkardel 			{
2458585484eSchristos 				msyslog(LOG_ERR, "fcntl(...|FASYNC) fails: %m - EXITING");
246abb0f93cSkardel 				exit(1);
247abb0f93cSkardel 				/*NOTREACHED*/
248abb0f93cSkardel 			}
249abb0f93cSkardel 		}
250abb0f93cSkardel #  else
251abb0f93cSkardel #	include "Bletch: Need asynchronous I/O!"
252abb0f93cSkardel #  endif
253abb0f93cSkardel 
254abb0f93cSkardel #  ifdef UDP_BACKWARDS_SETOWN
255abb0f93cSkardel 		pgrp = -getpid();
256abb0f93cSkardel #  else
257abb0f93cSkardel 		pgrp = getpid();
258abb0f93cSkardel #  endif
259abb0f93cSkardel 
260abb0f93cSkardel #  if defined(SIOCSPGRP)
261abb0f93cSkardel 		if (ioctl(fd, SIOCSPGRP, (char *)&pgrp) == -1)
262abb0f93cSkardel 		{
2638585484eSchristos 			msyslog(LOG_ERR, "ioctl(SIOCSPGRP) fails: %m - EXITING");
264abb0f93cSkardel 			exit(1);
265abb0f93cSkardel 			/*NOTREACHED*/
266abb0f93cSkardel 		}
267abb0f93cSkardel #  elif defined(FIOSETOWN)
268abb0f93cSkardel 		if (ioctl(fd, FIOSETOWN, (char*)&pgrp) == -1)
269abb0f93cSkardel 		{
2708585484eSchristos 			msyslog(LOG_ERR, "ioctl(FIOSETOWN) fails: %m - EXITING");
271abb0f93cSkardel 			exit(1);
272abb0f93cSkardel 			/*NOTREACHED*/
273abb0f93cSkardel 		}
274abb0f93cSkardel #  elif defined(F_SETOWN)
275abb0f93cSkardel 		if (fcntl(fd, F_SETOWN, pgrp) == -1)
276abb0f93cSkardel 		{
2778585484eSchristos 			msyslog(LOG_ERR, "fcntl(F_SETOWN) fails: %m - EXITING");
278abb0f93cSkardel 			exit(1);
279abb0f93cSkardel 			/*NOTREACHED*/
280abb0f93cSkardel 		}
281abb0f93cSkardel #  else
282abb0f93cSkardel #	include "Bletch: Need to set process(group) to receive SIG(IO|POLL)"
283abb0f93cSkardel #  endif
284abb0f93cSkardel 	}
285abb0f93cSkardel # endif /* USE_UDP_SIGPOLL */
286abb0f93cSkardel }
287abb0f93cSkardel 
2888585484eSchristos static RETSIGTYPE
sigio_handler(int sig)289abb0f93cSkardel sigio_handler(
290abb0f93cSkardel 	int sig
291abb0f93cSkardel 	)
292abb0f93cSkardel {
293abb0f93cSkardel 	int saved_errno = errno;
294abb0f93cSkardel 	l_fp ts;
295abb0f93cSkardel 
296abb0f93cSkardel 	get_systime(&ts);
297abb0f93cSkardel 
298abb0f93cSkardel # if defined(HAVE_SIGACTION)
299abb0f93cSkardel 	sigio_handler_active++;
300abb0f93cSkardel 	if (sigio_handler_active != 1)  /* This should never happen! */
301abb0f93cSkardel 	    msyslog(LOG_ERR, "sigio_handler: sigio_handler_active != 1");
302abb0f93cSkardel # endif
303abb0f93cSkardel 
3048585484eSchristos 	INSIST(input_handler_callback != NULL);
3058585484eSchristos 	(*input_handler_callback)(&ts);
306abb0f93cSkardel 
307abb0f93cSkardel # if defined(HAVE_SIGACTION)
308abb0f93cSkardel 	sigio_handler_active--;
309abb0f93cSkardel 	if (sigio_handler_active != 0)  /* This should never happen! */
310abb0f93cSkardel 	    msyslog(LOG_ERR, "sigio_handler: sigio_handler_active != 0");
311abb0f93cSkardel # endif
312abb0f93cSkardel 
313abb0f93cSkardel 	errno = saved_errno;
314abb0f93cSkardel }
315abb0f93cSkardel 
316abb0f93cSkardel /*
317abb0f93cSkardel  * Signal support routines.
318abb0f93cSkardel  */
319abb0f93cSkardel # ifdef HAVE_SIGACTION
320abb0f93cSkardel void
set_signal(input_handler_t * input)3218585484eSchristos set_signal(input_handler_t *input)
322abb0f93cSkardel {
3238585484eSchristos 	INSIST(input != NULL);
3248585484eSchristos 
3258585484eSchristos 	input_handler_callback = input;
3268585484eSchristos 
3278585484eSchristos 	using_sigio = TRUE;
328abb0f93cSkardel #  ifdef USE_SIGIO
329abb0f93cSkardel 	(void) signal_no_reset(SIGIO, sigio_handler);
330abb0f93cSkardel # endif
331abb0f93cSkardel #  ifdef USE_SIGPOLL
332abb0f93cSkardel 	(void) signal_no_reset(SIGPOLL, sigio_handler);
333abb0f93cSkardel # endif
334abb0f93cSkardel }
335abb0f93cSkardel 
336abb0f93cSkardel void
block_io_and_alarm(void)337abb0f93cSkardel block_io_and_alarm(void)
338abb0f93cSkardel {
339abb0f93cSkardel 	sigset_t set;
340abb0f93cSkardel 
341abb0f93cSkardel 	if (sigemptyset(&set))
342abb0f93cSkardel 	    msyslog(LOG_ERR, "block_io_and_alarm: sigemptyset() failed: %m");
343abb0f93cSkardel #  if defined(USE_SIGIO)
344abb0f93cSkardel 	if (sigaddset(&set, SIGIO))
345abb0f93cSkardel 	    msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGIO) failed: %m");
346abb0f93cSkardel #  endif
347abb0f93cSkardel #  if defined(USE_SIGPOLL)
348abb0f93cSkardel 	if (sigaddset(&set, SIGPOLL))
349abb0f93cSkardel 	    msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGPOLL) failed: %m");
350abb0f93cSkardel #  endif
351abb0f93cSkardel 	if (sigaddset(&set, SIGALRM))
352abb0f93cSkardel 	    msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGALRM) failed: %m");
353abb0f93cSkardel 
354abb0f93cSkardel 	if (sigprocmask(SIG_BLOCK, &set, NULL))
355abb0f93cSkardel 	    msyslog(LOG_ERR, "block_io_and_alarm: sigprocmask() failed: %m");
356abb0f93cSkardel }
357abb0f93cSkardel 
358abb0f93cSkardel void
block_sigio(void)359abb0f93cSkardel block_sigio(void)
360abb0f93cSkardel {
361abb0f93cSkardel 	if ( sigio_handler_active == 0 )  /* not called from within signal handler */
362abb0f93cSkardel 	{
363abb0f93cSkardel 		sigset_t set;
364abb0f93cSkardel 
365abb0f93cSkardel 		++sigio_block_count;
366abb0f93cSkardel 		if (sigio_block_count > 1)
367abb0f93cSkardel 		    msyslog(LOG_INFO, "block_sigio: sigio_block_count > 1");
368abb0f93cSkardel 		if (sigio_block_count < 1)
369abb0f93cSkardel 		    msyslog(LOG_INFO, "block_sigio: sigio_block_count < 1");
370abb0f93cSkardel 
371abb0f93cSkardel 		if (sigemptyset(&set))
372abb0f93cSkardel 		    msyslog(LOG_ERR, "block_sigio: sigemptyset() failed: %m");
373abb0f93cSkardel #	if defined(USE_SIGIO)
374abb0f93cSkardel 		if (sigaddset(&set, SIGIO))
375abb0f93cSkardel 		    msyslog(LOG_ERR, "block_sigio: sigaddset(SIGIO) failed: %m");
376abb0f93cSkardel #	endif
377abb0f93cSkardel #	if defined(USE_SIGPOLL)
378abb0f93cSkardel 		if (sigaddset(&set, SIGPOLL))
379abb0f93cSkardel 		    msyslog(LOG_ERR, "block_sigio: sigaddset(SIGPOLL) failed: %m");
380abb0f93cSkardel #	endif
381abb0f93cSkardel 
382abb0f93cSkardel 		if (sigprocmask(SIG_BLOCK, &set, NULL))
383abb0f93cSkardel 		    msyslog(LOG_ERR, "block_sigio: sigprocmask() failed: %m");
384abb0f93cSkardel 	}
385abb0f93cSkardel }
386abb0f93cSkardel 
387abb0f93cSkardel void
unblock_io_and_alarm(void)388abb0f93cSkardel unblock_io_and_alarm(void)
389abb0f93cSkardel {
390abb0f93cSkardel 	sigset_t unset;
391abb0f93cSkardel 
392abb0f93cSkardel 	if (sigemptyset(&unset))
393abb0f93cSkardel 	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigemptyset() failed: %m");
394abb0f93cSkardel 
395abb0f93cSkardel #  if defined(USE_SIGIO)
396abb0f93cSkardel 	if (sigaddset(&unset, SIGIO))
397abb0f93cSkardel 	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGIO) failed: %m");
398abb0f93cSkardel #  endif
399abb0f93cSkardel #  if defined(USE_SIGPOLL)
400abb0f93cSkardel 	if (sigaddset(&unset, SIGPOLL))
401abb0f93cSkardel 	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGPOLL) failed: %m");
402abb0f93cSkardel #  endif
403abb0f93cSkardel 	if (sigaddset(&unset, SIGALRM))
404abb0f93cSkardel 	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGALRM) failed: %m");
405abb0f93cSkardel 
406abb0f93cSkardel 	if (sigprocmask(SIG_UNBLOCK, &unset, NULL))
407abb0f93cSkardel 	    msyslog(LOG_ERR, "unblock_io_and_alarm: sigprocmask() failed: %m");
408abb0f93cSkardel }
409abb0f93cSkardel 
410abb0f93cSkardel void
unblock_sigio(void)411abb0f93cSkardel unblock_sigio(void)
412abb0f93cSkardel {
413abb0f93cSkardel 	if ( sigio_handler_active == 0 )  /* not called from within signal handler */
414abb0f93cSkardel 	{
415abb0f93cSkardel 		sigset_t unset;
416abb0f93cSkardel 
417abb0f93cSkardel 		--sigio_block_count;
418abb0f93cSkardel 		if (sigio_block_count > 0)
419abb0f93cSkardel 		    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count > 0");
420abb0f93cSkardel 		if (sigio_block_count < 0)
421abb0f93cSkardel 		    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count < 0");
422abb0f93cSkardel 
423abb0f93cSkardel 		if (sigemptyset(&unset))
424abb0f93cSkardel 		    msyslog(LOG_ERR, "unblock_sigio: sigemptyset() failed: %m");
425abb0f93cSkardel 
426abb0f93cSkardel #	if defined(USE_SIGIO)
427abb0f93cSkardel 		if (sigaddset(&unset, SIGIO))
428abb0f93cSkardel 		    msyslog(LOG_ERR, "unblock_sigio: sigaddset(SIGIO) failed: %m");
429abb0f93cSkardel #	endif
430abb0f93cSkardel #	if defined(USE_SIGPOLL)
431abb0f93cSkardel 		if (sigaddset(&unset, SIGPOLL))
432abb0f93cSkardel 		    msyslog(LOG_ERR, "unblock_sigio: sigaddset(SIGPOLL) failed: %m");
433abb0f93cSkardel #	endif
434abb0f93cSkardel 
435abb0f93cSkardel 		if (sigprocmask(SIG_UNBLOCK, &unset, NULL))
436abb0f93cSkardel 		    msyslog(LOG_ERR, "unblock_sigio: sigprocmask() failed: %m");
437abb0f93cSkardel 	}
438abb0f93cSkardel }
439abb0f93cSkardel 
440abb0f93cSkardel void
wait_for_signal(void)441abb0f93cSkardel wait_for_signal(void)
442abb0f93cSkardel {
443abb0f93cSkardel 	sigset_t old;
444abb0f93cSkardel 
445abb0f93cSkardel 	if (sigprocmask(SIG_UNBLOCK, NULL, &old))
446abb0f93cSkardel 	    msyslog(LOG_ERR, "wait_for_signal: sigprocmask() failed: %m");
447abb0f93cSkardel 
448abb0f93cSkardel #  if defined(USE_SIGIO)
449abb0f93cSkardel 	if (sigdelset(&old, SIGIO))
450abb0f93cSkardel 	    msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGIO) failed: %m");
451abb0f93cSkardel #  endif
452abb0f93cSkardel #  if defined(USE_SIGPOLL)
453abb0f93cSkardel 	if (sigdelset(&old, SIGPOLL))
454abb0f93cSkardel 	    msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGPOLL) failed: %m");
455abb0f93cSkardel #  endif
456abb0f93cSkardel 	if (sigdelset(&old, SIGALRM))
457abb0f93cSkardel 	    msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGALRM) failed: %m");
458abb0f93cSkardel 
459abb0f93cSkardel 	if (sigsuspend(&old) && (errno != EINTR))
460abb0f93cSkardel 	    msyslog(LOG_ERR, "wait_for_signal: sigsuspend() failed: %m");
461abb0f93cSkardel }
462abb0f93cSkardel 
463abb0f93cSkardel # else /* !HAVE_SIGACTION */
464abb0f93cSkardel /*
465abb0f93cSkardel  * Must be an old bsd system.
466abb0f93cSkardel  * We assume there is no SIGPOLL.
467abb0f93cSkardel  */
468abb0f93cSkardel 
469abb0f93cSkardel void
block_io_and_alarm(void)470abb0f93cSkardel block_io_and_alarm(void)
471abb0f93cSkardel {
472abb0f93cSkardel 	int mask;
473abb0f93cSkardel 
474abb0f93cSkardel 	mask = sigmask(SIGIO) | sigmask(SIGALRM);
475abb0f93cSkardel 	if (sigblock(mask))
476abb0f93cSkardel 	    msyslog(LOG_ERR, "block_io_and_alarm: sigblock() failed: %m");
477abb0f93cSkardel }
478abb0f93cSkardel 
479abb0f93cSkardel void
block_sigio(void)480abb0f93cSkardel block_sigio(void)
481abb0f93cSkardel {
482abb0f93cSkardel 	int mask;
483abb0f93cSkardel 
484abb0f93cSkardel 	++sigio_block_count;
485abb0f93cSkardel 	if (sigio_block_count > 1)
486abb0f93cSkardel 	    msyslog(LOG_INFO, "block_sigio: sigio_block_count > 1");
487abb0f93cSkardel 	if (sigio_block_count < 1)
488abb0f93cSkardel 	    msyslog(LOG_INFO, "block_sigio: sigio_block_count < 1");
489abb0f93cSkardel 
490abb0f93cSkardel 	mask = sigmask(SIGIO);
491abb0f93cSkardel 	if (sigblock(mask))
492abb0f93cSkardel 	    msyslog(LOG_ERR, "block_sigio: sigblock() failed: %m");
493abb0f93cSkardel }
494abb0f93cSkardel 
495abb0f93cSkardel void
set_signal(input_handler_t * input)4968585484eSchristos set_signal(input_handler_t *input)
497abb0f93cSkardel {
4988585484eSchristos 	INSIST(input != NULL);
4998585484eSchristos 
5008585484eSchristos 	input_handler_callback = input;
5018585484eSchristos 
5028585484eSchristos 	using_sigio = TRUE;
503abb0f93cSkardel 	(void) signal_no_reset(SIGIO, sigio_handler);
504abb0f93cSkardel }
505abb0f93cSkardel 
506abb0f93cSkardel void
unblock_io_and_alarm(void)507abb0f93cSkardel unblock_io_and_alarm(void)
508abb0f93cSkardel {
509abb0f93cSkardel 	int mask, omask;
510abb0f93cSkardel 
511abb0f93cSkardel 	mask = sigmask(SIGIO) | sigmask(SIGALRM);
512abb0f93cSkardel 	omask = sigblock(0);
513abb0f93cSkardel 	omask &= ~mask;
514abb0f93cSkardel 	(void) sigsetmask(omask);
515abb0f93cSkardel }
516abb0f93cSkardel 
517abb0f93cSkardel void
unblock_sigio(void)518abb0f93cSkardel unblock_sigio(void)
519abb0f93cSkardel {
520abb0f93cSkardel 	int mask, omask;
521abb0f93cSkardel 
522abb0f93cSkardel 	--sigio_block_count;
523abb0f93cSkardel 	if (sigio_block_count > 0)
524abb0f93cSkardel 	    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count > 0");
525abb0f93cSkardel 	if (sigio_block_count < 0)
526abb0f93cSkardel 	    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count < 0");
527abb0f93cSkardel 	mask = sigmask(SIGIO);
528abb0f93cSkardel 	omask = sigblock(0);
529abb0f93cSkardel 	omask &= ~mask;
530abb0f93cSkardel 	(void) sigsetmask(omask);
531abb0f93cSkardel }
532abb0f93cSkardel 
533abb0f93cSkardel void
wait_for_signal(void)534abb0f93cSkardel wait_for_signal(void)
535abb0f93cSkardel {
536abb0f93cSkardel 	int mask, omask;
537abb0f93cSkardel 
538abb0f93cSkardel 	mask = sigmask(SIGIO) | sigmask(SIGALRM);
539abb0f93cSkardel 	omask = sigblock(0);
540abb0f93cSkardel 	omask &= ~mask;
541abb0f93cSkardel 	if (sigpause(omask) && (errno != EINTR))
542abb0f93cSkardel 	    msyslog(LOG_ERR, "wait_for_signal: sigspause() failed: %m");
543abb0f93cSkardel }
544abb0f93cSkardel 
545abb0f93cSkardel # endif /* HAVE_SIGACTION */
546abb0f93cSkardel #else
547abb0f93cSkardel int  NotAnEmptyCompilationUnit;
548abb0f93cSkardel #endif
549