uxpoll.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /* On some systems this is needed to get poll.h to define eg.. POLLRDNORM */
  2. #define _XOPEN_SOURCE
  3. #include <poll.h>
  4. #include "putty.h"
  5. #include "tree234.h"
  6. struct pollwrapper {
  7. struct pollfd *fds;
  8. size_t nfd, fdsize;
  9. tree234 *fdtopos;
  10. };
  11. typedef struct pollwrap_fdtopos pollwrap_fdtopos;
  12. struct pollwrap_fdtopos {
  13. int fd;
  14. size_t pos;
  15. };
  16. static int pollwrap_fd_cmp(void *av, void *bv)
  17. {
  18. pollwrap_fdtopos *a = (pollwrap_fdtopos *)av;
  19. pollwrap_fdtopos *b = (pollwrap_fdtopos *)bv;
  20. return a->fd < b->fd ? -1 : a->fd > b->fd ? +1 : 0;
  21. }
  22. pollwrapper *pollwrap_new(void)
  23. {
  24. pollwrapper *pw = snew(pollwrapper);
  25. pw->fdsize = 16;
  26. pw->nfd = 0;
  27. pw->fds = snewn(pw->fdsize, struct pollfd);
  28. pw->fdtopos = newtree234(pollwrap_fd_cmp);
  29. return pw;
  30. }
  31. void pollwrap_free(pollwrapper *pw)
  32. {
  33. pollwrap_clear(pw);
  34. freetree234(pw->fdtopos);
  35. sfree(pw->fds);
  36. sfree(pw);
  37. }
  38. void pollwrap_clear(pollwrapper *pw)
  39. {
  40. pw->nfd = 0;
  41. for (pollwrap_fdtopos *f2p;
  42. (f2p = delpos234(pw->fdtopos, 0)) != NULL ;)
  43. sfree(f2p);
  44. }
  45. void pollwrap_add_fd_events(pollwrapper *pw, int fd, int events)
  46. {
  47. pollwrap_fdtopos *f2p, f2p_find;
  48. assert(fd >= 0);
  49. f2p_find.fd = fd;
  50. f2p = find234(pw->fdtopos, &f2p_find, NULL);
  51. if (!f2p) {
  52. sgrowarray(pw->fds, pw->fdsize, pw->nfd);
  53. size_t index = pw->nfd++;
  54. pw->fds[index].fd = fd;
  55. pw->fds[index].events = pw->fds[index].revents = 0;
  56. f2p = snew(pollwrap_fdtopos);
  57. f2p->fd = fd;
  58. f2p->pos = index;
  59. pollwrap_fdtopos *added = add234(pw->fdtopos, f2p);
  60. assert(added == f2p);
  61. }
  62. pw->fds[f2p->pos].events |= events;
  63. }
  64. /* Omit any of the POLL{RD,WR}{NORM,BAND} flag values that are still
  65. * not defined by poll.h, just in case */
  66. #ifndef POLLRDNORM
  67. #define POLLRDNORM 0
  68. #endif
  69. #ifndef POLLRDBAND
  70. #define POLLRDBAND 0
  71. #endif
  72. #ifndef POLLWRNORM
  73. #define POLLWRNORM 0
  74. #endif
  75. #ifndef POLLWRBAND
  76. #define POLLWRBAND 0
  77. #endif
  78. #define SELECT_R_IN (POLLIN | POLLRDNORM | POLLRDBAND)
  79. #define SELECT_W_IN (POLLOUT | POLLWRNORM | POLLWRBAND)
  80. #define SELECT_X_IN (POLLPRI)
  81. #define SELECT_R_OUT (SELECT_R_IN | POLLERR | POLLHUP)
  82. #define SELECT_W_OUT (SELECT_W_IN | POLLERR)
  83. #define SELECT_X_OUT (SELECT_X_IN)
  84. void pollwrap_add_fd_rwx(pollwrapper *pw, int fd, int rwx)
  85. {
  86. int events = 0;
  87. if (rwx & SELECT_R)
  88. events |= SELECT_R_IN;
  89. if (rwx & SELECT_W)
  90. events |= SELECT_W_IN;
  91. if (rwx & SELECT_X)
  92. events |= SELECT_X_IN;
  93. pollwrap_add_fd_events(pw, fd, events);
  94. }
  95. int pollwrap_poll_instant(pollwrapper *pw)
  96. {
  97. return poll(pw->fds, pw->nfd, 0);
  98. }
  99. int pollwrap_poll_endless(pollwrapper *pw)
  100. {
  101. return poll(pw->fds, pw->nfd, -1);
  102. }
  103. int pollwrap_poll_timeout(pollwrapper *pw, int milliseconds)
  104. {
  105. assert(milliseconds >= 0);
  106. return poll(pw->fds, pw->nfd, milliseconds);
  107. }
  108. static void pollwrap_get_fd_events_revents(pollwrapper *pw, int fd,
  109. int *events_p, int *revents_p)
  110. {
  111. pollwrap_fdtopos *f2p, f2p_find;
  112. int events = 0, revents = 0;
  113. assert(fd >= 0);
  114. f2p_find.fd = fd;
  115. f2p = find234(pw->fdtopos, &f2p_find, NULL);
  116. if (f2p) {
  117. events = pw->fds[f2p->pos].events;
  118. revents = pw->fds[f2p->pos].revents;
  119. }
  120. if (events_p)
  121. *events_p = events;
  122. if (revents_p)
  123. *revents_p = revents;
  124. }
  125. int pollwrap_get_fd_events(pollwrapper *pw, int fd)
  126. {
  127. int revents;
  128. pollwrap_get_fd_events_revents(pw, fd, NULL, &revents);
  129. return revents;
  130. }
  131. int pollwrap_get_fd_rwx(pollwrapper *pw, int fd)
  132. {
  133. int events, revents;
  134. pollwrap_get_fd_events_revents(pw, fd, &events, &revents);
  135. int rwx = 0;
  136. if ((events & POLLIN) && (revents & SELECT_R_OUT))
  137. rwx |= SELECT_R;
  138. if ((events & POLLOUT) && (revents & SELECT_W_OUT))
  139. rwx |= SELECT_W;
  140. if ((events & POLLPRI) && (revents & SELECT_X_OUT))
  141. rwx |= SELECT_X;
  142. return rwx;
  143. }