1 /* $NetBSD: iosignal.c,v 1.2 2003/12/04 16:23:36 drochner Exp $ */
4 * iosignal.c - input/output routines for ntpd. The socket-opening code
5 * was shamelessly stolen from ntpd.
10 * Do the #includes differently, as under some versions of Linux
11 * sys/param.h has a #undef CONFIG_PHONE line in it.
13 * As we have ~40 CONFIG_ variables, I don't feel like renaming them
14 * every time somebody adds a new macro to some system header.
23 #ifdef HAVE_SYS_PARAM_H
24 # include <sys/param.h>
25 #endif /* HAVE_SYS_PARAM_H */
26 #ifdef HAVE_SYS_IOCTL_H
27 # include <sys/ioctl.h>
30 #include <arpa/inet.h>
32 #if _BSDI_VERSION >= 199510
39 # define FNDELAY O_NDELAY
42 #include "ntp_machine.h"
46 #include "ntp_stdlib.h"
49 #if defined(HAVE_SIGNALED_IO)
50 static int sigio_block_count
= 0;
51 # if defined(HAVE_SIGACTION)
53 * If sigaction() is used for signal handling and a signal is
54 * pending then the kernel blocks the signal before it calls
57 * The variable below is used to take care that the SIGIO signal
58 * is not unintentionally unblocked inside the sigio_handler()
59 * if the handler executes a piece of code that is normally
60 * bracketed by BLOCKIO()/UNBLOCKIO() calls.
62 static int sigio_handler_active
= 0;
64 extern void input_handler
P((l_fp
*));
67 * SIGPOLL and SIGIO ROUTINES.
71 * Some systems (MOST) define SIGPOLL == SIGIO, others SIGIO == SIGPOLL, and
72 * a few have separate SIGIO and SIGPOLL signals. This code checks for the
73 * SIGIO == SIGPOLL case at compile time.
74 * Do not define USE_SIGPOLL or USE_SIGIO.
75 * these are interal only to iosignal.c!
77 # if defined(USE_SIGPOLL)
80 # if defined(USE_SIGIO)
84 # if defined(USE_TTY_SIGPOLL) || defined(USE_UDP_SIGPOLL)
88 # if !defined(USE_TTY_SIGPOLL) || !defined(USE_UDP_SIGPOLL)
92 # if defined(USE_SIGIO) && defined(USE_SIGPOLL)
96 # endif /* SIGIO == SIGPOLL */
97 # endif /* USE_SIGIO && USE_SIGIO */
101 * TTY initialization routines.
105 struct refclockio
*rio
108 # ifdef USE_TTY_SIGPOLL
110 /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
111 if (ioctl(rio
->fd
, I_SETSIG
, S_INPUT
) < 0)
114 "init_clock_sig: ioctl(I_SETSIG, S_INPUT) failed: %m");
121 * Special cases first!
123 /* Was: defined(SYS_HPUX) */
124 # if defined(FIOSSAIOOWN) && defined(FIOSNBIO) && defined(FIOSSAIOSTAT)
129 /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
131 if (ioctl(rio
->fd
, FIOSSAIOOWN
, (char *)&pgrp
) == -1)
133 msyslog(LOG_ERR
, "ioctl(FIOSSAIOOWN) fails for clock I/O: %m");
139 * set non-blocking, async I/O on the descriptor
141 if (ioctl(rio
->fd
, FIOSNBIO
, (char *)&on
) == -1)
143 msyslog(LOG_ERR
, "ioctl(FIOSNBIO) fails for clock I/O: %m");
148 if (ioctl(rio
->fd
, FIOSSAIOSTAT
, (char *)&on
) == -1)
150 msyslog(LOG_ERR
, "ioctl(FIOSSAIOSTAT) fails for clock I/O: %m");
156 # endif /* SYS_HPUX: FIOSSAIOOWN && FIOSNBIO && FIOSSAIOSTAT */
157 /* Was: defined(SYS_AIX) && !defined(_BSD) */
158 # if !defined(_BSD) && defined(_AIX) && defined(FIOASYNC) && defined(FIOSETOWN)
160 * SYSV compatibility mode under AIX.
166 /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
167 if (ioctl(rio
->fd
, FIOASYNC
, (char *)&on
) == -1)
169 msyslog(LOG_ERR
, "ioctl(FIOASYNC) fails for clock I/O: %m");
173 if (ioctl(rio
->fd
, FIOSETOWN
, (char*)&pgrp
) == -1)
175 msyslog(LOG_ERR
, "ioctl(FIOSETOWN) fails for clock I/O: %m");
179 if (fcntl(rio
->fd
, F_SETFL
, FNDELAY
|FASYNC
) < 0)
181 msyslog(LOG_ERR
, "fcntl(FNDELAY|FASYNC) fails for clock I/O: %m");
186 # endif /* AIX && !BSD: !_BSD && FIOASYNC && FIOSETOWN */
189 /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
190 # if defined(TIOCSCTTY) && defined(USE_FSETOWNCTTY)
192 * there are, however, always exceptions to the rules
193 * one is, that OSF accepts SETOWN on TTY fd's only, iff they are
194 * CTTYs. SunOS and HPUX do not semm to have this restriction.
195 * another question is: how can you do multiple SIGIO from several
196 * ttys (as they all should be CTTYs), wondering...
200 if (ioctl(rio
->fd
, TIOCSCTTY
, 0) == -1)
202 msyslog(LOG_ERR
, "ioctl(TIOCSCTTY, 0) fails for clock I/O: %m");
205 # endif /* TIOCSCTTY && USE_FSETOWNCTTY */
207 if (fcntl(rio
->fd
, F_SETOWN
, getpid()) == -1)
209 msyslog(LOG_ERR
, "fcntl(F_SETOWN) fails for clock I/O: %m");
213 if (fcntl(rio
->fd
, F_SETFL
, FNDELAY
|FASYNC
) < 0)
216 "fcntl(FNDELAY|FASYNC) fails for clock I/O: %m");
221 # endif /* CLOCK_DONE */
222 # endif /* !USE_TTY_SIGPOLL */
232 # ifdef USE_UDP_SIGPOLL
234 if (ioctl(fd
, I_SETSIG
, S_INPUT
) < 0)
237 "init_socket_sig: ioctl(I_SETSIG, S_INPUT) failed: %m");
241 # else /* USE_UDP_SIGPOLL */
248 # if defined(FIOASYNC)
249 if (ioctl(fd
, FIOASYNC
, (char *)&on
) == -1)
251 msyslog(LOG_ERR
, "ioctl(FIOASYNC) fails: %m");
255 # elif defined(FASYNC)
259 if ((flags
= fcntl(fd
, F_GETFL
, 0)) == -1)
261 msyslog(LOG_ERR
, "fcntl(F_GETFL) fails: %m");
265 if (fcntl(fd
, F_SETFL
, flags
|FASYNC
) < 0)
267 msyslog(LOG_ERR
, "fcntl(...|FASYNC) fails: %m");
273 # include "Bletch: Need asynchronous I/O!"
276 # ifdef UDP_BACKWARDS_SETOWN
282 # if defined(SIOCSPGRP)
283 if (ioctl(fd
, SIOCSPGRP
, (char *)&pgrp
) == -1)
285 msyslog(LOG_ERR
, "ioctl(SIOCSPGRP) fails: %m");
289 # elif defined(FIOSETOWN)
290 if (ioctl(fd
, FIOSETOWN
, (char*)&pgrp
) == -1)
292 msyslog(LOG_ERR
, "ioctl(FIOSETOWN) fails: %m");
296 # elif defined(F_SETOWN)
297 if (fcntl(fd
, F_SETOWN
, pgrp
) == -1)
299 msyslog(LOG_ERR
, "fcntl(F_SETOWN) fails: %m");
304 # include "Bletch: Need to set process(group) to receive SIG(IO|POLL)"
307 # endif /* USE_UDP_SIGPOLL */
315 int saved_errno
= errno
;
320 # if defined(HAVE_SIGACTION)
321 sigio_handler_active
++;
322 if (sigio_handler_active
!= 1) /* This should never happen! */
323 msyslog(LOG_ERR
, "sigio_handler: sigio_handler_active != 1");
326 (void)input_handler(&ts
);
328 # if defined(HAVE_SIGACTION)
329 sigio_handler_active
--;
330 if (sigio_handler_active
!= 0) /* This should never happen! */
331 msyslog(LOG_ERR
, "sigio_handler: sigio_handler_active != 0");
338 * Signal support routines.
340 # ifdef HAVE_SIGACTION
345 (void) signal_no_reset(SIGIO
, sigio_handler
);
348 (void) signal_no_reset(SIGPOLL
, sigio_handler
);
353 block_io_and_alarm(void)
357 if (sigemptyset(&set
))
358 msyslog(LOG_ERR
, "block_io_and_alarm: sigemptyset() failed: %m");
359 # if defined(USE_SIGIO)
360 if (sigaddset(&set
, SIGIO
))
361 msyslog(LOG_ERR
, "block_io_and_alarm: sigaddset(SIGIO) failed: %m");
363 # if defined(USE_SIGPOLL)
364 if (sigaddset(&set
, SIGPOLL
))
365 msyslog(LOG_ERR
, "block_io_and_alarm: sigaddset(SIGPOLL) failed: %m");
367 if (sigaddset(&set
, SIGALRM
))
368 msyslog(LOG_ERR
, "block_io_and_alarm: sigaddset(SIGALRM) failed: %m");
370 if (sigprocmask(SIG_BLOCK
, &set
, NULL
))
371 msyslog(LOG_ERR
, "block_io_and_alarm: sigprocmask() failed: %m");
377 if ( sigio_handler_active
== 0 ) /* not called from within signal handler */
382 if (sigio_block_count
> 1)
383 msyslog(LOG_INFO
, "block_sigio: sigio_block_count > 1");
384 if (sigio_block_count
< 1)
385 msyslog(LOG_INFO
, "block_sigio: sigio_block_count < 1");
387 if (sigemptyset(&set
))
388 msyslog(LOG_ERR
, "block_sigio: sigemptyset() failed: %m");
389 # if defined(USE_SIGIO)
390 if (sigaddset(&set
, SIGIO
))
391 msyslog(LOG_ERR
, "block_sigio: sigaddset(SIGIO) failed: %m");
393 # if defined(USE_SIGPOLL)
394 if (sigaddset(&set
, SIGPOLL
))
395 msyslog(LOG_ERR
, "block_sigio: sigaddset(SIGPOLL) failed: %m");
398 if (sigprocmask(SIG_BLOCK
, &set
, NULL
))
399 msyslog(LOG_ERR
, "block_sigio: sigprocmask() failed: %m");
404 unblock_io_and_alarm(void)
408 if (sigemptyset(&unset
))
409 msyslog(LOG_ERR
, "unblock_io_and_alarm: sigemptyset() failed: %m");
411 # if defined(USE_SIGIO)
412 if (sigaddset(&unset
, SIGIO
))
413 msyslog(LOG_ERR
, "unblock_io_and_alarm: sigaddset(SIGIO) failed: %m");
415 # if defined(USE_SIGPOLL)
416 if (sigaddset(&unset
, SIGPOLL
))
417 msyslog(LOG_ERR
, "unblock_io_and_alarm: sigaddset(SIGPOLL) failed: %m");
419 if (sigaddset(&unset
, SIGALRM
))
420 msyslog(LOG_ERR
, "unblock_io_and_alarm: sigaddset(SIGALRM) failed: %m");
422 if (sigprocmask(SIG_UNBLOCK
, &unset
, NULL
))
423 msyslog(LOG_ERR
, "unblock_io_and_alarm: sigprocmask() failed: %m");
429 if ( sigio_handler_active
== 0 ) /* not called from within signal handler */
434 if (sigio_block_count
> 0)
435 msyslog(LOG_INFO
, "unblock_sigio: sigio_block_count > 0");
436 if (sigio_block_count
< 0)
437 msyslog(LOG_INFO
, "unblock_sigio: sigio_block_count < 0");
439 if (sigemptyset(&unset
))
440 msyslog(LOG_ERR
, "unblock_sigio: sigemptyset() failed: %m");
442 # if defined(USE_SIGIO)
443 if (sigaddset(&unset
, SIGIO
))
444 msyslog(LOG_ERR
, "unblock_sigio: sigaddset(SIGIO) failed: %m");
446 # if defined(USE_SIGPOLL)
447 if (sigaddset(&unset
, SIGPOLL
))
448 msyslog(LOG_ERR
, "unblock_sigio: sigaddset(SIGPOLL) failed: %m");
451 if (sigprocmask(SIG_UNBLOCK
, &unset
, NULL
))
452 msyslog(LOG_ERR
, "unblock_sigio: sigprocmask() failed: %m");
457 wait_for_signal(void)
461 if (sigprocmask(SIG_UNBLOCK
, NULL
, &old
))
462 msyslog(LOG_ERR
, "wait_for_signal: sigprocmask() failed: %m");
464 # if defined(USE_SIGIO)
465 if (sigdelset(&old
, SIGIO
))
466 msyslog(LOG_ERR
, "wait_for_signal: sigdelset(SIGIO) failed: %m");
468 # if defined(USE_SIGPOLL)
469 if (sigdelset(&old
, SIGPOLL
))
470 msyslog(LOG_ERR
, "wait_for_signal: sigdelset(SIGPOLL) failed: %m");
472 if (sigdelset(&old
, SIGALRM
))
473 msyslog(LOG_ERR
, "wait_for_signal: sigdelset(SIGALRM) failed: %m");
475 if (sigsuspend(&old
) && (errno
!= EINTR
))
476 msyslog(LOG_ERR
, "wait_for_signal: sigsuspend() failed: %m");
479 # else /* !HAVE_SIGACTION */
481 * Must be an old bsd system.
482 * We assume there is no SIGPOLL.
486 block_io_and_alarm(void)
490 mask
= sigmask(SIGIO
) | sigmask(SIGALRM
);
492 msyslog(LOG_ERR
, "block_io_and_alarm: sigblock() failed: %m");
501 if (sigio_block_count
> 1)
502 msyslog(LOG_INFO
, "block_sigio: sigio_block_count > 1");
503 if (sigio_block_count
< 1)
504 msyslog(LOG_INFO
, "block_sigio: sigio_block_count < 1");
506 mask
= sigmask(SIGIO
);
508 msyslog(LOG_ERR
, "block_sigio: sigblock() failed: %m");
514 (void) signal_no_reset(SIGIO
, sigio_handler
);
518 unblock_io_and_alarm(void)
522 mask
= sigmask(SIGIO
) | sigmask(SIGALRM
);
525 (void) sigsetmask(omask
);
534 if (sigio_block_count
> 0)
535 msyslog(LOG_INFO
, "unblock_sigio: sigio_block_count > 0");
536 if (sigio_block_count
< 0)
537 msyslog(LOG_INFO
, "unblock_sigio: sigio_block_count < 0");
538 mask
= sigmask(SIGIO
);
541 (void) sigsetmask(omask
);
545 wait_for_signal(void)
549 mask
= sigmask(SIGIO
) | sigmask(SIGALRM
);
552 if (sigpause(omask
) && (errno
!= EINTR
))
553 msyslog(LOG_ERR
, "wait_for_signal: sigspause() failed: %m");
556 # endif /* HAVE_SIGACTION */
558 int NotAnEmptyCompilationUnit
;