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