s6

Mirror/fork of https://skarnet.org/software/s6/
git clone https://ccx.te2000.cz/git/s6
Log | Files | Refs | README | LICENSE

commit 49cb17940e403431566dc7b5a312624f14eb25d0
parent e62d3ae45e9bf3b97551b8879bf6c441ff961ec1
Author: Laurent Bercot <ska-skaware@skarnet.org>
Date:   Fri, 23 Jan 2015 23:47:14 +0000

 Added fdholder, beta. Documentation will come next.

Diffstat:
Mpackage/modes | 16+++++++++++++++-
Mpackage/targets.mak | 16+++++++++++++++-
Asrc/fdholder/deps-exe/s6-fdholder-daemon | 1+
Asrc/fdholder/deps-exe/s6-fdholder-getdump | 1+
Asrc/fdholder/deps-exe/s6-fdholder-getdumpc | 4++++
Asrc/fdholder/deps-exe/s6-fdholder-list | 1+
Asrc/fdholder/deps-exe/s6-fdholder-listc | 4++++
Asrc/fdholder/deps-exe/s6-fdholder-retrieve | 1+
Asrc/fdholder/deps-exe/s6-fdholder-retrievec | 4++++
Asrc/fdholder/deps-exe/s6-fdholder-setdump | 1+
Asrc/fdholder/deps-exe/s6-fdholder-setdumpc | 4++++
Asrc/fdholder/deps-exe/s6-fdholder-store | 1+
Asrc/fdholder/deps-exe/s6-fdholder-storec | 4++++
Asrc/fdholder/deps-exe/s6-fdholder-transferdump | 1+
Asrc/fdholder/deps-exe/s6-fdholder-transferdumpc | 4++++
Asrc/fdholder/deps-exe/s6-fdholderd | 4++++
Asrc/fdholder/s6-fdholder-daemon.c | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/fdholder/s6-fdholder-getdump.c | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/fdholder/s6-fdholder-getdumpc.c | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/fdholder/s6-fdholder-list.c | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/fdholder/s6-fdholder-listc.c | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/fdholder/s6-fdholder-retrieve.c | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/fdholder/s6-fdholder-retrievec.c | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/fdholder/s6-fdholder-setdump.c | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/fdholder/s6-fdholder-setdumpc.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/fdholder/s6-fdholder-store.c | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/fdholder/s6-fdholder-storec.c | 46++++++++++++++++++++++++++++++++++++++++++++++
Asrc/fdholder/s6-fdholder-transferdump.c | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/fdholder/s6-fdholder-transferdumpc.c | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/fdholder/s6-fdholderd.c | 798+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/libs6/s6_fdholder_setdump.c | 6+++---
31 files changed, 1762 insertions(+), 5 deletions(-)

