]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ntp/libntp/iosignal.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / ntp / libntp / iosignal.c
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)
48 static 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  */
60 static int sigio_handler_active = 0;
61 # endif
62 extern  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  */
101 int
102 init_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
225 void
226 init_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
308 RETSIGTYPE
309 sigio_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
339 void
340 set_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
350 void
351 block_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
372 void
373 block_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
401 void
402 unblock_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
424 void
425 unblock_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
454 void
455 wait_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
483 void
484 block_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
493 void
494 block_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
509 void
510 set_signal(void)
511 {
512         (void) signal_no_reset(SIGIO, sigio_handler);
513 }
514
515 void
516 unblock_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
526 void
527 unblock_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
542 void
543 wait_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
556 int  NotAnEmptyCompilationUnit;
557 #endif