Welcome to mirror list, hosted at ThFree Co, Russian Federation.

UXSEL.C « UNIX - github.com/mRemoteNG/PuTTYNG.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 18d512ac9f18cb67298b0d62b59ce791a1e76ef7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
 * uxsel.c
 *
 * This module is a sort of all-purpose interchange for file
 * descriptors. At one end it talks to network.c and pty.c and
 * anything else which might have one or more fds that need
 * select() or poll()-type things doing to them during an extended
 * program run; at the other end it talks to window.c or plink.c or
 * anything else which might have its own means of actually doing
 * those select()-type things.
 */

#include <assert.h>

#include "putty.h"
#include "tree234.h"

struct fd {
    int fd;
    int rwx;                           /* 4=except 2=write 1=read */
    uxsel_callback_fn callback;
    uxsel_id *id;                      /* for uxsel_input_remove */
};

static tree234 *fds;

static int uxsel_fd_cmp(void *av, void *bv)
{
    struct fd *a = (struct fd *)av;
    struct fd *b = (struct fd *)bv;
    if (a->fd < b->fd)
        return -1;
    if (a->fd > b->fd)
        return +1;
    return 0;
}
static int uxsel_fd_findcmp(void *av, void *bv)
{
    int *a = (int *)av;
    struct fd *b = (struct fd *)bv;
    if (*a < b->fd)
        return -1;
    if (*a > b->fd)
        return +1;
    return 0;
}

void uxsel_init(void)
{
    fds = newtree234(uxsel_fd_cmp);
}

/*
 * Here is the interface to fd-supplying modules. They supply an
 * fd, a set of read/write/execute states, and a callback function
 * for when the fd satisfies one of those states. Repeated calls to
 * uxsel_set on the same fd are perfectly legal and serve to change
 * the rwx state (typically you only want to select an fd for
 * writing when you actually have pending data you want to write to
 * it!).
 */

void uxsel_set(int fd, int rwx, uxsel_callback_fn callback)
{
    struct fd *newfd;

    assert(fd >= 0);

    uxsel_del(fd);

    if (rwx) {
        newfd = snew(struct fd);
        newfd->fd = fd;
        newfd->rwx = rwx;
        newfd->callback = callback;
        newfd->id = uxsel_input_add(fd, rwx);
        add234(fds, newfd);
    }
}

void uxsel_del(int fd)
{
    struct fd *oldfd = find234(fds, &fd, uxsel_fd_findcmp);
    if (oldfd) {
        if (oldfd->id)
            uxsel_input_remove(oldfd->id);
        del234(fds, oldfd);
        sfree(oldfd);
    }
}

/*
 * And here is the interface to select-functionality-supplying
 * modules.
 */

int next_fd(int *state, int *rwx)
{
    struct fd *fd;
    fd = index234(fds, (*state)++);
    if (fd) {
        *rwx = fd->rwx;
        return fd->fd;
    } else
        return -1;
}

int first_fd(int *state, int *rwx)
{
    *state = 0;
    return next_fd(state, rwx);
}

void select_result(int fd, int event)
{
    struct fd *fdstruct = find234(fds, &fd, uxsel_fd_findcmp);

    noise_ultralight(NOISE_SOURCE_IOID, fd);

    /*
     * Apparently this can sometimes be NULL. Can't see how, but I
     * assume it means I need to ignore the event since it's on an
     * fd I've stopped being interested in. Sigh.
     */
    if (fdstruct)
        fdstruct->callback(fd, event);
}