uxsel.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*
  2. * uxsel.c
  3. *
  4. * This module is a sort of all-purpose interchange for file
  5. * descriptors. At one end it talks to network.c and pty.c and
  6. * anything else which might have one or more fds that need
  7. * select() or poll()-type things doing to them during an extended
  8. * program run; at the other end it talks to window.c or plink.c or
  9. * anything else which might have its own means of actually doing
  10. * those select()-type things.
  11. */
  12. #include <assert.h>
  13. #include "putty.h"
  14. #include "tree234.h"
  15. struct fd {
  16. int fd;
  17. int rwx; /* 4=except 2=write 1=read */
  18. uxsel_callback_fn callback;
  19. uxsel_id *id; /* for uxsel_input_remove */
  20. };
  21. static tree234 *fds;
  22. static int uxsel_fd_cmp(void *av, void *bv)
  23. {
  24. struct fd *a = (struct fd *)av;
  25. struct fd *b = (struct fd *)bv;
  26. if (a->fd < b->fd)
  27. return -1;
  28. if (a->fd > b->fd)
  29. return +1;
  30. return 0;
  31. }
  32. static int uxsel_fd_findcmp(void *av, void *bv)
  33. {
  34. int *a = (int *)av;
  35. struct fd *b = (struct fd *)bv;
  36. if (*a < b->fd)
  37. return -1;
  38. if (*a > b->fd)
  39. return +1;
  40. return 0;
  41. }
  42. void uxsel_init(void)
  43. {
  44. fds = newtree234(uxsel_fd_cmp);
  45. }
  46. /*
  47. * Here is the interface to fd-supplying modules. They supply an
  48. * fd, a set of read/write/execute states, and a callback function
  49. * for when the fd satisfies one of those states. Repeated calls to
  50. * uxsel_set on the same fd are perfectly legal and serve to change
  51. * the rwx state (typically you only want to select an fd for
  52. * writing when you actually have pending data you want to write to
  53. * it!).
  54. */
  55. void uxsel_set(int fd, int rwx, uxsel_callback_fn callback)
  56. {
  57. struct fd *newfd;
  58. assert(fd >= 0);
  59. uxsel_del(fd);
  60. if (rwx) {
  61. newfd = snew(struct fd);
  62. newfd->fd = fd;
  63. newfd->rwx = rwx;
  64. newfd->callback = callback;
  65. newfd->id = uxsel_input_add(fd, rwx);
  66. add234(fds, newfd);
  67. }
  68. }
  69. void uxsel_del(int fd)
  70. {
  71. struct fd *oldfd = find234(fds, &fd, uxsel_fd_findcmp);
  72. if (oldfd) {
  73. if (oldfd->id)
  74. uxsel_input_remove(oldfd->id);
  75. del234(fds, oldfd);
  76. sfree(oldfd);
  77. }
  78. }
  79. /*
  80. * And here is the interface to select-functionality-supplying
  81. * modules.
  82. */
  83. int next_fd(int *state, int *rwx)
  84. {
  85. struct fd *fd;
  86. fd = index234(fds, (*state)++);
  87. if (fd) {
  88. *rwx = fd->rwx;
  89. return fd->fd;
  90. } else
  91. return -1;
  92. }
  93. int first_fd(int *state, int *rwx)
  94. {
  95. *state = 0;
  96. return next_fd(state, rwx);
  97. }
  98. void select_result(int fd, int event)
  99. {
  100. struct fd *fdstruct = find234(fds, &fd, uxsel_fd_findcmp);
  101. noise_ultralight(NOISE_SOURCE_IOID, fd);
  102. /*
  103. * Apparently this can sometimes be NULL. Can't see how, but I
  104. * assume it means I need to ignore the event since it's on an
  105. * fd I've stopped being interested in. Sigh.
  106. */
  107. if (fdstruct)
  108. fdstruct->callback(fd, event);
  109. }