aboutsummaryrefslogtreecommitdiff
path: root/src/socket.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2015-10-29 13:09:26 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2015-10-30 10:12:05 +0200
commit9861a788306d5f742e633ff6a8a26a913f5e3fd1 (patch)
tree803ba61295468becef3df24f10fade8cacf44efc /src/socket.c
parent4683f7830491d1d50c5097466d9a066cb41286c7 (diff)
downloadpies-9861a788306d5f742e633ff6a8a26a913f5e3fd1.tar.gz
pies-9861a788306d5f742e633ff6a8a26a913f5e3fd1.tar.bz2
Introduce control connection.
* src/ctl.c: New file. * src/Makefile.am (pies_SOURCES): Add ctl.c * src/pies.c: New configuration statement "control" * src/pies.h (instance, ctl_url): New externs. (register_socket): Change signature. (update_socket,ctl_open): New protos. * src/socket.c (listenset): Remove. (fdset): New static. (sockinst)<handler>: Array of three pointers: handlers for read, write, and exception, correspondingly. (find_socket_handler): Remove. (register_socket): Take three function pointers as arguments. Update corresponding elements of fdset. (update_socket): New function. (pies_pause): Handle all three I/O operations. (deregister_socket) (register_program_socket) (disable_socket,enable_socket): Reflect the changes. * src/sysvinit.c (create_fifo): Update call to register_socket.
Diffstat (limited to 'src/socket.c')
-rw-r--r--src/socket.c149
1 files changed, 118 insertions, 31 deletions
diff --git a/src/socket.c b/src/socket.c
index 78f79f5..13ee5e0 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -15,6 +15,7 @@
along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
#include "pies.h"
+#include <assert.h>
static void
switch_eids (uid_t *puid, gid_t *pgid, mode_t *pumask)
@@ -390,20 +391,21 @@ pass_fd (const char *socket_name, int fd, unsigned maxtime)
close (sockfd);
return res;
}
-
-fd_set listenset;
+fd_set fdset[3];
int fd_max;
struct sockinst
{
struct sockinst *prev, *next;
int fd;
- int (*handler) (int, void *);
+ int dead;
+ socket_handler_t handler[3];
void *data;
};
struct sockinst *si_head, *si_tail;
+static int si_iterating;
static struct sockinst *
find_socket (int fd)
@@ -416,17 +418,6 @@ find_socket (int fd)
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 void
calc_fd_max ()
{
@@ -439,20 +430,38 @@ calc_fd_max ()
}
void *
-register_socket (int fd, int (*handler) (int, void *), void *data)
+register_socket (int fd,
+ socket_handler_t rd,
+ socket_handler_t wr,
+ socket_handler_t ex,
+ void *data)
{
struct sockinst *sip = xmalloc (sizeof *sip);
sip->fd = fd;
- sip->handler = handler;
+ sip->dead = 0;
+ sip->handler[PIES_EVT_RD] = rd;
+ sip->handler[PIES_EVT_WR] = wr;
+ sip->handler[PIES_EVT_EX] = ex;
sip->data = data;
sip->next = NULL;
sip->prev = si_tail;
if (si_tail)
si_tail->next = sip;
else
- si_head = sip;
+ {
+ FD_ZERO (&fdset[PIES_EVT_RD]);
+ FD_ZERO (&fdset[PIES_EVT_WR]);
+ FD_ZERO (&fdset[PIES_EVT_EX]);
+ si_head = sip;
+ }
+
si_tail = sip;
- FD_SET (fd, &listenset);
+ if (rd)
+ FD_SET (fd, &fdset[PIES_EVT_RD]);
+ if (wr)
+ FD_SET (fd, &fdset[PIES_EVT_WR]);
+ if (ex)
+ FD_SET (fd, &fdset[PIES_EVT_EX]);
if (fd_max == -1)
calc_fd_max ();
else if (fd > fd_max)
@@ -460,13 +469,30 @@ register_socket (int fd, int (*handler) (int, void *), void *data)
return sip;
}
+/* FIXME: Don't use with disable_socket/enable_socket */
void
-deregister_socket (int fd)
+update_socket (int fd, int evt, socket_handler_t f)
{
struct sockinst *sp = find_socket (fd);
+ assert (sp != NULL);
+ sp->handler[evt] = f;
+ if (f)
+ FD_SET (fd, &fdset[evt]);
+ else
+ FD_CLR (fd, &fdset[evt]);
+}
- if (!sp)
- return;
+static void
+delete_sockinst (struct sockinst *sp)
+{
+ if (sp->handler[PIES_EVT_RD])
+ FD_CLR (sp->fd, &fdset[PIES_EVT_RD]);
+ if (sp->handler[PIES_EVT_WR])
+ FD_CLR (sp->fd, &fdset[PIES_EVT_WR]);
+ if (sp->handler[PIES_EVT_EX])
+ FD_CLR (sp->fd, &fdset[PIES_EVT_EX]);
+ fd_max = -1;
+
if (sp->prev)
sp->prev->next = sp->next;
else
@@ -475,9 +501,20 @@ deregister_socket (int fd)
sp->next->prev = sp->prev;
else
si_tail = sp->prev;
+
free (sp);
- FD_CLR (fd, &listenset);
- fd_max = -1;
+}
+
+void
+deregister_socket (int fd)
+{
+ struct sockinst *sp = find_socket (fd);
+ if (!sp)
+ return;
+ if (si_iterating)
+ sp->dead = 1;
+ else
+ delete_sockinst (sp);
}
@@ -489,7 +526,7 @@ register_program_socket (int socktype, int fd, void *data)
logmsg (LOG_ERR, "listen: %s", strerror (errno));
return 1;
}
- register_socket (fd, progman_accept, data);
+ register_socket (fd, progman_accept, NULL, NULL, data);
return 0;
}
@@ -499,16 +536,26 @@ disable_socket (int fd)
if (fd < 0)
return;
debug (2, (_("disabling fd %d"), fd));
- FD_CLR (fd, &listenset);
+ FD_CLR (fd, &fdset[PIES_EVT_RD]);
+ FD_CLR (fd, &fdset[PIES_EVT_WR]);
+ FD_CLR (fd, &fdset[PIES_EVT_EX]);
}
void
enable_socket (int fd)
{
+ struct sockinst *sp;
if (fd < 0)
return;
debug (2, (_("enabling fd %d"), fd));
- FD_SET (fd, &listenset);
+ sp = find_socket (fd);
+ assert (sp != NULL);
+ if (sp->handler[PIES_EVT_RD])
+ FD_SET (fd, &fdset[PIES_EVT_RD]);
+ if (sp->handler[PIES_EVT_WR])
+ FD_SET (fd, &fdset[PIES_EVT_WR]);
+ if (sp->handler[PIES_EVT_EX])
+ FD_SET (fd, &fdset[PIES_EVT_EX]);
}
void
@@ -519,15 +566,55 @@ pies_pause ()
while (1)
{
- fd_set rdset = listenset;
- int rc = select (fd_max + 1, &rdset, NULL, NULL, NULL);
+ fd_set rdset = fdset[PIES_EVT_RD];
+ fd_set wrset = fdset[PIES_EVT_WR];
+ fd_set exset = fdset[PIES_EVT_EX];
+
+ int rc = select (fd_max + 1, &rdset, &wrset, &exset, NULL);
if (rc > 0)
{
struct sockinst *sp;
-
+ int delete = 0;
+ ++si_iterating;
for (sp = si_head; sp; sp = sp->next)
- if (FD_ISSET (sp->fd, &rdset))
- sp->handler (sp->fd, sp->data);
+ {
+ if (sp->dead)
+ {
+ delete = 1;
+ continue;
+ }
+ if (sp->handler[PIES_EVT_RD] && FD_ISSET (sp->fd, &rdset))
+ sp->handler[PIES_EVT_RD] (sp->fd, sp->data);
+
+ if (sp->dead)
+ {
+ delete = 1;
+ continue;
+ }
+ if (sp->handler[PIES_EVT_WR] && FD_ISSET (sp->fd, &wrset))
+ sp->handler[PIES_EVT_WR] (sp->fd, sp->data);
+
+ if (sp->dead)
+ {
+ delete = 1;
+ continue;
+ }
+ if (sp->handler[PIES_EVT_EX] && FD_ISSET (sp->fd, &exset))
+ sp->handler[PIES_EVT_EX] (sp->fd, sp->data);
+ }
+ --si_iterating;
+
+ if (delete)
+ {
+ for (sp = si_head; sp; )
+ {
+ struct sockinst *next = sp->next;
+ if (sp->dead)
+ delete_sockinst (sp);
+ sp = next;
+ }
+ calc_fd_max ();
+ }
break;
}
else if (rc < 0)

Return to:

Send suggestions and report system problems to the System administrator.