summaryrefslogtreecommitdiff
path: root/src/server/s6-rcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/s6-rcd.c')
-rw-r--r--src/server/s6-rcd.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/server/s6-rcd.c b/src/server/s6-rcd.c
new file mode 100644
index 0000000..0fcfb77
--- /dev/null
+++ b/src/server/s6-rcd.c
@@ -0,0 +1,139 @@
+/* ISC license. */
+
+#include <fcntl.h>
+
+#include <skalibs/types.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/subgetopt.h>
+#include <skalibs/tai.h>
+#include <skalibs/djbunix.h>
+
+#include "s6-rcd.h"
+
+#define USAGE "s6-rcd [ -v verbosity ] [ -1 ] [ -t timeout ] [ -T lameducktimeout ] [ -i rulesdir | -x rulesfile ] [ -l livedir ]"
+#define dieusage() strerr_dieusage(100, USAGE) ;
+
+unsigned int verbosity = 1 ;
+globalflags_t flags =
+{
+ .lameduck = 0 ;
+} ;
+
+tain_t lameduckdeadline = TAIN_INFINITE_RELATIVE ;
+
+int main (int argc, char const *const *argv)
+{
+ int spfd, sock ;
+ PROG = "s6-rcd" ;
+
+ {
+ char const *rules = 0 ;
+ unsigned int rulestype = 0 ;
+ int flag1 = 0 ;
+ unsigned int t = 0, T = 0 ;
+ subgetopt_t l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "v:1c:n:i:x:t:T:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'v' : if (!uint0_scan(l.arg, &verbosity)) dieusage() ; break ;
+ case '1' : flag1 = 1 ; break ;
+ case 'i' : rules = l.arg ; rulestype = 1 ; break ;
+ case 'x' : rules = l.arg ; rulestype = 2 ; break ;
+ case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ;
+ case 'T' : if (!uint0_scan(l.arg, &T)) dieusage() ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ if (t) tain_from_millisecs(&client_answer_tto, t) ;
+ if (T) tain_from_millisecs(&lameduckdeadline, T) ;
+ if (!rulestype) strerr_dief1x(100, "no access rights specified!") ;
+ if (flag1)
+ {
+ if (fcntl(1, F_GETFD) < 0)
+ strerr_dief1sys(100, "called with option -1 but stdout said") ;
+ }
+ else close(1) ;
+
+ spfd = signals_init() ;
+ clientrules_init(rulestype, rules) ;
+ sock = livedir_init() ;
+ if (!tain_now_set_stopwatch_g())
+ strerr_diefu1sys(111, "initialize clock") ;
+ if (flag1)
+ {
+ fd_write(1, "\n", 1) ;
+ fd_close(1) ;
+ }
+ }
+
+ for (;;)
+ {
+ iopause_fd x[2 + client_connections + client_monitors] ;
+ tain_t deadline ;
+ uint32_t j = 2 ;
+ int r = 1 ;
+
+ {
+ s6rc_event_t ev ;
+ while (ev_pop(&ev)) { ev_handle(&ev) ; ep_run(&ev) ; }
+ }
+
+ tain_add_g(&deadline, &tain_infinite_relative) ;
+ if (flags.lameduck) deadline = lameduckdeadline ;
+
+ x[0].fd = spfd ;
+ x[0].events = IOPAUSE_READ ;
+ x[1].fd = sock ;
+ x[1].events = !flags.lameduck ? IOPAUSE_READ : 0 ;
+
+ for (client_t *c = client_head ; c ; c = c->next)
+ if (client_prepare_iopause(c, &deadline, x, &j)) r = 0 ;
+
+ if (r) /* clean buffers */
+ {
+ if (flags.lameduck) break ;
+ if (flags.dbupdate && db_update())
+ {
+ flags.dbupdate = 0 ;
+ continue ;
+ }
+ }
+
+ r = iopause_g(x, j, &deadline) ;
+ if (r < 0) strerr_diefu1sys(111, "iopause") ;
+
+ if (!r)
+ {
+ if (flags.lameduck && !tain_future(&lameduckdeadline)) break ;
+ for (client_t *c = client_head ; c ; c = c ? c->next : client_head)
+ if (!tain_future(c->deadline)) client_yoink(&c) ;
+ continue ;
+ }
+
+ if (x[0].revents & IOPAUSE_READ) signals_handle() ;
+
+ for (client_t *c = client_head ; c ; c = c ? c->next : client_head)
+ if (!client_flush(c, x)) client_yoink(&c) ;
+
+ for (client_t *c = client_head ; c ; c = c ? c->next : client_head)
+ if (!client_read(c, x)) client_yoink(&c) ;
+
+ if (x[1].revents & IOPAUSE_READ)
+ {
+ uint8_t perms = 0 ;
+ int dummy ;
+ int fd = ipc_accept_nb(x[1].fd, 0, 0, &dummy) ;
+ if (fd < 0)
+ if (!error_isagain(errno)) strerr_diefu1sys(111, "accept connection") ;
+ else continue ;
+ else if (!clientrules_check(fd, &perms)) fd_close(fd) ;
+ else client_add(fd, perms) ;
+ }
+ }
+
+ return 0 ;
+}