/contrib/ntp/libntp/iosignal.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 557 lines · 412 code · 70 blank · 75 comment · 111 complexity · 8c3815570d7d245b6475afa4c67e7145 MD5 · raw file

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