A clone of btpd with my configuration changes.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

213 lignes
5.1 KiB

  1. /* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
  2. /*
  3. * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. The name of the author may not be used to endorse or promote products
  15. * derived from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #ifdef HAVE_CONFIG_H
  29. #include "config.h"
  30. #endif
  31. #include <sys/types.h>
  32. #ifdef HAVE_SYS_TIME_H
  33. #include <sys/time.h>
  34. #else
  35. #include <sys/_time.h>
  36. #endif
  37. #include <sys/queue.h>
  38. #include <sys/socket.h>
  39. #include <signal.h>
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <unistd.h>
  44. #include <errno.h>
  45. #ifdef HAVE_FCNTL_H
  46. #include <fcntl.h>
  47. #endif
  48. #include "event.h"
  49. #include "evsignal.h"
  50. #include "log.h"
  51. extern struct event_list signalqueue;
  52. static sig_atomic_t evsigcaught[NSIG];
  53. static int needrecalc;
  54. volatile sig_atomic_t evsignal_caught = 0;
  55. static struct event ev_signal;
  56. static int ev_signal_pair[2];
  57. static int ev_signal_added;
  58. /* Callback for when the signal handler write a byte to our signaling socket */
  59. static void
  60. evsignal_cb(int fd, short what, void *arg)
  61. {
  62. static char signals[100];
  63. struct event *ev = arg;
  64. ssize_t n;
  65. n = read(fd, signals, sizeof(signals));
  66. if (n == -1)
  67. event_err(1, "%s: read", __func__);
  68. event_add(ev, NULL);
  69. }
  70. #ifdef HAVE_SETFD
  71. #define FD_CLOSEONEXEC(x) do { \
  72. if (fcntl(x, F_SETFD, 1) == -1) \
  73. event_warn("fcntl(%d, F_SETFD)", x); \
  74. } while (0)
  75. #else
  76. #define FD_CLOSEONEXEC(x)
  77. #endif
  78. void
  79. evsignal_init(sigset_t *evsigmask)
  80. {
  81. sigemptyset(evsigmask);
  82. /*
  83. * Our signal handler is going to write to one end of the socket
  84. * pair to wake up our event loop. The event loop then scans for
  85. * signals that got delivered.
  86. */
  87. if (socketpair(AF_UNIX, SOCK_STREAM, 0, ev_signal_pair) == -1)
  88. event_err(1, "%s: socketpair", __func__);
  89. FD_CLOSEONEXEC(ev_signal_pair[0]);
  90. FD_CLOSEONEXEC(ev_signal_pair[1]);
  91. fcntl(ev_signal_pair[0], F_SETFL, O_NONBLOCK);
  92. event_set(&ev_signal, ev_signal_pair[1], EV_READ,
  93. evsignal_cb, &ev_signal);
  94. ev_signal.ev_flags |= EVLIST_INTERNAL;
  95. }
  96. int
  97. evsignal_add(sigset_t *evsigmask, struct event *ev)
  98. {
  99. int evsignal;
  100. if (ev->ev_events & (EV_READ|EV_WRITE))
  101. event_errx(1, "%s: EV_SIGNAL incompatible use", __func__);
  102. evsignal = EVENT_SIGNAL(ev);
  103. sigaddset(evsigmask, evsignal);
  104. return (0);
  105. }
  106. /*
  107. * Nothing to be done here.
  108. */
  109. int
  110. evsignal_del(sigset_t *evsigmask, struct event *ev)
  111. {
  112. int evsignal;
  113. evsignal = EVENT_SIGNAL(ev);
  114. sigdelset(evsigmask, evsignal);
  115. needrecalc = 1;
  116. return (sigaction(EVENT_SIGNAL(ev),(struct sigaction *)SIG_DFL, NULL));
  117. }
  118. static void
  119. evsignal_handler(int sig)
  120. {
  121. int save_errno = errno;
  122. evsigcaught[sig]++;
  123. evsignal_caught = 1;
  124. /* Wake up our notification mechanism */
  125. write(ev_signal_pair[0], "a", 1);
  126. errno = save_errno;
  127. }
  128. int
  129. evsignal_recalc(sigset_t *evsigmask)
  130. {
  131. struct sigaction sa;
  132. struct event *ev;
  133. if (!ev_signal_added) {
  134. ev_signal_added = 1;
  135. event_add(&ev_signal, NULL);
  136. }
  137. if (TAILQ_FIRST(&signalqueue) == NULL && !needrecalc)
  138. return (0);
  139. needrecalc = 0;
  140. if (sigprocmask(SIG_BLOCK, evsigmask, NULL) == -1)
  141. return (-1);
  142. /* Reinstall our signal handler. */
  143. memset(&sa, 0, sizeof(sa));
  144. sa.sa_handler = evsignal_handler;
  145. sa.sa_mask = *evsigmask;
  146. sa.sa_flags |= SA_RESTART;
  147. TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
  148. if (sigaction(EVENT_SIGNAL(ev), &sa, NULL) == -1)
  149. return (-1);
  150. }
  151. return (0);
  152. }
  153. int
  154. evsignal_deliver(sigset_t *evsigmask)
  155. {
  156. if (TAILQ_FIRST(&signalqueue) == NULL)
  157. return (0);
  158. return (sigprocmask(SIG_UNBLOCK, evsigmask, NULL));
  159. /* XXX - pending signals handled here */
  160. }
  161. void
  162. evsignal_process(void)
  163. {
  164. struct event *ev;
  165. sig_atomic_t ncalls;
  166. TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
  167. ncalls = evsigcaught[EVENT_SIGNAL(ev)];
  168. if (ncalls) {
  169. if (!(ev->ev_events & EV_PERSIST))
  170. event_del(ev);
  171. event_active(ev, EV_SIGNAL, ncalls);
  172. }
  173. }
  174. memset(evsigcaught, 0, sizeof(evsigcaught));
  175. evsignal_caught = 0;
  176. }