iosignal.c revision 132452
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) 29static 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 */ 41static int sigio_handler_active = 0; 42# endif 43extern 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 */ 88int 89init_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 212void 213init_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 295RETSIGTYPE 296sigio_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 326void 327set_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 337void 338block_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 359void 360block_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 388void 389unblock_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 411void 412unblock_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 441void 442wait_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 470void 471block_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 480void 481block_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 496void 497set_signal(void) 498{ 499 (void) signal_no_reset(SIGIO, sigio_handler); 500} 501 502void 503unblock_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 513void 514unblock_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 529void 530wait_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 543int NotAnEmptyCompilationUnit; 544#endif 545