diff options
Diffstat (limited to 'src/socket.c')
-rw-r--r-- | src/socket.c | 106 |
1 files changed, 96 insertions, 10 deletions
diff --git a/src/socket.c b/src/socket.c index e32701f..fdce7d1 100644 --- a/src/socket.c +++ b/src/socket.c @@ -395,17 +395,101 @@ pass_fd (const char *socket_name, int fd, unsigned maxtime) fd_set listenset; int fd_max; +struct sockinst +{ + struct sockinst *prev, *next; + int fd; + int (*handler) (int, void *); + void *data; +}; + +struct sockinst *si_head, *si_tail; + +static struct sockinst * +find_socket (int fd) +{ + struct sockinst *sp; + + for (sp = si_head; sp; sp = sp->next) + if (sp->fd == fd) + break; + return sp; +} + +struct sockinst * +find_socket_handler (int (*handler) (int, void *)) +{ + struct sockinst *sp; + + for (sp = si_head; sp; sp = sp->next) + if (sp->handler == handler) + break; + return sp; +} + +static int +calc_fd_max () +{ + struct sockinst *sp; + + fd_max = -1; + for (sp = si_head; sp; sp = sp->next) + if (sp->fd > fd_max) + fd_max = sp->fd; +} + +void * +register_socket (int fd, int (*handler) (int, void *), void *data) +{ + struct sockinst *sip = xmalloc (sizeof *sip); + sip->fd = fd; + sip->handler = handler; + sip->data = data; + sip->next = NULL; + sip->prev = si_tail; + if (si_tail) + si_tail->next = sip; + else + si_head = sip; + si_tail = sip; + FD_SET (fd, &listenset); + if (fd_max == -1) + calc_fd_max (); + else if (fd > fd_max) + fd_max = fd; + return sip; +} + +void +deregister_socket (int fd) +{ + struct sockinst *sp = find_socket (fd); + + if (!sp) + return; + if (sp->prev) + sp->prev->next = sp->next; + else + si_head = sp->next; + if (sp->next) + sp->next->prev = sp->prev; + else + si_tail = sp->prev; + free (sp); + FD_CLR (fd, &listenset); + fd_max = -1; +} + + int -register_socket (int socktype, int fd) +register_program_socket (int socktype, int fd, void *data) { if (socktype == SOCK_STREAM && listen (fd, 8) == -1) { logmsg (LOG_ERR, "listen: %s", strerror (errno)); return 1; } - FD_SET (fd, &listenset); - if (fd > fd_max) - fd_max = fd; + register_socket (fd, progman_accept, data); return 0; } @@ -430,18 +514,20 @@ enable_socket (int fd) void pies_pause () { + if (fd_max == -1) + calc_fd_max (); + while (1) { fd_set rdset = listenset; int rc = select (fd_max + 1, &rdset, NULL, NULL, NULL); if (rc > 0) { - int i; - for (i = 0; i <= fd_max; i++) - { - if (FD_ISSET (i, &rdset)) - progman_accept (i); - } + struct sockinst *sp; + + for (sp = si_head; sp; sp = sp->next) + if (FD_ISSET (sp->fd, &rdset)) + sp->handler (sp->fd, sp->data); break; } else if (rc < 0) |