diff --git a/package/modes b/package/modes @@ -1,3 +1,4 @@ +ucspilogd 0755 s6-ftrigrd 0755 s6-ftrig-listen1 0755 s6-ftrig-listen 0755 @@ -40,4 +41,17 @@ s6-ipcserverd 0755 s6-sudo 0755 s6-sudoc 0755 s6-sudod 0755 -ucspilogd 0755 +s6-fdholder-daemon 0755 +s6-fdholderd 0755 +s6-fdholder-store 0755 +s6-fdholder-storec 0755 +s6-fdholder-retrieve 0755 +s6-fdholder-retrievec 0755 +s6-fdholder-list 0755 +s6-fdholder-listc 0755 +s6-fdholder-getdump 0755 +s6-fdholder-getdumpc 0755 +s6-fdholder-setdump 0755 +s6-fdholder-setdumpc 0755 +s6-fdholder-transferdump 0755 +s6-fdholder-transferdumpc 0755 diff --git a/package/targets.mak b/package/targets.mak @@ -1,4 +1,5 @@ BIN_TARGETS := \ +ucspilogd \ s6-ftrigrd \ s6-ftrig-listen1 \ s6-ftrig-listen \ @@ -38,7 +39,20 @@ s6-ipcserverd \ s6-sudo \ s6-sudoc \ s6-sudod \ -ucspilogd +s6-fdholder-daemon \ +s6-fdholderd \ +s6-fdholder-store \ +s6-fdholder-storec \ +s6-fdholder-retrieve \ +s6-fdholder-retrievec \ +s6-fdholder-list \ +s6-fdholder-listc \ +s6-fdholder-getdump \ +s6-fdholder-getdumpc \ +s6-fdholder-setdump \ +s6-fdholder-setdumpc \ +s6-fdholder-transferdump \ +s6-fdholder-transferdumpc SBIN_TARGETS := \ s6-applyuidgid \ diff --git a/src/fdholder/deps-exe/s6-fdholder-daemon b/src/fdholder/deps-exe/s6-fdholder-daemon @@ -0,0 +1 @@ +-lskarnet diff --git a/src/fdholder/deps-exe/s6-fdholder-getdump b/src/fdholder/deps-exe/s6-fdholder-getdump @@ -0,0 +1 @@ +-lskarnet diff --git a/src/fdholder/deps-exe/s6-fdholder-getdumpc b/src/fdholder/deps-exe/s6-fdholder-getdumpc @@ -0,0 +1,4 @@ +${LIBS6} +-lskarnet +${SOCKET_LIB} +${TAINNOW_LIB} diff --git a/src/fdholder/deps-exe/s6-fdholder-list b/src/fdholder/deps-exe/s6-fdholder-list @@ -0,0 +1 @@ +-lskarnet diff --git a/src/fdholder/deps-exe/s6-fdholder-listc b/src/fdholder/deps-exe/s6-fdholder-listc @@ -0,0 +1,4 @@ +${LIBS6} +-lskarnet +${SOCKET_LIB} +${TAINNOW_LIB} diff --git a/src/fdholder/deps-exe/s6-fdholder-retrieve b/src/fdholder/deps-exe/s6-fdholder-retrieve @@ -0,0 +1 @@ +-lskarnet diff --git a/src/fdholder/deps-exe/s6-fdholder-retrievec b/src/fdholder/deps-exe/s6-fdholder-retrievec @@ -0,0 +1,4 @@ +${LIBS6} +-lskarnet +${SOCKET_LIB} +${TAINNOW_LIB} diff --git a/src/fdholder/deps-exe/s6-fdholder-setdump b/src/fdholder/deps-exe/s6-fdholder-setdump @@ -0,0 +1 @@ +-lskarnet diff --git a/src/fdholder/deps-exe/s6-fdholder-setdumpc b/src/fdholder/deps-exe/s6-fdholder-setdumpc @@ -0,0 +1,4 @@ +${LIBS6} +-lskarnet +${SOCKET_LIB} +${TAINNOW_LIB} diff --git a/src/fdholder/deps-exe/s6-fdholder-store b/src/fdholder/deps-exe/s6-fdholder-store @@ -0,0 +1 @@ +-lskarnet diff --git a/src/fdholder/deps-exe/s6-fdholder-storec b/src/fdholder/deps-exe/s6-fdholder-storec @@ -0,0 +1,4 @@ +${LIBS6} +-lskarnet +${SOCKET_LIB} +${TAINNOW_LIB} diff --git a/src/fdholder/deps-exe/s6-fdholder-transferdump b/src/fdholder/deps-exe/s6-fdholder-transferdump @@ -0,0 +1 @@ +-lskarnet diff --git a/src/fdholder/deps-exe/s6-fdholder-transferdumpc b/src/fdholder/deps-exe/s6-fdholder-transferdumpc @@ -0,0 +1,4 @@ +${LIBS6} +-lskarnet +${SOCKET_LIB} +${TAINNOW_LIB} diff --git a/src/fdholder/deps-exe/s6-fdholderd b/src/fdholder/deps-exe/s6-fdholderd @@ -0,0 +1,4 @@ +${LIBS6} +-lskarnet +${SOCKET_LIB} +${TAINNOW_LIB} diff --git a/src/fdholder/s6-fdholder-daemon.c b/src/fdholder/s6-fdholder-daemon.c @@ -0,0 +1,156 @@ +/* ISC license. */ + +#include <sys/types.h> +#include <limits.h> +#include <skalibs/uint.h> +#include <skalibs/gidstuff.h> +#include <skalibs/sgetopt.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> +#include <s6/config.h> + +#define USAGE "s6-fdholder-daemon [ -v verbosity ] [ -d | -D ] [ -1 ] [ -c maxconn ] [ -n maxfds ] [ -b backlog ] [ -G gid,gid,... ] [ -g gid ] [ -u uid ] [ -U ] [ -t timeout ] [ -T lameducktimeout ] [ -i rulesdir | -x rulesfile ] path" +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv, char const *const *envp) +{ + unsigned int verbosity = 1 ; + int flag1 = 0 ; + int flagU = 0 ; + int flagreuse = 1 ; + unsigned int uid = 0, gid = 0 ; + gid_t gids[NGROUPS_MAX] ; + unsigned int gidn = (unsigned int)-1 ; + unsigned int maxconn = 0 ; + unsigned int maxfds = 0 ; + unsigned int backlog = (unsigned int)-1 ; + unsigned int timeout = 0 ; + unsigned int ltimeout = 0 ; + char const *rulesdir = 0 ; + char const *rulesfile = 0 ; + PROG = "s6-fdholder-daemon" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "Dd1Uv:c:n:b:u:g:G:t:T:i:x:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'D' : flagreuse = 0 ; break ; + case 'd' : flagreuse = 1 ; break ; + case '1' : flag1 = 1 ; break ; + case 'v' : if (!uint0_scan(l.arg, &verbosity)) dieusage() ; break ; + case 'c' : if (!uint0_scan(l.arg, &maxconn)) dieusage() ; if (!maxconn) maxconn = 1 ; break ; + case 'n' : if (!uint0_scan(l.arg, &maxfds)) dieusage() ; if (!maxfds) maxfds = 1 ; break ; + case 'b' : if (!uint0_scan(l.arg, &backlog)) dieusage() ; break ; + case 'u' : if (!uint0_scan(l.arg, &uid)) dieusage() ; break ; + case 'g' : if (!uint0_scan(l.arg, &gid)) dieusage() ; break ; + case 'G' : if (!gid_scanlist(gids, NGROUPS_MAX, l.arg, &gidn) && *l.arg) dieusage() ; break ; + case 'U' : flagU = 1 ; uid = 0 ; gid = 0 ; gidn = (unsigned int)-1 ; break ; + case 't' : if (!uint0_scan(l.arg, &timeout)) dieusage() ; break ; + case 'T' : if (!uint0_scan(l.arg, &ltimeout)) dieusage() ; break ; + case 'i' : rulesdir = l.arg ; rulesfile = 0 ; break ; + case 'x' : rulesfile = l.arg ; rulesdir = 0 ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + if (!argc) dieusage() ; + } + if (!rulesdir && !rulesfile) strerr_dief1x(100, "no access rights specified!") ; + + { + unsigned int m = 0, pos = 0 ; + char const *newargv[30] ; + char fmt[UINT_FMT * 8 + GID_FMT * NGROUPS_MAX] ; + newargv[m++] = S6_BINPREFIX "s6-ipcserver-socketbinder" ; + if (!flagreuse) newargv[m++] = "-D" ; + if (backlog != (unsigned int)-1) + { + newargv[m++] = "-b" ; + newargv[m++] = fmt + pos ; + pos += uint_fmt(fmt + pos, backlog) ; + fmt[pos++] = 0 ; + } + newargv[m++] = "--" ; + newargv[m++] = *argv++ ; + if (flagU || uid || gid || gidn != (unsigned int)-1) + { + newargv[m++] = S6_BINPREFIX "s6-applyuidgid" ; + if (flagU) newargv[m++] = "-Uz" ; + if (uid) + { + newargv[m++] = "-u" ; + newargv[m++] = fmt + pos ; + pos += uint_fmt(fmt + pos, uid) ; + fmt[pos++] = 0 ; + } + if (gid) + { + newargv[m++] = "-g" ; + newargv[m++] = fmt + pos ; + pos += uint_fmt(fmt + pos, gid) ; + fmt[pos++] = 0 ; + } + if (gidn != (unsigned int)-1) + { + newargv[m++] = "-G" ; + newargv[m++] = fmt + pos ; + pos += gid_fmtlist(fmt + pos, gids, gidn) ; + fmt[pos++] = 0 ; + } + newargv[m++] = "--" ; + } + newargv[m++] = S6_BINPREFIX "s6-fdholderd" ; + if (verbosity != 1) + { + newargv[m++] = "-v" ; + newargv[m++] = fmt + pos ; + pos += uint_fmt(fmt + pos, verbosity) ; + fmt[pos++] = 0 ; + } + if (flag1) newargv[m++] = "-1" ; + if (maxconn) + { + newargv[m++] = "-c" ; + newargv[m++] = fmt + pos ; + pos += uint_fmt(fmt + pos, maxconn) ; + fmt[pos++] = 0 ; + } + if (maxfds) + { + newargv[m++] = "-n" ; + newargv[m++] = fmt + pos ; + pos += uint_fmt(fmt + pos, maxfds) ; + fmt[pos++] = 0 ; + } + if (timeout) + { + newargv[m++] = "-t" ; + newargv[m++] = fmt + pos ; + pos += uint_fmt(fmt + pos, timeout) ; + fmt[pos++] = 0 ; + } + if (ltimeout) + { + newargv[m++] = "-T" ; + newargv[m++] = fmt + pos ; + pos += uint_fmt(fmt + pos, timeout) ; + fmt[pos++] = 0 ; + } + if (rulesdir) + { + newargv[m++] = "-i" ; + newargv[m++] = rulesdir ; + } + else if (rulesfile) + { + newargv[m++] = "-x" ; + newargv[m++] = rulesfile ; + } + newargv[m++] = 0 ; + pathexec_run(newargv[0], newargv, envp) ; + strerr_dieexec(111, newargv[0]) ; + } +} diff --git a/src/fdholder/s6-fdholder-getdump.c b/src/fdholder/s6-fdholder-getdump.c @@ -0,0 +1,58 @@ +/* ISC license. */ + +#include <skalibs/uint.h> +#include <skalibs/sgetopt.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> +#include <execline/config.h> +#include <s6/config.h> + +#define USAGE "s6-fdholder-getdump [ -t timeout ] socket prog..." +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv, char const *const *envp) +{ + unsigned int timeout = 0 ; + PROG = "s6-fdholder-retrieve" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "t:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 't' : if (!uint0_scan(l.arg, &timeout)) dieusage() ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + if (argc < 2) dieusage() ; + } + + { + char const *newargv[12 + argc] ; + unsigned int m = 0 ; + char fmtt[UINT_FMT] ; + newargv[m++] = S6_BINPREFIX "s6-ipcclient" ; + newargv[m++] = "-l0" ; + newargv[m++] = "--" ; + newargv[m++] = *argv++ ; + newargv[m++] = S6_BINPREFIX "s6-fdholder-getdumpc" ; + if (timeout) + { + fmtt[uint_fmt(fmtt, timeout)] = 0 ; + newargv[m++] = "-t" ; + newargv[m++] = fmtt ; + } + newargv[m++] = "--" ; + newargv[m++] = EXECLINE_EXTBINPREFIX "fdclose" ; + newargv[m++] = "6" ; + newargv[m++] = EXECLINE_EXTBINPREFIX "fdclose" ; + newargv[m++] = "7" ; + while (*argv) newargv[m++] = *argv++ ; + newargv[m++] = 0 ; + pathexec_run(newargv[0], newargv, envp) ; + strerr_dieexec(111, newargv[0]) ; + } +} diff --git a/src/fdholder/s6-fdholder-getdumpc.c b/src/fdholder/s6-fdholder-getdumpc.c @@ -0,0 +1,82 @@ +/* ISC license. */ + +#include <skalibs/uint.h> +#include <skalibs/bytestr.h> +#include <skalibs/strerr2.h> +#include <skalibs/sgetopt.h> +#include <skalibs/tai.h> +#include <skalibs/djbunix.h> +#include <skalibs/genalloc.h> +#include <s6/s6-fdholder.h> + +#define USAGE "s6-fdholder-getdumpc [ -t timeout ] prog..." +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv, char const *const *envp) +{ + s6_fdholder_t a = S6_FDHOLDER_ZERO ; + genalloc dump = GENALLOC_ZERO ; + tain_t deadline, halfinfinite ; + PROG = "s6-fdholder-getdumpc" ; + { + unsigned int t = 0 ; + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "t:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + if (t) tain_from_millisecs(&deadline, t) ; + else deadline = tain_infinite_relative ; + } + if (!argc) dieusage() ; + + s6_fdholder_init(&a, 6) ; + tain_now_g() ; + tain_add_g(&deadline, &deadline) ; + if (!s6_fdholder_getdump_g(&a, &dump, &deadline)) + strerr_diefu1sys(111, "get dump") ; + s6_fdholder_free(&a) ; + tain_half(&halfinfinite, &tain_infinite_relative) ; + tain_add_g(&halfinfinite, &halfinfinite) ; + { + unsigned int n = genalloc_len(s6_fdholder_fd_t, &dump) ; + unsigned int pos = 0, i = 0 ; + char modifs[7 + UINT_FMT + (25 + TIMESTAMP + 4 * UINT_FMT) * n] ; + byte_copy(modifs + pos, 7, "S6_FD#=") ; pos += 7 ; + pos += uint_fmt(modifs + pos, n) ; + modifs[pos++] = 0 ; + for (; i < n ; i++) + { + s6_fdholder_fd_t *p = genalloc_s(s6_fdholder_fd_t, &dump) + i ; + unsigned int len = str_len(p->id) + 1 ; + if (uncoe(p->fd) < 0) strerr_diefu1sys(111, "uncoe") ; + byte_copy(modifs + pos, 6, "S6_FD_") ; pos += 6 ; + pos += uint_fmt(modifs + pos, i) ; + modifs[pos++] = '=' ; + pos += uint_fmt(modifs + pos, p->fd) ; + modifs[pos++] = 0 ; + byte_copy(modifs + pos, 8, "S6_FDID_") ; pos += 8 ; + pos += uint_fmt(modifs + pos, i) ; + modifs[pos++] = '=' ; + byte_copy(modifs + pos, len, p->id) ; + pos += len ; + if (tain_less(&p->limit, &halfinfinite)) + { + byte_copy(modifs + pos, 11, "S6_FDLIMIT_") ; pos += 11 ; + pos += uint_fmt(modifs + pos, i) ; + modifs[pos++] = '=' ; + pos += timestamp_fmt(modifs + pos, &p->limit) ; + modifs[pos++] = 0 ; + } + } + pathexec_r(argv, envp, env_len(envp), modifs, pos) ; + } + strerr_dieexec(111, argv[0]) ; +} diff --git a/src/fdholder/s6-fdholder-list.c b/src/fdholder/s6-fdholder-list.c @@ -0,0 +1,52 @@ +/* ISC license. */ + +#include <skalibs/uint.h> +#include <skalibs/sgetopt.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> +#include <s6/config.h> + +#define USAGE "s6-fdholder-list [ -t timeout ] [ -T ] socket" +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv, char const *const *envp) +{ + char const *newargv[9] ; + unsigned int m = 0 ; + unsigned int timeout = 0 ; + int printexpire = 0 ; + char fmtt[UINT_FMT] ; + PROG = "s6-fdholder-list" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "d:t:T:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'T' : printexpire = 1 ; break ; + case 't' : if (!uint0_scan(l.arg, &timeout)) dieusage() ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) dieusage() ; + + newargv[m++] = S6_BINPREFIX "s6-ipcclient" ; + newargv[m++] = "-l0" ; + newargv[m++] = "--" ; + newargv[m++] = argv[0] ; + newargv[m++] = S6_BINPREFIX "s6-fdholder-listc" ; + if (printexpire) newargv[m++] = "-T" ; + if (timeout) + { + fmtt[uint_fmt(fmtt, timeout)] = 0 ; + newargv[m++] = "-t" ; + newargv[m++] = fmtt ; + } + newargv[m++] = 0 ; + pathexec_run(newargv[0], newargv, envp) ; + strerr_dieexec(111, newargv[0]) ; +} diff --git a/src/fdholder/s6-fdholder-listc.c b/src/fdholder/s6-fdholder-listc.c @@ -0,0 +1,61 @@ +/* ISC license. */ + +#include <skalibs/uint.h> +#include <skalibs/bytestr.h> +#include <skalibs/buffer.h> +#include <skalibs/strerr2.h> +#include <skalibs/sgetopt.h> +#include <skalibs/tai.h> +#include <skalibs/stralloc.h> +#include <skalibs/skamisc.h> +#include <s6/s6-fdholder.h> + +#define USAGE "s6-fdholder-listc [ -t timeout ]" +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv, char const *const *envp) +{ + s6_fdholder_t a = S6_FDHOLDER_ZERO ; + stralloc sa = STRALLOC_ZERO, sb = STRALLOC_ZERO ; + unsigned int pos = 0 ; + int n ; + tain_t deadline ; + PROG = "s6-fdholder-listc" ; + { + unsigned int t = 0 ; + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "t:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + if (t) tain_from_millisecs(&deadline, t) ; + else deadline = tain_infinite_relative ; + } + + s6_fdholder_init(&a, 6) ; + tain_now_g() ; + tain_add_g(&deadline, &deadline) ; + n = s6_fdholder_list_g(&a, &sa, &deadline) ; + if (n < 0) strerr_diefu1sys(111, "get fd list") ; + while (n--) + { + register unsigned int len = str_len(sa.s + pos) ; + sb.len = 0 ; + if (!string_quote_nodelim_mustquote(&sb, sa.s + pos, len, 0, 0)) + strerr_diefu1sys(111, "quote string") ; + if (buffer_put(buffer_1, sb.s, sb.len) < sb.len || buffer_put(buffer_1, "\n", 1) < 1) + strerr_diefu1sys(111, "buffer_put") ; + pos += len+1 ; + } + stralloc_free(&sb) ; + stralloc_free(&sa) ; + if (!buffer_flush(buffer_1)) strerr_diefu1sys(111, "write to stdout") ; + return 0 ; +} diff --git a/src/fdholder/s6-fdholder-retrieve.c b/src/fdholder/s6-fdholder-retrieve.c @@ -0,0 +1,62 @@ +/* ISC license. */ + +#include <skalibs/uint.h> +#include <skalibs/sgetopt.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> +#include <execline/config.h> +#include <s6/config.h> + +#define USAGE "s6-fdholder-retrieve [ -D ] [ -t timeout ] socket id prog..." +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv, char const *const *envp) +{ + unsigned int timeout = 0 ; + int dodelete = 0 ; + PROG = "s6-fdholder-retrieve" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "Dt:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'D' : dodelete = 1 ; break ; + case 't' : if (!uint0_scan(l.arg, &timeout)) dieusage() ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + if (argc < 3) dieusage() ; + } + + { + char const *newargv[13 + argc] ; + unsigned int m = 0 ; + char fmtt[UINT_FMT] ; + newargv[m++] = S6_BINPREFIX "s6-ipcclient" ; + newargv[m++] = "-l0" ; + newargv[m++] = "--" ; + newargv[m++] = *argv++ ; + newargv[m++] = S6_BINPREFIX "s6-fdholder-retrievec" ; + if (dodelete) newargv[m++] = "-D" ; + if (timeout) + { + fmtt[uint_fmt(fmtt, timeout)] = 0 ; + newargv[m++] = "-t" ; + newargv[m++] = fmtt ; + } + newargv[m++] = "--" ; + newargv[m++] = *argv++ ; + newargv[m++] = EXECLINE_EXTBINPREFIX "fdclose" ; + newargv[m++] = "6" ; + newargv[m++] = EXECLINE_EXTBINPREFIX "fdclose" ; + newargv[m++] = "7" ; + while (*argv) newargv[m++] = *argv++ ; + newargv[m++] = 0 ; + pathexec_run(newargv[0], newargv, envp) ; + strerr_dieexec(111, newargv[0]) ; + } +} diff --git a/src/fdholder/s6-fdholder-retrievec.c b/src/fdholder/s6-fdholder-retrievec.c @@ -0,0 +1,52 @@ +/* ISC license. */ + +#include <skalibs/uint.h> +#include <skalibs/strerr2.h> +#include <skalibs/sgetopt.h> +#include <skalibs/tai.h> +#include <skalibs/djbunix.h> +#include <s6/s6-fdholder.h> + +#define USAGE "s6-fdholder-retrievec [ -D ] [ -t timeout ] id prog..." +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv, char const *const *envp) +{ + s6_fdholder_t a = S6_FDHOLDER_ZERO ; + tain_t deadline ; + int fd ; + int dodelete = 0 ; + PROG = "s6-fdholder-retrievec" ; + { + unsigned int t = 0 ; + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "Dt:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'D' : dodelete = 1 ; break ; + case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + if (t) tain_from_millisecs(&deadline, t) ; + else deadline = tain_infinite_relative ; + } + if (!argc) dieusage() ; + + s6_fdholder_init(&a, 6) ; + tain_now_g() ; + tain_add_g(&deadline, &deadline) ; + fd = s6_fdholder_retrieve_maybe_delete_g(&a, argv[0], dodelete, &deadline) ; + if (fd < 0) strerr_diefu2sys(111, "retrieve fd for id ", argv[0]) ; + else if (!fd) + { + if (uncoe(0) < 0) strerr_diefu1sys(111, "uncoe stdin") ; + } + else if (fd_move(0, fd) < 0) strerr_diefu1sys(111, "move fd") ; + pathexec_run(argv[1], argv+1, envp) ; + strerr_dieexec(111, argv[1]) ; +} diff --git a/src/fdholder/s6-fdholder-setdump.c b/src/fdholder/s6-fdholder-setdump.c @@ -0,0 +1,49 @@ +/* ISC license. */ + +#include <skalibs/uint.h> +#include <skalibs/sgetopt.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> +#include <s6/config.h> + +#define USAGE "s6-fdholder-setdump [ -t timeout ] socket" +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv, char const *const *envp) +{ + char const *newargv[8] ; + unsigned int timeout = 0 ; + unsigned int m = 0 ; + char fmtt[UINT_FMT] ; + PROG = "s6-fdholder-setdump" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "t:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 't' : if (!uint0_scan(l.arg, &timeout)) dieusage() ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) dieusage() ; + + newargv[m++] = S6_BINPREFIX "s6-ipcclient" ; + newargv[m++] = "-l0" ; + newargv[m++] = "--" ; + newargv[m++] = argv[0] ; + newargv[m++] = S6_BINPREFIX "s6-fdholder-setdumpc" ; + if (timeout) + { + fmtt[uint_fmt(fmtt, timeout)] = 0 ; + newargv[m++] = "-t" ; + newargv[m++] = fmtt ; + } + newargv[m++] = 0 ; + pathexec_run(newargv[0], newargv, envp) ; + strerr_dieexec(111, newargv[0]) ; +} diff --git a/src/fdholder/s6-fdholder-setdumpc.c b/src/fdholder/s6-fdholder-setdumpc.c @@ -0,0 +1,76 @@ +/* ISC license. */ + +#include <skalibs/uint.h> +#include <skalibs/bytestr.h> +#include <skalibs/env.h> +#include <skalibs/strerr2.h> +#include <skalibs/sgetopt.h> +#include <skalibs/tai.h> +#include <s6/s6-fdholder.h> + +#define USAGE "s6-fdholder-setdumpc [ -t timeout ]" +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv, char const *const *envp) +{ + s6_fdholder_t a = S6_FDHOLDER_ZERO ; + tain_t deadline ; + unsigned int dumplen ; + char const *x ; + PROG = "s6-fdholder-setdumpc" ; + { + unsigned int t = 0 ; + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "t:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + if (t) tain_from_millisecs(&deadline, t) ; + else deadline = tain_infinite_relative ; + } + + s6_fdholder_init(&a, 6) ; + x = env_get2(envp, "S6_FD#") ; + if (!x) strerr_dienotset(100, "S6_FD#") ; + if (!uint0_scan(x, &dumplen)) strerr_dieinvalid(100, "S6_FD#") ; + if (dumplen) + { + unsigned int i = 0 ; + s6_fdholder_fd_t dump[dumplen] ; + char s[11 + UINT_FMT] ; + tain_now_g() ; + tain_add_g(&deadline, &deadline) ; + for (; i < dumplen ; i++) + { + unsigned int fd, len ; + byte_copy(s, 6, "S6_FD_") ; + s[6 + uint_fmt(s+6, i)] = 0 ; + x = env_get2(envp, s) ; + if (!x) strerr_dienotset(100, s) ; + if (!uint0_scan(x, &fd)) strerr_dieinvalid(100, s) ; + dump[i].fd = fd ; + byte_copy(s, 8, "S6_FDID_") ; + s[8 + uint_fmt(s+8, i)] = 0 ; + x = env_get2(envp, s) ; + if (!x) strerr_dienotset(100, s) ; + len = str_len(x) ; + if (!len || len > S6_FDHOLDER_ID_SIZE) strerr_dieinvalid(100, s) ; + byte_copy(dump[i].id, len+1, x) ; + byte_copy(s, 11, "S6_FDLIMIT_") ; + s[11 + uint_fmt(s+11, i)] = 0 ; + x = env_get2(envp, s) ; + if (!x) tain_add_g(&dump[i].limit, &tain_infinite_relative) ; + else if (!timestamp_scan(x, &dump[i].limit)) strerr_dieinvalid(100, s) ; + } + if (!s6_fdholder_setdump_g(&a, dump, dumplen, &deadline)) + strerr_diefu1sys(111, "set dump") ; + } + return 0 ; +} diff --git a/src/fdholder/s6-fdholder-store.c b/src/fdholder/s6-fdholder-store.c @@ -0,0 +1,63 @@ +/* ISC license. */ + +#include <skalibs/uint.h> +#include <skalibs/sgetopt.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> +#include <s6/config.h> + +#define USAGE "s6-fdholder-store [ -d fd ] [ -t timeout ] [ -T fdtimeout ] socket id" +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv, char const *const *envp) +{ + char const *newargv[12] ; + unsigned int timeout = 0, limit = 0 ; + unsigned int m = 0 ; + char fmtt[UINT_FMT] ; + char fmtl[UINT_FMT] ; + PROG = "s6-fdholder-store" ; + { + unsigned int fd = 0 ; + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "d:t:T:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'd' : if (!uint0_scan(l.arg, &fd)) dieusage() ; break ; + case 't' : if (!uint0_scan(l.arg, &timeout)) dieusage() ; break ; + case 'T' : if (!uint0_scan(l.arg, &limit)) dieusage() ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + if (argc < 2) dieusage() ; + if (fd && fd_move(0, fd) < 0) + strerr_diefu1sys(111, "move file descriptor") ; + } + + newargv[m++] = S6_BINPREFIX "s6-ipcclient" ; + newargv[m++] = "-l0" ; + newargv[m++] = "--" ; + newargv[m++] = argv[0] ; + newargv[m++] = S6_BINPREFIX "s6-fdholder-storec" ; + if (timeout) + { + fmtt[uint_fmt(fmtt, timeout)] = 0 ; + newargv[m++] = "-t" ; + newargv[m++] = fmtt ; + } + if (limit) + { + fmtl[uint_fmt(fmtl, limit)] = 0 ; + newargv[m++] = "-T" ; + newargv[m++] = fmtl ; + } + newargv[m++] = "--" ; + newargv[m++] = argv[1] ; + newargv[m++] = 0 ; + pathexec_run(newargv[0], newargv, envp) ; + strerr_dieexec(111, newargv[0]) ; +} diff --git a/src/fdholder/s6-fdholder-storec.c b/src/fdholder/s6-fdholder-storec.c @@ -0,0 +1,46 @@ +/* ISC license. */ + +#include <skalibs/uint.h> +#include <skalibs/strerr2.h> +#include <skalibs/sgetopt.h> +#include <skalibs/tai.h> +#include <s6/s6-fdholder.h> + +#define USAGE "s6-fdholder-storec [ -t timeout ] [ -T fdtimeout ] id" +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv, char const *const *envp) +{ + s6_fdholder_t a = S6_FDHOLDER_ZERO ; + tain_t deadline, limit ; + PROG = "s6-fdholder-storec" ; + { + unsigned int t = 0, T = 0 ; + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "t:T:", &l) ; + if (opt == -1) break ; + switch (opt) + { + 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(&deadline, t) ; + else deadline = tain_infinite_relative ; + if (T) tain_from_millisecs(&limit, T) ; + else limit = tain_infinite_relative ; + } + if (!argc) dieusage() ; + + s6_fdholder_init(&a, 6) ; + tain_now_g() ; + tain_add_g(&deadline, &deadline) ; + tain_add_g(&limit, &limit) ; + if (!s6_fdholder_store_g(&a, 0, argv[0], &limit, &deadline)) + strerr_diefu1sys(111, "store fd") ; + return 0 ; +} diff --git a/src/fdholder/s6-fdholder-transferdump.c b/src/fdholder/s6-fdholder-transferdump.c @@ -0,0 +1,88 @@ +/* ISC license. */ + +#include <skalibs/uint.h> +#include <skalibs/sgetopt.h> +#include <skalibs/env.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> +#include <execline/config.h> +#include <s6/config.h> + +#define USAGE "s6-fdholder-transferdump [ -t timeoutfrom:timeoutto ] socketfrom socketto" +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv, char const *const *envp) +{ + char const *newargv[24] ; + unsigned int timeoutfrom = 0, timeoutto = 0 ; + unsigned int m = 0 ; + char fmtfrom[UINT_FMT] ; + char fmtto[UINT_FMT] ; + PROG = "s6-fdholder-setdump" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "t:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 't' : + { + unsigned int pos = uint_scan(l.arg, &timeoutfrom) ; + if (!pos) + { + if (l.arg[pos] != ':') dieusage() ; + timeoutfrom = 0 ; + } + if (!l.arg[pos]) timeoutto = 0 ; + else + { + if (l.arg[pos++] != ':') dieusage() ; + if (!l.arg[pos]) timeoutto = 0 ; + else if (!uint0_scan(l.arg + pos, &timeoutto)) dieusage() ; + } + break ; + } + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (argc < 2) dieusage() ; + + newargv[m++] = S6_BINPREFIX "s6-ipcclient" ; + newargv[m++] = "-l0" ; + newargv[m++] = "--" ; + newargv[m++] = argv[0] ; + newargv[m++] = EXECLINE_EXTBINPREFIX "fdclose" ; + newargv[m++] = "7" ; + newargv[m++] = EXECLINE_EXTBINPREFIX "fdmove" ; + newargv[m++] = "0" ; + newargv[m++] = "6" ; + newargv[m++] = S6_BINPREFIX "s6-ipcclient" ; + newargv[m++] = "-l0" ; + newargv[m++] = "--" ; + newargv[m++] = argv[1] ; + newargv[m++] = EXECLINE_EXTBINPREFIX "fdclose" ; + newargv[m++] = "6" ; + newargv[m++] = EXECLINE_EXTBINPREFIX "fdmove" ; + newargv[m++] = "1" ; + newargv[m++] = "7" ; + newargv[m++] = S6_BINPREFIX "s6-fdholder-transferdumpc" ; + if (timeoutfrom) + { + fmtfrom[uint_fmt(fmtfrom, timeoutfrom)] = 0 ; + newargv[m++] = "-t" ; + newargv[m++] = fmtfrom ; + } + if (timeoutto) + { + fmtto[uint_fmt(fmtto, timeoutto)] = 0 ; + newargv[m++] = "-T" ; + newargv[m++] = fmtto ; + } + newargv[m++] = 0 ; + pathexec_run(newargv[0], newargv, envp) ; + strerr_dieexec(111, newargv[0]) ; +} diff --git a/src/fdholder/s6-fdholder-transferdumpc.c b/src/fdholder/s6-fdholder-transferdumpc.c @@ -0,0 +1,51 @@ +/* ISC license. */ + +#include <skalibs/uint.h> +#include <skalibs/strerr2.h> +#include <skalibs/sgetopt.h> +#include <skalibs/tai.h> +#include <skalibs/genalloc.h> +#include <s6/s6-fdholder.h> + +#define USAGE "s6-fdholder-transferdumpc [ -t timeoutfrom ] [ -T timeoutto ]" +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv, char const *const *envp) +{ + s6_fdholder_t a = S6_FDHOLDER_ZERO ; + genalloc dump = GENALLOC_ZERO ; + tain_t deadline, totto ; + PROG = "s6-fdholder-transferdumpc" ; + { + unsigned int t = 0, T = 0 ; + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "t:T:", &l) ; + if (opt == -1) break ; + switch (opt) + { + 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(&deadline, t) ; + else deadline = tain_infinite_relative ; + if (T) tain_from_millisecs(&totto, T) ; + else totto = tain_infinite_relative ; + } + + s6_fdholder_init(&a, 0) ; + tain_now_g() ; + tain_add_g(&deadline, &deadline) ; + if (!s6_fdholder_getdump_g(&a, &dump, &deadline)) + strerr_diefu1sys(111, "get dump") ; + s6_fdholder_free(&a) ; + s6_fdholder_init(&a, 1) ; + tain_add_g(&deadline, &totto) ; + if (!s6_fdholder_setdump_g(&a, genalloc_s(s6_fdholder_fd_t, &dump), genalloc_len(s6_fdholder_fd_t, &dump), &deadline)) + strerr_diefu1sys(111, "set dump") ; + return 0 ; +} diff --git a/src/fdholder/s6-fdholderd.c b/src/fdholder/s6-fdholderd.c @@ -0,0 +1,798 @@ +/* ISC license. */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/resource.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <signal.h> +#include <regex.h> +#include <skalibs/uint32.h> +#include <skalibs/uint.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/sgetopt.h> +#include <skalibs/env.h> +#include <skalibs/bytestr.h> +#include <skalibs/error.h> +#include <skalibs/strerr2.h> +#include <skalibs/tai.h> +#include <skalibs/djbunix.h> +#include <skalibs/sig.h> +#include <skalibs/iopause.h> +#include <skalibs/selfpipe.h> +#include <skalibs/siovec.h> +#include <skalibs/cdb.h> +#include <skalibs/webipc.h> +#include <skalibs/genset.h> +#include <skalibs/avltreen.h> +#include <skalibs/unixmessage.h> +#include <skalibs/unixconnection.h> +#include <s6/accessrules.h> +#include <s6/s6-fdholder.h> + +#define USAGE "s6-fdholderd [ -v verbosity ] [ -1 ] [ -c maxconn ] [ -n maxfds ] [ -t timeout ] [ -T lameducktimeout ] [ -i rulesdir | -x rulesfile ]" +#define dieusage() strerr_dieusage(100, USAGE) ; + +static unsigned int verbosity = 1 ; +static int cont = 1 ; +static tain_t answertto = TAIN_INFINITE_RELATIVE ; +static tain_t lameduckdeadline = TAIN_INFINITE_RELATIVE ; +static tain_t const nano1 = { .sec = TAI_ZERO, .nano = 1 } ; + +static unsigned int rulestype = 0 ; +static char const *rules = 0 ; +static int cdbfd = -1 ; +static struct cdb cdbmap = CDB_ZERO ; + +static void handle_signals (void) +{ + for (;;) switch (selfpipe_read()) + { + case -1 : strerr_diefu1sys(111, "selfpipe_read()") ; + case 0 : return ; + case SIGTERM : + { + if (cont) + { + cont = 0 ; + tain_add_g(&lameduckdeadline, &lameduckdeadline) ; + } + break ; + } + case SIGHUP : + { + int fd ; + struct cdb c = CDB_ZERO ; + if (rulestype != 2) break ; + fd = open_readb(rules) ; + if (fd < 0) break ; + if (cdb_init(&c, fd) < 0) + { + fd_close(fd) ; + break ; + } + cdb_free(&cdbmap) ; + fd_close(cdbfd) ; + cdbfd = fd ; + cdbmap = c ; + } + break ; + default : break ; + } +} + + /* fd store */ + +static genset *fdstore ; +#define FD(i) genset_p(s6_fdholder_fd_t, fdstore, (i)) +static unsigned int maxfds = 1000 ; +#define numfds genset_n(fdstore) +static avltreen *fds_by_id ; +static avltreen *fds_by_deadline ; + +static void *fds_id_dtok (unsigned int d, void *x) +{ + (void)x ; + return FD(d)->id ; +} + +static int fds_id_cmp (void const *a, void const *b, void *x) +{ + (void)x ; + return str_diff((char const *)a, (char const *)b) ; +} + +static void *fds_deadline_dtok (unsigned int d, void *x) +{ + (void)x ; + return &FD(d)->limit ; +} + +static int fds_deadline_cmp (void const *a, void const *b, void *x) +{ + register tain_t const *aa = (tain_t const *)a ; + register tain_t const *bb = (tain_t const *)b ; + (void)x ; + return tain_less(aa, bb) ? -1 : tain_less(bb, aa) ; +} + +static void fds_delete (unsigned int pp) +{ + avltreen_delete(fds_by_id, fds_id_dtok(pp, 0)) ; + avltreen_delete(fds_by_deadline, fds_deadline_dtok(pp, 0)) ; + genset_delete(fdstore, pp) ; +} + + + /* client connection */ + +typedef struct client_s client_t, *client_t_ref ; +struct client_s +{ + unsigned int next ; + unsigned int xindex ; + tain_t deadline ; + regex_t rre ; + regex_t wre ; + unsigned int dumping ; + unsigned int flags ; + unixconnection_t connection ; +} ; + +static genset *clients ; +static unsigned int sentinel ; +#define CLIENT(i) genset_p(client_t, clients, (i)) +#define numconn (genset_n(clients) - 1) + +static inline void client_free (client_t *c) +{ + fd_close(unixmessage_sender_fd(&c->connection.out)) ; + unixconnection_free(&c->connection) ; + regfree(&c->rre) ; + regfree(&c->wre) ; +} + +static inline void client_delete (unsigned int cc, unsigned int prev) +{ + register client_t *c = CLIENT(cc) ; + CLIENT(prev)->next = c->next ; + client_free(c) ; + genset_delete(clients, cc) ; +} + +static void removeclient (unsigned int *i, unsigned int j) +{ + client_delete(*i, j) ; + *i = j ; +} + +static void client_setdeadline (client_t *c) +{ + tain_t blah ; + tain_half(&blah, &tain_infinite_relative) ; + tain_add_g(&blah, &blah) ; + if (tain_less(&blah, &c->deadline)) + tain_add_g(&c->deadline, &answertto) ; +} + +static inline int client_prepare_iopause (unsigned int i, tain_t *deadline, iopause_fd *x, unsigned int *j) +{ + register client_t *c = CLIENT(i) ; + if (tain_less(&c->deadline, deadline)) *deadline = c->deadline ; + if (!unixmessage_sender_isempty(&c->connection.out) || !unixmessage_receiver_isempty(&c->connection.in) || (cont && !unixmessage_receiver_isfull(&c->connection.in))) + { + x[*j].fd = unixmessage_sender_fd(&c->connection.out) ; + x[*j].events = (!unixmessage_receiver_isempty(&c->connection.in) || (cont && !unixmessage_receiver_isfull(&c->connection.in)) ? IOPAUSE_READ : 0) | (!unixmessage_sender_isempty(&c->connection.out) ? IOPAUSE_WRITE : 0) ; + c->xindex = (*j)++ ; + } + else c->xindex = 0 ; + return !!c->xindex ; +} + +static inline void client_add (unsigned int *cc, int fd, regex_t const *rre, regex_t const *wre, unsigned int flags) +{ + unsigned int i ; + client_t *c ; + i = genset_new(clients) ; + c = CLIENT(i) ; + tain_add_g(&c->deadline, &answertto) ; + c->rre = *rre ; + c->wre = *wre ; + c->dumping = 0 ; + c->flags = flags ; + unixconnection_init(&c->connection, fd, fd) ; + c->next = CLIENT(sentinel)->next ; + CLIENT(sentinel)->next = i ; + *cc = i ; +} + +static inline int client_flush (unsigned int i, iopause_fd const *x) +{ + register client_t *c = CLIENT(i) ; + if (c->xindex && (x[c->xindex].revents & IOPAUSE_WRITE)) + { + if (unixconnection_flush(&c->connection)) + tain_add_g(&c->deadline, &tain_infinite_relative) ; + else if (!error_isagain(errno)) return 0 ; + } + return 1 ; +} + +static int answer (client_t *c, char e) +{ + unixmessage_t m = { .s = &e, .len = 1, .fds = 0, .nfds = 0 } ; + if (!unixmessage_put(&c->connection.out, &m)) return 0 ; + client_setdeadline(c) ; + return 1 ; +} + +static int do_store (unsigned int cc, unixmessage_t const *m) +{ + unsigned int pp, idlen ; + client_t *c = CLIENT(cc) ; + s6_fdholder_fd_t *p ; + if (c->dumping || m->len < TAIN_PACK + 3 || m->nfds != 1) return (errno = EPROTO, 0) ; + idlen = (unsigned char)m->s[TAIN_PACK] ; + if (idlen > S6_FDHOLDER_ID_SIZE || idlen + 2 + TAIN_PACK != m->len || m->s[1 + TAIN_PACK + idlen]) return (errno = EPROTO, 0) ; + if (regexec(&c->wre, m->s + TAIN_PACK + 1, 0, 0, 0)) + { + unixmessage_drop(m) ; + return answer(c, EPERM) ; + } + if (numfds >= maxfds) + { + unixmessage_drop(m) ; + return answer(c, ENOSPC) ; + } + if (avltreen_search(fds_by_id, m->s + TAIN_PACK + 1, &pp)) + { + unixmessage_drop(m) ; + return answer(c, EBUSY) ; + } + if (!answer(c, 0)) return 0 ; + pp = genset_new(fdstore) ; p = FD(pp) ; + tain_unpack(m->s, &p->limit) ; p->fd = m->fds[0] ; + byte_copy(p->id, idlen, m->s + TAIN_PACK + 1) ; + byte_zero(p->id + idlen, S6_FDHOLDER_ID_SIZE + 1 - idlen) ; + for (;;) + { + unsigned int dummy ; + if (!avltreen_search(fds_by_deadline, &p->limit, &dummy)) break ; + tain_add(&p->limit, &p->limit, &nano1) ; + } + avltreen_insert(fds_by_id, pp) ; + avltreen_insert(fds_by_deadline, pp) ; + return 1 ; +} + +static int do_delete (unsigned int cc, unixmessage_t const *m) +{ + unsigned int pp, idlen ; + client_t *c = CLIENT(cc) ; + if (c->dumping || m->len < 3 || m->nfds) return (errno = EPROTO, 0) ; + idlen = (unsigned char)m->s[0] ; + if (idlen > S6_FDHOLDER_ID_SIZE || idlen + 2 != m->len || m->s[idlen + 1]) return (errno = EPROTO, 0) ; + if (regexec(&c->wre, m->s + 1, 0, 0, 0)) return answer(c, EPERM) ; + if (!avltreen_search(fds_by_id, m->s + 1, &pp)) return answer(c, ENOENT) ; + if (!answer(c, 0)) return 0 ; + fd_close(FD(pp)->fd) ; + fds_delete(pp) ; + return 1 ; +} + +static int do_retrieve (unsigned int cc, unixmessage_t const *m) +{ + int fd ; + unixmessage_t ans = { .s = "", .len = 1, .fds = &fd, .nfds = 1 } ; + unsigned int pp, idlen ; + client_t *c = CLIENT(cc) ; + if (c->dumping || m->len < 4 || m->nfds) return (errno = EPROTO, 0) ; + idlen = (unsigned char)m->s[1] ; + if (idlen > S6_FDHOLDER_ID_SIZE || idlen + 3 != m->len || m->s[idlen + 2]) return (errno = EPROTO, 0) ; + if (regexec(&c->rre, m->s + 2, 0, 0, 0)) return answer(c, EPERM) ; + if (m->s[0] && regexec(&c->wre, m->s + 2, 0, 0, 0)) return answer(c, EPERM) ; + if (!avltreen_search(fds_by_id, m->s + 2, &pp)) return answer(c, ENOENT) ; + fd = FD(pp)->fd ; + if (!unixmessage_put_and_close(&c->connection.out, &ans, m->s[0] ? unixmessage_bits_closeall : unixmessage_bits_closenone)) return 0 ; + if (m->s[0]) fds_delete(pp) ; + return 1 ; +} + +static int fill_siovec_with_ids_iter (char *thing, void *data) +{ + siovec_t *v = (*(siovec_t **)data)++ ; + s6_fdholder_fd_t *p = (s6_fdholder_fd_t *)thing ; + v->s = p->id ; + v->len = str_len(p->id) + 1 ; + return 1 ; +} + +static int do_list (unsigned int cc, unixmessage_t const *m) +{ + client_t *c = CLIENT(cc) ; + siovec_t v[numfds] ; + unixmessage_v_t ans = { .v = v, .vlen = 1+numfds, .fds = 0, .nfds = 0 } ; + siovec_t *vp = v + 1 ; + char pack[5] = "" ; + if (c->dumping || m->len || m->nfds) return (errno = EPROTO, 0) ; + uint32_pack_big(pack + 1, (uint32)numfds) ; + v[0].s = pack ; v[0].len = 5 ; + genset_iter(fdstore, &fill_siovec_with_ids_iter, &vp) ; + if (!unixmessage_putv(&c->connection.out, &ans)) return answer(c, errno) ; + client_setdeadline(c) ; + return 1 ; +} + +typedef struct getdumpiter_s getdumpiter_t, *getdumpiter_t_ref ; +struct getdumpiter_s +{ + siovec_t *v ; + int *fd ; + char *limit ; +} ; + +static int getdump_iter (char *thing, void *stuff) +{ + s6_fdholder_fd_t *p = (s6_fdholder_fd_t *)thing ; + getdumpiter_t *blah = stuff ; + unsigned char len = str_len(p->id) ; + tain_pack(blah->limit, &p->limit) ; + blah->limit[TAIN_PACK] = (unsigned char)len ; + blah->v->s = p->id ; + blah->v->len = len + 1 ; + *blah->fd++ = p->fd ; + blah->v += 2 ; + blah->limit += TAIN_PACK + 1 ; + return 1 ; +} + +static int do_getdump (unsigned int cc, unixmessage_t const *m) +{ + unsigned int n = numfds ? 1 + ((numfds-1) / UNIXMESSAGE_MAXFDS) : 0 ; + client_t *c = CLIENT(cc) ; + if (c->dumping || m->len || m->nfds) return (errno = EPROTO, 0) ; + if (!(c->flags & 1)) return answer(c, EPERM) ; + { + char pack[9] = "" ; + unixmessage_t ans = { .s = pack, .len = 9, .fds = 0, .nfds = 0 } ; + uint32_pack_big(pack+1, (uint32)n) ; + uint32_pack_big(pack+5, (uint32)numfds) ; + if (!unixmessage_put(&c->connection.out, &ans)) return answer(c, errno) ; + } + if (n) + { + unsigned int i = 0 ; + unixmessage_v_t ans[n] ; + siovec_t v[numfds << 1] ; + int fds[numfds] ; + char limits[(TAIN_PACK+1) * numfds] ; + for (; i < numfds ; i++) + { + v[i<<1].s = limits + i * (TAIN_PACK+1) ; + v[i<<1].len = TAIN_PACK+1 ; + } + { + getdumpiter_t state = { .v = v+1, .fd = fds, .limit = limits } ; + genset_iter(fdstore, &getdump_iter, &state) ; + } + for (i = 0 ; i < n-1 ; i++) + { + ans[i].v = v + (i<<1) * UNIXMESSAGE_MAXFDS ; + ans[i].vlen = UNIXMESSAGE_MAXFDS << 1 ; + ans[i].fds = fds + i * UNIXMESSAGE_MAXFDS ; + ans[i].nfds = UNIXMESSAGE_MAXFDS ; + } + ans[n-1].v = v + ((n-1)<<1) * UNIXMESSAGE_MAXFDS ; + ans[n-1].vlen = (1 + (numfds-1) % UNIXMESSAGE_MAXFDS) << 1 ; + ans[n-1].fds = fds + (n-1) * UNIXMESSAGE_MAXFDS ; + ans[n-1].nfds = 1 + (numfds - 1) % UNIXMESSAGE_MAXFDS ; + for (i = 0 ; i < n ; i++) + { + if (!unixmessage_putv(&c->connection.out, ans + i)) + { + int e = errno ; + ++i ; + while (i--) unixmessage_unput(&c->connection.out) ; + return answer(c, e) ; + } + } + } + client_setdeadline(c) ; + return 1 ; +} + +static int do_setdump (unsigned int cc, unixmessage_t const *m) +{ + char pack[5] = "" ; + uint32 n ; + unixmessage_t ans = { .s = pack, .len = 5, .fds = 0, .nfds = 0 } ; + client_t *c = CLIENT(cc) ; + if (c->dumping || m->len != 4 || m->nfds) return (errno = EPROTO, 0) ; + if (!(c->flags & 2)) return answer(c, EPERM) ; + uint32_unpack_big(m->s, &n) ; + if (n > maxfds || n + numfds > maxfds) return answer(c, ENFILE) ; + c->dumping = n ; + n = n ? 1 + (n-1) / UNIXMESSAGE_MAXFDS : 0 ; + uint32_pack_big(pack+1, n) ; + if (!unixmessage_put(&c->connection.out, &ans)) return answer(c, errno) ; + return 1 ; +} + +static int do_setdump_data (unsigned int cc, unixmessage_t const *m) +{ + client_t *c = CLIENT(cc) ; + if (!m->nfds || m->nfds > c->dumping || m->len < m->nfds * (TAIN_PACK + 3)) + return (errno = EPROTO, 0) ; + if (!(c->flags & 2)) + { + unixmessage_drop(m) ; + return answer(c, EPERM) ; + } + if (numfds + m->nfds > maxfds) + { + unixmessage_drop(m) ; + return answer(c, ENFILE) ; + } + { + char const *s = m->s ; + unsigned int len = m->len ; + unsigned int i = 0 ; + unsigned int indices[m->nfds] ; + for (; i < m->nfds ; i++) + { + s6_fdholder_fd_t *p ; + unsigned int idlen ; + if (len < TAIN_PACK + 3) break ; + idlen = (unsigned char)s[TAIN_PACK] ; + if (idlen > S6_FDHOLDER_ID_SIZE || len < TAIN_PACK + 2 + idlen || s[TAIN_PACK + 1 + idlen]) break ; + indices[i] = genset_new(fdstore) ; + p = FD(indices[i]) ; + tain_unpack(s, &p->limit) ; + byte_copy(p->id, idlen+1, s + TAIN_PACK + 1) ; + p->fd = m->fds[i] ; + char fmt[TIMESTAMP] ; + fmt[timestamp_fmt(fmt, &p->limit)] = 0 ; + avltreen_insert(fds_by_id, indices[i]) ; + avltreen_insert(fds_by_deadline, indices[i]) ; + s += TAIN_PACK + 2 + idlen ; len -= TAIN_PACK + 2 + idlen ; + } + if (i < m->nfds || len) + { + while (i--) fds_delete(indices[i]) ; + return (errno = EPROTO, 0) ; + } + } + c->dumping -= m->nfds ; + return answer(c, c->dumping ? EAGAIN : 0) ; +} + +static int do_error (unsigned int cc, unixmessage_t const *m) +{ + (void)cc ; + (void)m ; + return (errno = EPROTO, 0) ; +} + +typedef int parsefunc_t (unsigned int, unixmessage_t const *) ; +typedef parsefunc_t *parsefunc_t_ref ; + +static inline int parse_protocol (unixmessage_t const *m, void *p) +{ + static parsefunc_t_ref const f[8] = + { + &do_store, + &do_delete, + &do_retrieve, + &do_list, + &do_getdump, + &do_setdump, + &do_setdump_data, + &do_error + } ; + unixmessage_t mcopy = { .s = m->s + 1, .len = m->len - 1, .fds = m->fds, .nfds = m->nfds } ; + if (!m->len) + { + unixmessage_drop(m) ; + return (errno = EPROTO, 0) ; + } + if (!(*f[byte_chr("SDRL?!.", 7, m->s[0])])(*(unsigned int *)p, &mcopy)) + { + unixmessage_drop(m) ; + return 0 ; + } + return 1 ; +} + +static inline int client_read (unsigned int cc, iopause_fd const *x) +{ + register client_t *c = CLIENT(cc) ; + return !unixmessage_receiver_isempty(&c->connection.in) || (c->xindex && (x[c->xindex].revents & IOPAUSE_READ)) ? + unixmessage_handle(&c->connection.in, &parse_protocol, &cc) > 0 : 1 ; +} + + + /* Environment on new connections */ + +static int makere (regex_t *re, char const *s, char const *var) +{ + register unsigned int varlen = str_len(var) ; + if (str_start(s, var) && (s[varlen] == '=')) + { + int r = regcomp(re, s + varlen + 1, REG_EXTENDED | REG_NOSUB) ; + if (r) + { + if (verbosity) + { + char buf[256] ; + regerror(r, re, buf, 256) ; + strerr_warnw6x("invalid ", var, " value: ", s + varlen + 1, ": ", buf) ; + } + return -1 ; + } + else return 1 ; + } + return 0 ; +} + +static void defaultre (regex_t *re) +{ + int r = regcomp(re, "^$", REG_EXTENDED | REG_NOSUB) ; + if (r) + { + char buf[256] ; + regerror(r, re, buf, 256) ; + strerr_diefu2x(100, "compile ^$ into a regular expression: ", buf) ; + } +} + +static inline int parse_env (char const *const *envp, regex_t *rre, regex_t *wre, unsigned int *flags) +{ + unsigned int fl = 0 ; + int rre_done = 0, wre_done = 0 ; + for (; *envp ; envp++) + { + if (str_start(*envp, "S6_FDHOLDER_GETDUMP=")) fl |= 1 ; + if (str_start(*envp, "S6_FDHOLDER_SETDUMP=")) fl |= 2 ; + if (!rre_done) + { + rre_done = makere(rre, *envp, "S6_FDHOLDER_RETRIEVE_REGEX") ; + if (rre_done < 0) + { + if (wre_done) regfree(wre) ; + return 0 ; + } + } + if (!wre_done) + { + wre_done = makere(wre, *envp, "S6_FDHOLDER_STORE_REGEX") ; + if (wre_done < 0) + { + if (rre_done) regfree(rre) ; + return 0 ; + } + } + } + if (!rre_done) defaultre(wre) ; + if (!wre_done) defaultre(wre) ; + *flags = fl ; + return 1 ; +} + +static inline int new_connection (int fd, regex_t *rre, regex_t *wre, unsigned int *flags) +{ + s6_accessrules_params_t params = S6_ACCESSRULES_PARAMS_ZERO ; + s6_accessrules_result_t result = S6_ACCESSRULES_ERROR ; + unsigned int uid, gid ; + + if (ipc_eid(fd, &uid, &gid) < 0) + { + if (verbosity) strerr_warnwu1sys("getpeereid") ; + return 0 ; + } + + switch (rulestype) + { + case 1 : + result = s6_accessrules_uidgid_fs(uid, gid, rules, &params) ; break ; + case 2 : + result = s6_accessrules_uidgid_cdb(uid, gid, &cdbmap, &params) ; break ; + default : break ; + } + if (result != S6_ACCESSRULES_ALLOW) + { + if (verbosity && (result == S6_ACCESSRULES_ERROR)) + strerr_warnw1sys("error while checking rules") ; + return 0 ; + } + if (params.exec.len && verbosity) + { + char fmtuid[UINT_FMT] ; + char fmtgid[UINT_FMT] ; + fmtuid[uint_fmt(fmtuid, uid)] = 0 ; + fmtgid[uint_fmt(fmtgid, gid)] = 0 ; + strerr_warnw4x("unused exec string in rules for uid ", fmtuid, " gid ", fmtgid) ; + } + if (params.env.s) + { + unsigned int n = byte_count(params.env.s, params.env.len, '\0') ; + char const *envp[n+1] ; + if (!env_make(envp, n, params.env.s, params.env.len)) + { + if (verbosity) strerr_warnwu1sys("env_make") ; + s6_accessrules_params_free(&params) ; + return 0 ; + } + envp[n] = 0 ; + if (!parse_env(envp, rre, wre, flags)) + { + if (verbosity) strerr_warnwu1sys("parse_env") ; + s6_accessrules_params_free(&params) ; + return 0 ; + } + s6_accessrules_params_free(&params) ; + } + return 1 ; +} + +int main (int argc, char const *const *argv, char const *const *envp) +{ + int spfd ; + int flag1 = 0 ; + unsigned int maxconn = 40 ; + PROG = "s6-fdholderd" ; + + { + subgetopt_t l = SUBGETOPT_ZERO ; + unsigned int t = 0, T = 0 ; + for (;;) + { + register 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 ; + case 'c' : if (!uint0_scan(l.arg, &maxconn)) dieusage() ; break ; + case 'n' : if (!uint0_scan(l.arg, &maxfds)) dieusage() ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + if (t) tain_from_millisecs(&answertto, t) ; + if (T) tain_from_millisecs(&lameduckdeadline, T) ; + } + if (!rulestype) strerr_dief1x(100, "no access rights specified!") ; + if (maxconn > S6_FDHOLDER_MAX) maxconn = S6_FDHOLDER_MAX ; + if (!maxconn) maxconn = 1 ; + { + struct rlimit fdlimit ; + if (getrlimit(RLIMIT_NOFILE, &fdlimit) < 0) + strerr_diefu1sys(111, "getrlimit") ; + if (fdlimit.rlim_cur != RLIM_INFINITY) + { + if (fdlimit.rlim_cur < 6) + strerr_dief1x(111, "open file limit too low") ; + if (maxfds > fdlimit.rlim_cur) maxfds = fdlimit.rlim_cur - 5 ; + } + } + if (!maxfds) maxfds = 1 ; + { + struct stat st ; + if (fstat(0, &st) < 0) strerr_diefu1sys(111, "fstat stdin") ; + if (!S_ISSOCK(st.st_mode)) strerr_dief1x(100, "stdin is not a socket") ; + } + if (flag1) + { + if (fcntl(1, F_GETFD) < 0) + strerr_dief1sys(100, "called with option -1 but stdout said") ; + } + else close(1) ; + spfd = selfpipe_init() ; + if (spfd < 0) strerr_diefu1sys(111, "selfpipe_init") ; + if (sig_ignore(SIGPIPE) < 0) strerr_diefu1sys(111, "ignore SIGPIPE") ; + { + sigset_t set ; + sigemptyset(&set) ; + sigaddset(&set, SIGTERM) ; + sigaddset(&set, SIGHUP) ; + if (selfpipe_trapset(&set) < 0) strerr_diefu1sys(111, "trap signals") ; + } + + if (rulestype == 2) + { + cdbfd = open_readb(rules) ; + if (cdbfd < 0) strerr_diefu3sys(111, "open ", rules, " for reading") ; + if (cdb_init(&cdbmap, cdbfd) < 0) + strerr_diefu2sys(111, "cdb_init ", rules) ; + } + + { + /* Hello, stack. I have a present for you. */ + GENSETB_TYPE(client_t, 1+maxconn) clientblob ; + GENSETB_TYPE(s6_fdholder_fd_t, maxfds) fdblob ; + AVLTREEB_TYPE(maxfds) fdmap_id ; + AVLTREEB_TYPE(maxfds) fdmap_deadline ; + iopause_fd x[2 + maxconn] ; + /* Hope you enjoyed it! Have a nice day! */ + + GENSETB_init(client_t, &clientblob, 1+maxconn) ; + clients = &clientblob.info ; + sentinel = gensetb_new(&clientblob) ; + clientblob.storage[sentinel].next = sentinel ; + GENSETB_init(s6_fdholder_t, &fdblob, maxfds) ; + fdstore = &fdblob.info ; + avltreeb_init(&fdmap_id, maxfds, &fds_id_dtok, &fds_id_cmp, 0) ; + fds_by_id = &fdmap_id.info ; + avltreeb_init(&fdmap_deadline, maxfds, &fds_deadline_dtok, &fds_deadline_cmp, 0) ; + fds_by_deadline = &fdmap_deadline.info ; + x[0].fd = spfd ; x[0].events = IOPAUSE_READ ; + x[1].fd = 0 ; + + if (flag1) + { + fd_write(1, "\n", 1) ; + fd_close(1) ; + } + tain_now_g() ; + + for (;;) + { + tain_t deadline ; + unsigned int j = 2 ; + unsigned int i ; + int r = 1 ; + + if (cont) tain_add_g(&deadline, &tain_infinite_relative) ; + else deadline = lameduckdeadline ; + if (avltreeb_min(&fdmap_deadline, &i) && tain_less(&FD(i)->limit, &deadline)) deadline = FD(i)->limit ; + x[1].events = (cont && (numconn < maxconn)) ? IOPAUSE_READ : 0 ; + for (i = clientblob.storage[sentinel].next ; i != sentinel ; i = clientblob.storage[i].next) + if (client_prepare_iopause(i, &deadline, x, &j)) r = 0 ; + if (!cont && r) break ; + + r = iopause_g(x, j, &deadline) ; + if (r < 0) strerr_diefu1sys(111, "iopause") ; + + if (!r) + { + if (!cont && !tain_future(&lameduckdeadline)) return 1 ; + for (;;) + { + if (!avltreeb_min(&fdmap_deadline, &i)) break ; + if (tain_future(&FD(i)->limit)) break ; + fd_close(FD(i)->fd) ; + fds_delete(i) ; + } + for (j = sentinel, i = clientblob.storage[sentinel].next ; i != sentinel ; j = i, i = clientblob.storage[i].next) + if (!tain_future(&clientblob.storage[i].deadline)) removeclient(&i, j) ; + continue ; + } + + if (x[0].revents & IOPAUSE_READ) handle_signals() ; + + for (j = sentinel, i = clientblob.storage[sentinel].next ; i != sentinel ; j = i, i = clientblob.storage[i].next) + if (!client_flush(i, x)) removeclient(&i, j) ; + + for (j = sentinel, i = clientblob.storage[sentinel].next ; i != sentinel ; j = i, i = clientblob.storage[i].next) + if (!client_read(i, x)) removeclient(&i, j) ; + + if (x[1].revents & IOPAUSE_READ) + { + regex_t rre, wre ; + unsigned int flags = 0 ; + int fd = ipc_accept_nb(x[1].fd, 0, 0, (int *)&i) ; + if (fd < 0) + if (!error_isagain(errno)) strerr_diefu1sys(111, "accept") ; + else continue ; + else if (!new_connection(fd, &rre, &wre, &flags)) fd_close(fd) ; + else client_add(&i, fd, &rre, &wre, flags) ; + } + } + } + return 0 ; +} diff --git a/src/libs6/s6_fdholder_setdump.c b/src/libs6/s6_fdholder_setdump.c @@ -30,7 +30,7 @@ int s6_fdholder_setdump (s6_fdholder_t *a, s6_fdholder_fd_t const *list, unsigne if (!m.len || m.nfds) { unixmessage_drop(&m) ; return (errno = EPROTO, 0) ; } if (m.s[0]) return (errno = m.s[0], 0) ; if (m.len != 5) return (errno = EPROTO, 0) ; - uint32_unpack_big(pack + 1, &trips) ; + uint32_unpack_big(m.s + 1, &trips) ; if (trips != 1 + (ntot-1) / UNIXMESSAGE_MAXFDS) return (errno = EPROTO, 0) ; } for (i = 0 ; i < trips ; i++, ntot -= UNIXMESSAGE_MAXFDS) @@ -49,9 +49,9 @@ int s6_fdholder_setdump (s6_fdholder_t *a, s6_fdholder_fd_t const *list, unsigne v[1 + (j<<1)].s = pack + j * (TAIN_PACK+1) ; v[1 + (j<<1)].len = TAIN_PACK + 1 ; tain_pack(pack + j * (TAIN_PACK+1), &list->limit) ; - pack[j * (TAIN_PACK+1) + TAIN_PACK] = (unsigned char)len + 1 ; + pack[j * (TAIN_PACK+1) + TAIN_PACK] = (unsigned char)len ; v[2 + (j<<1)].s = (char *)list->id ; - v[2 + (j<<1)].len = len ; + v[2 + (j<<1)].len = len + 1 ; fds[j] = list->fd ; } if (!unixmessage_putv(&a->connection.out, &m)) return 0 ;