source: filezilla/trunk/fuentes/src/putty/unix/uxsel.c @ 130

Last change on this file since 130 was 130, checked in by jrpelegrina, 3 years ago

First release to xenial

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