PageRenderTime 59ms CodeModel.GetById 12ms app.highlight 41ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/ntp/libntp/iosignal.c

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