Annotation of embedaddon/ntp/libntp/iosignal.c, revision 1.1
1.1 ! misho 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 (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
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>