aboutsummaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/ctl.c459
-rw-r--r--src/pies.c28
-rw-r--r--src/pies.h31
-rw-r--r--src/socket.c147
-rw-r--r--src/sysvinit.c2
6 files changed, 636 insertions, 32 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 17c0d10..04634c7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,6 +19,7 @@ sbin_PROGRAMS = pies
pies_SOURCES = \
acl.c\
addrfmt.c\
+ ctl.c\
depmap.c\
diag.c\
inetd.c\
diff --git a/src/ctl.c b/src/ctl.c
new file mode 100644
index 0000000..cfa0e13
--- /dev/null
+++ b/src/ctl.c
@@ -0,0 +1,459 @@
+/* This file is part of GNU Pies.
+ Copyright (C) 2007-2013 Sergey Poznyakoff
+
+ GNU Pies is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GNU Pies is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "pies.h"
+#include "prog.h"
+#include "xvasprintf.h"
+
+#define DEFAULT_CONTROL_URL "unix:///tmp/%s.ctl"
+
+struct control control;
+
+
+struct ctlbuf
+{
+ char *base;
+ size_t size;
+ size_t level;
+ size_t pos;
+};
+
+#define CTLBUFSIZE 16
+#define EOT '\04'
+
+static void
+ctlbuf_init (struct ctlbuf *buf)
+{
+ buf->base = NULL;
+ buf->size = 0;
+ buf->level = 0;
+ buf->pos = 0;
+}
+
+static void
+ctlbuf_free (struct ctlbuf *buf)
+{
+ free (buf->base);
+}
+
+static void
+ctlbuf_alloc (struct ctlbuf *buf, size_t s)
+{
+ while (buf->level + s >= buf->size)
+ {
+ if (buf->size == 0)
+ buf->size = CTLBUFSIZE;
+ buf->base = x2realloc (buf->base, &buf->size);
+ }
+}
+
+static void
+ctlbuf_write (struct ctlbuf *buf, char const *str, size_t n)
+{
+ ctlbuf_alloc (buf, n);
+ memcpy (buf->base + buf->level, str, n);
+ buf->level += n;
+}
+
+#define ctlbuf_rdsize(b) ((b)->level - (b)->pos)
+
+static ssize_t
+ctlbuf_read (struct ctlbuf *buf, char *str, size_t n)
+{
+ size_t size = ctlbuf_rdsize (buf);
+ if (size < n)
+ n = size;
+ memcpy (str, buf->base + buf->pos, n);
+ buf->pos += n;
+ return n;
+}
+
+static void
+ctlbuf_flush (struct ctlbuf *buf)
+{
+ buf->pos = buf->level = 0;
+}
+
+static void
+ctlbuf_chomp (struct ctlbuf *buf)
+{
+ if (buf->base)
+ {
+ while (buf->level > 0
+ && strchr(" \t\r\n", buf->base[buf->level-1]))
+ --buf->level;
+ }
+ ctlbuf_write (buf, "", 1);
+}
+
+#define CTL_END_STATE 0
+#define CTL_INITIAL_STATE 0x01
+#define CTL_AUTHENTICATED_STATE 0x02
+#define CTL_ALL_STATES (CTL_INITIAL_STATE|CTL_AUTHENTICATED_STATE)
+
+struct ctlio;
+
+static void cmd_quit (struct ctlio *, size_t, char **);
+static void cmd_noop (struct ctlio *, size_t, char **);
+static void cmd_help (struct ctlio *, size_t, char **);
+static void cmd_id (struct ctlio *, size_t, char **);
+
+struct ctlio_command
+{
+ char *verb;
+ char *descr;
+ int states;
+ int minargs;
+ size_t maxargs;
+ void (*handler) (struct ctlio *, size_t, char **);
+};
+
+static struct ctlio_command cmdtab[] = {
+ { "noop", "no operation",
+ CTL_ALL_STATES, 1, 1, cmd_noop },
+ { "id", "identify the instance",
+ CTL_AUTHENTICATED_STATE, 1, 1, cmd_id },
+ { "quit", "quit the session",
+ CTL_ALL_STATES, 1, 1, cmd_quit },
+ { "help", "display help",
+ CTL_ALL_STATES, 1, 1, cmd_help },
+ { NULL }
+};
+
+static struct ctlio_command *
+ctlio_command_find (char const *verb)
+{
+ struct ctlio_command *cp;
+
+ for (cp = cmdtab; cp->verb; cp++)
+ if (strcasecmp (cp->verb, verb) == 0)
+ return cp;
+ return NULL;
+}
+
+#define CRLF "\r\n"
+
+struct ctlio
+{
+ int state;
+ struct ctlbuf ibuf;
+ struct ctlbuf obuf;
+ struct wordsplit ws;
+ int wsflags;
+};
+
+static struct ctlio *
+ctlio_create (void)
+{
+ struct ctlio *io;
+
+ io = xmalloc (sizeof (*io));
+ io->state = CTL_INITIAL_STATE;
+ ctlbuf_init (&io->ibuf);
+ ctlbuf_init (&io->obuf);
+ io->wsflags = WRDSF_DEFFLAGS;
+ return io;
+}
+
+void
+ctlio_destroy (struct ctlio *io)
+{
+ ctlbuf_free (&io->ibuf);
+ ctlbuf_free (&io->obuf);
+ if (io->wsflags & WRDSF_REUSE)
+ wordsplit_free (&io->ws);
+ free (io);
+}
+
+static int
+ctlio_end (int fd, struct ctlio *io)
+{
+ deregister_socket (fd);
+ close (fd);
+ ctlio_destroy (io);
+ return 1;
+}
+
+static void
+ctlio_print (struct ctlio *io, const char *text)
+{
+ ctlbuf_write (&io->obuf, text, strlen (text));
+}
+
+static void
+ctlio_printf (struct ctlio *io, const char *fmt, ...)
+{
+ va_list ap;
+ char *str;
+
+ va_start (ap, fmt);
+ str = xvasprintf (fmt, ap);
+ va_end (ap);
+ ctlio_print (io, str);
+ free (str);
+}
+
+static void
+ctlio_eol (struct ctlio *io)
+{
+ ctlio_print (io, CRLF);
+}
+
+static void
+ctlio_eot (struct ctlio *io)
+{
+ ctlio_print (io, "." CRLF);
+}
+
+static void
+ctlio_reply (struct ctlio *io, const char *code, const char *fmt, ...)
+{
+ ctlio_print (io, code);
+ if (fmt)
+ {
+ va_list ap;
+ char *str;
+
+ va_start (ap, fmt);
+ str = xvasprintf (fmt, ap);
+ va_end (ap);
+ ctlio_print (io, " ");
+ ctlio_print (io, str);
+ free (str);
+ }
+ ctlio_eol (io);
+}
+
+static void
+ctlio_do_command (struct ctlio *io)
+{
+ int rc;
+ struct ctlio_command *cmd;
+
+ ctlbuf_chomp (&io->ibuf);
+ ctlbuf_flush (&io->obuf);
+ rc = wordsplit (io->ibuf.base, &io->ws, io->wsflags);
+ io->wsflags |= WRDSF_REUSE;
+ if (rc)
+ {
+ logmsg (LOG_ERR, _("can't parse input line: %s"),
+ wordsplit_strerror (&io->ws));
+ ctlio_reply (io, "550", "parse error");
+ return;
+ }
+
+ cmd = ctlio_command_find (io->ws.ws_wordv[0]);
+ if (!cmd)
+ {
+ ctlio_reply (io, "500", "unknown command");
+ return;
+ }
+ if (!(cmd->states & io->state))
+ {
+ ctlio_reply (io, "510", "command not valid in state");
+ return;
+ }
+ if (cmd->minargs && io->ws.ws_wordc < cmd->minargs)
+ {
+ ctlio_reply (io, "500", "too few arguments");
+ return;
+ }
+ if (cmd->maxargs && io->ws.ws_wordc > cmd->maxargs)
+ {
+ ctlio_reply (io, "500", "too many arguments");
+ return;
+ }
+ cmd->handler (io, io->ws.ws_wordc, io->ws.ws_wordv);
+}
+
+static void
+ctlio_initial_reply (struct ctlio *io)
+{
+ ctlio_printf (io, "220 %s", instance);
+ ctlio_printf (io, " <%s>", "foobarbaz");
+ //FIXME: auth mechanisms
+ ctlio_eol (io);
+}
+
+static void
+cmd_noop (struct ctlio *io, size_t argc, char **argv)
+{
+ ctlio_reply (io, "220", "%s attending", instance);
+}
+
+static void
+cmd_quit (struct ctlio *io, size_t argc, char **argv)
+{
+ ctlio_reply (io, "221", "bye");
+ io->state = CTL_END_STATE;
+}
+
+static void
+cmd_id (struct ctlio *io, size_t argc, char **argv)
+{
+ ctlio_reply (io, "110", "instance identification follows");
+ ctlio_printf (io, "Package:%s%s", PACKAGE_NAME, CRLF);
+ ctlio_printf (io, "Version:%s%s", PACKAGE_VERSION, CRLF);
+#if HAVE_DECL_PROGRAM_INVOCATION_NAME
+ ctlio_printf (io, "Binary:%s%s", program_invocation_name, CRLF);
+#endif
+ ctlio_printf (io, "Instance:%s%s", instance, CRLF);
+ ctlio_eot (io);
+}
+
+static void
+cmd_help (struct ctlio *io, size_t argc, char **argv)
+{
+ struct ctlio_command *cp;
+
+ ctlio_reply (io, "113", "help text follows");
+ for (cp = cmdtab; cp->verb; cp++)
+ {
+ ctlio_printf (io, "%-9s%s", cp->verb, cp->descr);
+ ctlio_eol (io);
+ }
+ ctlio_eot (io);
+}
+
+
+static int ctlrd (int fd, void *data);
+static int ctlwr (int fd, void *data);
+
+static int
+ctlrd (int fd, void *data)
+{
+ ssize_t n;
+ char c;
+ struct ctlio *io = data;
+
+ n = read (fd, &c, 1);
+ // logmsg (LOG_DEBUG, "%s called: %d,%d", __FUNCTION__, n,c);
+ if (n == 1)
+ {
+ switch (c) {
+ case '\n':
+ ctlio_do_command (io);
+ ctlbuf_flush (&io->ibuf);
+ update_socket (fd, PIES_EVT_RD, NULL);
+ update_socket (fd, PIES_EVT_WR, ctlwr);
+ break;
+
+ case EOT:
+ return ctlio_end (fd, io);
+
+ default:
+ ctlbuf_write (&io->ibuf, &c, 1);
+ }
+ }
+ else
+ {
+ if (n == -1)
+ logmsg (LOG_ERR, "error reading from control socket: %s",
+ strerror (errno));
+ return ctlio_end (fd, io);
+ }
+
+ return 0;
+}
+
+static int
+ctlwr (int fd, void *data)
+{
+ char c;
+ struct ctlio *io = data;
+ // logmsg (LOG_DEBUG, "%s called", __FUNCTION__);
+ if (ctlbuf_read (&io->obuf, &c, 1))
+ write (fd, &c, 1);
+ else if (io->state == CTL_END_STATE)
+ return ctlio_end (fd, io);
+ else
+ {
+ update_socket (fd, PIES_EVT_WR, NULL);
+ update_socket (fd, PIES_EVT_RD, ctlrd);
+ ctlbuf_flush (&io->obuf);
+ }
+ return 0;
+}
+
+static int
+ctl_accept (int socket, void *data)
+{
+ int fd;
+ union pies_sockaddr_storage addr;
+ socklen_t addrlen = sizeof addr;
+ struct ctlio *io;
+
+ fd = accept (socket, (struct sockaddr*) &addr, &addrlen);
+ if (fd == -1)
+ {
+ logmsg (LOG_ERR, _("accept failed: %s"), strerror (errno));
+ return 1;
+ }
+
+ if (debug_level >= 1)
+ {
+ char *s = sockaddr_to_astr ((struct sockaddr *)&addr, addrlen);
+ logmsg (LOG_DEBUG, _("%s wants %s"), s, "control socket");
+ free (s);
+ }
+
+ if (check_acl (control.acl, (struct sockaddr *)&addr, addrlen))
+ {
+ close (fd);
+ return 1;
+ }
+ /* FIXME: Check number of connections? */
+
+ io = ctlio_create ();
+ ctlio_initial_reply (io);
+ register_socket (fd, NULL, ctlwr, NULL, io);
+
+ return 0;
+}
+
+void
+ctl_open ()
+{
+ int fd;
+
+ if (!control.url)
+ {
+ char *str = xasprintf (DEFAULT_CONTROL_URL, instance);
+ if (pies_url_create (&control.url, str))
+ {
+ logmsg (LOG_CRIT, _("%s: cannot create URL: %s"),
+ str, strerror (errno));
+ }
+ free (str);
+ }
+
+ fd = create_socket (control.url, SOCK_STREAM, NULL, 0600);
+ if (fd == -1)
+ {
+ logmsg (LOG_CRIT, _("can't create control socket %s"), control.url->string);
+ exit (EX_UNAVAILABLE);
+ }
+
+ if (listen (fd, 8))
+ {
+ logmsg (LOG_CRIT, "can't listen on control socket %s: %s",
+ strerror (errno));
+ exit (EX_UNAVAILABLE);
+ }
+
+ register_socket (fd, ctl_accept, NULL, NULL, NULL);
+}
+
diff --git a/src/pies.c b/src/pies.c
index b92b7a3..60663a5 100644
--- a/src/pies.c
+++ b/src/pies.c
@@ -1533,6 +1533,27 @@ component_section_parser (enum grecs_callback_command cmd,
return 0;
}
+struct grecs_keyword control_keywords[] = {
+ {"socket",
+ N_("url: string"),
+ N_("Listen on the given url."),
+ grecs_type_string, GRECS_DFLT,
+ &control.url, 0, _cb_url},
+ {"acl",
+ N_("name: string"),
+ N_("Set ACL."),
+ grecs_type_section, GRECS_DFLT,
+ &control.acl, 0,
+ acl_section_parser, NULL, acl_keywords},
+ {"idle-timeout",
+ "n",
+ N_("Disconnect after <n> seconds of inaction (not implemented)."),
+ grecs_type_uint, GRECS_DFLT,
+ &control.idle_timeout, 0,
+ NULL,
+ },
+ { NULL }
+};
/* syslog */
static struct grecs_keyword syslog_kw[] = {
@@ -1587,6 +1608,12 @@ struct grecs_keyword pies_keywords[] = {
grecs_type_section, GRECS_DFLT,
NULL, 0,
component_section_parser, NULL, component_keywords},
+ {"control",
+ NULL,
+ N_("Define control socket"),
+ grecs_type_section, GRECS_DFLT,
+ NULL, 0,
+ NULL, NULL, control_keywords },
{"syslog",
NULL,
N_("Configure syslog logging"),
@@ -2447,6 +2474,7 @@ main (int argc, char **argv)
diag_setup (DIAG_TO_SYSLOG);
}
+ ctl_open ();
if (!init_process)
create_pidfile (pidfile);
diff --git a/src/pies.h b/src/pies.h
index b627b47..a4e1a1b 100644
--- a/src/pies.h
+++ b/src/pies.h
@@ -276,6 +276,7 @@ enum pies_action {
ACTION_KBREQUEST
};
+extern char *instance;
extern char *log_tag;
extern int log_facility;
extern unsigned long shutdown_timeout;
@@ -393,9 +394,25 @@ int pies_url_create (struct pies_url **purl, const char *str);
void pies_url_destroy (struct pies_url **purl);
const char * pies_url_get_arg (struct pies_url *url, const char *argname);
+
void pies_pause (void);
-void *register_socket (int fd, int (*handler) (int, void *), void *data);
+
+enum
+ {
+ PIES_EVT_RD,
+ PIES_EVT_WR,
+ PIES_EVT_EX
+ };
+
+typedef int (*socket_handler_t) (int, void *);
+
+void *register_socket (int fd,
+ socket_handler_t rd,
+ socket_handler_t wr,
+ socket_handler_t ex,
+ void *data);
void deregister_socket (int fd);
+void update_socket (int fd, int evt, socket_handler_t f);
int register_program_socket (int socktype, int fd, void *data);
int pass_fd (const char *socket, int fd, unsigned time_out);
@@ -537,3 +554,15 @@ struct sysvinit_request {
void sysvinit_acct (int what, const char *user, const char *id, pid_t pid,
const char *line);
+
+/* ctl.c */
+struct control
+{
+ struct pies_url *url;
+ pies_acl_t acl;
+ unsigned int idle_timeout;
+};
+
+extern struct control control;
+
+void ctl_open(void);
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)
@@ -391,19 +392,20 @@ pass_fd (const char *socket_name, int fd, unsigned maxtime)
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
+ {
+ 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]);
+}
+
+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)
- return;
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)
diff --git a/src/sysvinit.c b/src/sysvinit.c
index 1bf3a3b..07a29b5 100644
--- a/src/sysvinit.c
+++ b/src/sysvinit.c
@@ -532,7 +532,7 @@ create_fifo ()
strerror (errno));
return;
}
- register_socket (fd, sysvinit_fifo_handler, NULL);
+ register_socket (fd, sysvinit_fifo_handler, NULL, NULL, NULL);
}
static char *try_console[] = { NULL, "/dev/console", "/dev/tty0" };

Return to:

Send suggestions and report system problems to the System administrator.