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