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