diff options
Diffstat (limited to 'src')
27 files changed, 651 insertions, 126 deletions
diff --git a/src/daemontools-extras/s6-log.c b/src/daemontools-extras/s6-log.c index e788016..14059c0 100644 --- a/src/daemontools-extras/s6-log.c +++ b/src/daemontools-extras/s6-log.c @@ -30,6 +30,7 @@ #include <skalibs/selfpipe.h> #include <skalibs/skamisc.h> #include <skalibs/environ.h> +#include <execline/config.h> #define USAGE "s6-log [ -q | -v ] [ -b ] [ -p ] [ -t ] [ -e ] logging_script" #define dienomem() strerr_diefu1sys(111, "stralloc_catb") @@ -354,7 +355,7 @@ static int finish (logdir_t *ldp, char const *name, char suffix) static inline void exec_processor (logdir_t_ref ldp) { - char const *cargv[4] = { "execlineb", "-Pc", ldp->processor, 0 } ; + char const *cargv[4] = { EXECLINE_EXTBINPREFIX "execlineb", "-Pc", ldp->processor, 0 } ; unsigned int dirlen = str_len(ldp->dir) ; int fd ; char x[dirlen + 10] ; diff --git a/src/include/s6/ftrigw.h b/src/include/s6/ftrigw.h index 5be9d13..38d89f1 100644 --- a/src/include/s6/ftrigw.h +++ b/src/include/s6/ftrigw.h @@ -8,6 +8,7 @@ extern int ftrigw_fifodir_make (char const *, int, int) ; extern int ftrigw_notify (char const *, char) ; extern int ftrigw_notifyb (char const *, char const *, unsigned int) ; +extern int ftrigw_notifyb_nosig (char const *, char const *, unsigned int) ; #define ftrigw_notifys(f, s) ftrigw_notifyb(f, (s), str_len(s)) extern int ftrigw_clean (char const *) ; diff --git a/src/include/s6/s6-fdholder.h b/src/include/s6/s6-fdholder.h new file mode 100644 index 0000000..0285a21 --- /dev/null +++ b/src/include/s6/s6-fdholder.h @@ -0,0 +1,80 @@ + /* ISC license. */ + +#ifndef S6_FDHOLDER_H +#define S6_FDHOLDER_H + +#include <skalibs/tai.h> +#include <skalibs/stralloc.h> +#include <skalibs/genalloc.h> +#include <skalibs/unixmessage.h> +#include <skalibs/unixconnection.h> + +#define S6_FDHOLDER_ID_SIZE 255 + +typedef struct s6_fdholder_s s6_fdholder_t, *s6_fdholder_t_ref ; +struct s6_fdholder_s +{ + unixconnection_t connection ; +} ; +#define S6_FDHOLDER_ZERO { .connection = UNIXMESSAGE_CONNECTION_ZERO } ; + +#define s6_fdholder_init(a, fdin, fdout) unixconnection_init(&(a)->connection, fdin, fdout) +#define s6_fdholder_free(a) unixconnection_free(&(a)->connection) + + + /* Individual fds */ + +extern int s6_fdholder_store_async (s6_fdholder_t *, int, char const *, tain_t const *) ; +extern int s6_fdholder_store (s6_fdholder_t *, int, char const *, tain_t const *, tain_t const *, tain_t *) ; +#define s6_fdholder_store_g(a, fd, id, limit, deadline) s6_fdholder_store(a, fd, id, limit, (deadline), &STAMP) + +extern int s6_fdholder_delete_async (s6_fdholder_t *, char const *) ; +extern int s6_fdholder_delete (s6_fdholder_t *, char const *, tain_t const *, tain_t *) ; +#define s6_fdholder_delete_g(a, id, deadline) s6_fdholder_delete(a, id, (deadline), &STAMP) + +typedef struct s6_fdholder_retrieve_result_s s6_fdholder_retrieve_result_t, *s6_fdholder_retrieve_result_t_ref ; +struct s6_fdholder_retrieve_result_s +{ + int fd ; + unsigned char err ; +} ; + +extern int s6_fdholder_retrieve_maybe_delete_async (s6_fdholder_t *, char const *, int) ; +extern unixmessage_handler_func_t s6_fdholder_retrieve_cb ; +extern int s6_fdholder_retrieve_maybe_delete (s6_fdholder_t *, char const *, int, tain_t const *, tain_t *) ; +#define s6_fdholder_retrieve_maybe_delete_g (a, id, h, deadline) s6_fdholder_retrieve(a, id, h, (deadline), &STAMP) +#define s6_fdholder_retrieve(a, id, deadline, stamp) s6_fdholder_retrieve_maybe_delete(a, id, 0, deadline, stamp) +#define s6_fdholder_retrieve_g (a, id, deadline) s6_fdholder_retrieve(a, id, (deadline), &STAMP) +#define s6_fdholder_retrieve_delete(a, id, deadline, stamp) s6_fdholder_retrieve_maybe_delete(a, id, 1, deadline, stamp) +#define s6_fdholder_retrieve_delete_g (a, id, deadline) s6_fdholder_retrieve(a, id, (deadline), &STAMP) + +typedef struct s6_fdholder_list_result_s s6_fdholder_list_result_t, *s6_fdholder_list_result_t_ref ; +struct s6_fdholder_list_result_s +{ + stralloc *sa ; + unsigned int n ; + unsigned char err ; +} ; + +extern int s6_fdholder_list_async (s6_fdholder_t *) ; +extern unixmessage_handler_func_t s6_fdholder_list_cb ; +extern int s6_fdholder_list (s6_fdholder_t *, stralloc *, tain_t const *, tain_t *) ; +#define s6_fdholder_list_g(a, sa, deadline) s6_fdholder_list(a, sa, (deadline), &STAMP) + + + /* Dumps */ + +typedef struct s6_fdholder_fd_s s6_fdholder_fd_t, *s6_fdholder_fd_t_ref ; +struct s6_fdholder_fd_s +{ + char id[S6_FDHOLDER_ID_SIZE + 1] ; + int fd ; + tain_t limit ; +} ; + +extern int s6_fdholder_getdump (s6_fdholder_t *, genalloc *, tain_t const *, tain_t *) ; +#define s6_fdholder_getdump_g(a, g, deadline) s6_fdholder_getdump_g(a, g, (deadline), &STAMP) +extern int s6_fdholder_setdump (s6_fdholder_t *, s6_fdholder_fd_t const *, unsigned int, tain_t const *, tain_t *) ; +#define s6_fdholder_setdump_g(a, list, n, deadline) s6_fdholder_setdump(a, list, n, (deadline), &STAMP) + +#endif diff --git a/src/include/s6/s6-supervise.h b/src/include/s6/s6-supervise.h index c8d72d7..2e9a3fa 100644 --- a/src/include/s6/s6-supervise.h +++ b/src/include/s6/s6-supervise.h @@ -10,7 +10,7 @@ #define S6_SVSCAN_CTLDIR ".s6-svscan" #define S6_SVSTATUS_FILENAME S6_SUPERVISE_CTLDIR "/status" #define S6_SUPERVISE_READY_FILENAME S6_SUPERVISE_CTLDIR "/ready" -#define S6_SVSTATUS_SIZE 18 +#define S6_SVSTATUS_SIZE 26 extern int s6_svc_write (char const *, char const *, unsigned int) ; extern int s6_svc_main (int, char const *const *, char const *, char const *, char const *) ; @@ -24,14 +24,23 @@ struct s6_svstatus_s unsigned int flagwantup : 1 ; unsigned int flagpaused : 1 ; unsigned int flagfinishing : 1 ; + unsigned int wstat ; } ; -#define S6_SVSTATUS_ZERO { .stamp = TAIN_ZERO, .pid = 0, .flagwant = 0, .flagwantup = 0, .flagpaused = 0, .flagfinishing = 0 } - +#define S6_SVSTATUS_ZERO \ +{ \ + .stamp = TAIN_ZERO, \ + .pid = 0, \ + .flagwant = 0, \ + .flagwantup = 0, \ + .flagpaused = 0, \ + .flagfinishing = 0, \ + .wstat = 0 \ +} extern void s6_svstatus_pack (char *, s6_svstatus_t const *) ; -extern void s6_svstatus_unpack (char const *, s6_svstatus_t_ref) ; -extern int s6_svstatus_read (char const *, s6_svstatus_t_ref) ; +extern void s6_svstatus_unpack (char const *, s6_svstatus_t *) ; +extern int s6_svstatus_read (char const *, s6_svstatus_t *) ; extern int s6_svstatus_write (char const *, s6_svstatus_t const *) ; /* These functions leak a fd, that's intended */ diff --git a/src/libs6/deps-lib/s6 b/src/libs6/deps-lib/s6 index 579d844..35a3296 100644 --- a/src/libs6/deps-lib/s6 +++ b/src/libs6/deps-lib/s6 @@ -13,6 +13,7 @@ ftrigw_clean.o ftrigw_fifodir_make.o ftrigw_notify.o ftrigw_notifyb.o +ftrigw_notifyb_nosig.o s6_accessrules_backend_cdb.o s6_accessrules_backend_fs.o s6_accessrules_keycheck_ip4.o @@ -23,7 +24,6 @@ s6_accessrules_uidgid_cdb.o s6_accessrules_uidgid_fs.o s6_supervise_lock.o s6_supervise_lock_mode.o -s6_svc_main.o s6_svc_write.o s6_svstatus_pack.o s6_svstatus_read.o @@ -39,3 +39,15 @@ s6lock_update.o s6lock_wait_and.o s6lock_wait_or.o s6lock_zero.o +s6_fdholder_delete.o +s6_fdholder_delete_async.o +s6_fdholder_getdump.o +s6_fdholder_list.o +s6_fdholder_list_async.o +s6_fdholder_list_cb.o +s6_fdholder_retrieve.o +s6_fdholder_retrieve_async.o +s6_fdholder_retrieve_cb.o +s6_fdholder_setdump.o +s6_fdholder_store.o +s6_fdholder_store_async.o diff --git a/src/libs6/ftrigw_notifyb.c b/src/libs6/ftrigw_notifyb.c index 345a3cc..ddd1116 100644 --- a/src/libs6/ftrigw_notifyb.c +++ b/src/libs6/ftrigw_notifyb.c @@ -1,67 +1,20 @@ /* ISC license. */ -#include <unistd.h> #include <errno.h> #include <signal.h> -#include <skalibs/direntry.h> -#include <skalibs/allreadwrite.h> -#include <skalibs/bytestr.h> #include <skalibs/sig.h> -#include <skalibs/djbunix.h> -#include "ftrig1.h" #include <s6/ftrigw.h> int ftrigw_notifyb (char const *path, char const *s, unsigned int len) { - unsigned int i = 0 ; struct skasigaction old ; - DIR *dir = opendir(path) ; - if (!dir) return -1 ; + int r ; if (skasigaction(SIGPIPE, &SKASIG_IGN, &old) < 0) return -1 ; - { - unsigned int pathlen = str_len(path) ; - char tmp[pathlen + FTRIG1_PREFIXLEN + 45] ; - byte_copy(tmp, pathlen, path) ; - tmp[pathlen] = '/' ; tmp[pathlen + FTRIG1_PREFIXLEN + 44] = 0 ; - for (;;) - { - direntry *d ; - int fd ; - errno = 0 ; - d = readdir(dir) ; - if (!d) break ; - if (str_diffn(d->d_name, FTRIG1_PREFIX, FTRIG1_PREFIXLEN)) continue ; - if (str_len(d->d_name) != FTRIG1_PREFIXLEN + 43) continue ; - byte_copy(tmp + pathlen + 1, FTRIG1_PREFIXLEN + 43, d->d_name) ; - fd = open_write(tmp) ; - if (fd == -1) - { - if (errno == ENXIO) unlink(tmp) ; - } - else - { - register int r = fd_write(fd, s, len) ; - if ((r < 0) || (unsigned int)r < len) - { - if (errno == EPIPE) unlink(tmp) ; - /* what to do if EGAIN ? full fifo -> fix the reader ! - There's a race condition in extreme cases though ; - but it's still better to be nonblocking - the writer - shouldn't get in trouble because of a bad reader. */ - fd_close(fd) ; - } - else - { - fd_close(fd) ; - i++ ; - } - } - } - } + r = ftrigw_notifyb_nosig(path, s, len) ; { int e = errno ; skasigaction(SIGPIPE, &old, 0) ; - dir_close(dir) ; - return e ? (errno = e, -1) : (int)i ; + errno = e ; } + return r ; } diff --git a/src/libs6/ftrigw_notifyb_nosig.c b/src/libs6/ftrigw_notifyb_nosig.c new file mode 100644 index 0000000..0d7b565 --- /dev/null +++ b/src/libs6/ftrigw_notifyb_nosig.c @@ -0,0 +1,62 @@ +/* ISC license. */ + +#include <unistd.h> +#include <errno.h> +#include <skalibs/direntry.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/bytestr.h> +#include <skalibs/djbunix.h> +#include "ftrig1.h" +#include <s6/ftrigw.h> + +int ftrigw_notifyb_nosig (char const *path, char const *s, unsigned int len) +{ + unsigned int i = 0 ; + DIR *dir = opendir(path) ; + if (!dir) return -1 ; + { + unsigned int pathlen = str_len(path) ; + char tmp[pathlen + FTRIG1_PREFIXLEN + 45] ; + byte_copy(tmp, pathlen, path) ; + tmp[pathlen] = '/' ; tmp[pathlen + FTRIG1_PREFIXLEN + 44] = 0 ; + for (;;) + { + direntry *d ; + int fd ; + errno = 0 ; + d = readdir(dir) ; + if (!d) break ; + if (str_diffn(d->d_name, FTRIG1_PREFIX, FTRIG1_PREFIXLEN)) continue ; + if (str_len(d->d_name) != FTRIG1_PREFIXLEN + 43) continue ; + byte_copy(tmp + pathlen + 1, FTRIG1_PREFIXLEN + 43, d->d_name) ; + fd = open_write(tmp) ; + if (fd == -1) + { + if (errno == ENXIO) unlink(tmp) ; + } + else + { + register int r = fd_write(fd, s, len) ; + if ((r < 0) || (unsigned int)r < len) + { + if (errno == EPIPE) unlink(tmp) ; + /* what to do if EGAIN ? full fifo -> fix the reader ! + There's a race condition in extreme cases though ; + but it's still better to be nonblocking - the writer + shouldn't get in trouble because of a bad reader. */ + fd_close(fd) ; + } + else + { + fd_close(fd) ; + i++ ; + } + } + } + } + { + int e = errno ; + dir_close(dir) ; + return e ? (errno = e, -1) : (int)i ; + } +} diff --git a/src/libs6/s6_fdholder_delete.c b/src/libs6/s6_fdholder_delete.c new file mode 100644 index 0000000..0432421 --- /dev/null +++ b/src/libs6/s6_fdholder_delete.c @@ -0,0 +1,21 @@ + /* ISC license. */ + +#include <errno.h> +#include <skalibs/error.h> +#include <skalibs/tai.h> +#include <skalibs/unixmessage.h> +#include <s6/s6-fdholder.h> + +int s6_fdholder_delete (s6_fdholder_t *a, char const *id, tain_t const *deadline, tain_t *stamp) +{ + unixmessage_t m ; + if (!s6_fdholder_delete_async(a, id)) return 0 ; + if (!unixmessage_sender_timed_flush(&a->connection.out, deadline, stamp)) return 0 ; + if (!unixmessage_timed_receive(&a->connection.in, &m, deadline, stamp)) return 0 ; + if (m.len != 1 || m.nfds) + { + unixmessage_drop(&m) ; + return (errno = EPROTO, 0) ; + } + return m.s[0] ? (errno = m.s[0], 0) : 1 ; +} diff --git a/src/libs6/s6_fdholder_delete_async.c b/src/libs6/s6_fdholder_delete_async.c new file mode 100644 index 0000000..6452efa --- /dev/null +++ b/src/libs6/s6_fdholder_delete_async.c @@ -0,0 +1,18 @@ + /* ISC license. */ + +#include <errno.h> +#include <skalibs/bytestr.h> +#include <skalibs/siovec.h> +#include <skalibs/unixmessage.h> +#include <s6/s6-fdholder.h> + +int s6_fdholder_delete_async (s6_fdholder_t *a, char const *id) +{ + unsigned int idlen = str_len(id) ; + char pack[2] = "D" ; + siovec_t v[2] = { { .s = pack, .len = 2 }, { .s = (char *)id, .len = idlen + 1 } } ; + unixmessage_v_t m = { .v = v, .vlen = 2, .fds = 0, .nfds = 0 } ; + if (idlen > S6_FDHOLDER_ID_SIZE) return (errno = ENAMETOOLONG, 0) ; + pack[1] = (unsigned char)idlen ; + return unixmessage_putv(&a->connection.out, &m) ; +} diff --git a/src/libs6/s6_fdholder_getdump.c b/src/libs6/s6_fdholder_getdump.c new file mode 100644 index 0000000..3fce3a7 --- /dev/null +++ b/src/libs6/s6_fdholder_getdump.c @@ -0,0 +1,73 @@ + /* ISC license. */ + +#include <errno.h> +#include <skalibs/uint32.h> +#include <skalibs/error.h> +#include <skalibs/bytestr.h> +#include <skalibs/tai.h> +#include <skalibs/genalloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/unixmessage.h> +#include <s6/s6-fdholder.h> + +int s6_fdholder_getdump (s6_fdholder_t *a, genalloc *g, tain_t const *deadline, tain_t *stamp) +{ + unixmessage_t m = { .s = "?", .len = 1, .fds = 0, .nfds = 0 } ; + uint32 ntot, n ; + unsigned int oldlen = genalloc_len(s6_fdholder_fd_t, g) ; + unsigned int i = 0 ; + int ok ; + if (!unixmessage_put(&a->connection.out, &m)) return 0 ; + if (!unixmessage_sender_timed_flush(&a->connection.out, deadline, stamp)) return 0 ; + if (!unixmessage_timed_receive(&a->connection.in, &m, deadline, stamp)) return 0 ; + if (!m.len || m.nfds) return (errno = EPROTO, 0) ; + if (m.s[0]) return (errno = m.s[0], 0) ; + if (m.len != 9) return (errno = EPROTO, 0) ; + uint32_unpack_big(m.s + 1, &n) ; + uint32_unpack_big(m.s + 5, &ntot) ; + if (!ntot) return 1 ; + if (n != 1 + (ntot-1) / UNIXMESSAGE_MAXFDS) return (errno = EPROTO, 0) ; + ok = genalloc_readyplus(s6_fdholder_fd_t, g, ntot) ; + + for (; i < n ; i++) + { + if (!unixmessage_timed_receive(&a->connection.in, &m, deadline, stamp)) goto err ; + if (genalloc_len(s6_fdholder_fd_t, g) + m.nfds > ntot) goto droperr ; + if (ok) + { + s6_fdholder_fd_t *tab = genalloc_s(s6_fdholder_fd_t, g) + genalloc_len(s6_fdholder_fd_t, g) ; + unsigned int i = 0 ; + for (; i < m.nfds ; i++) + { + unsigned char thislen ; + if (m.len < TAIN_PACK + 3) goto droperr ; + tain_unpack(m.s, &tab[i].limit) ; + m.s += TAIN_PACK ; m.len -= TAIN_PACK + 1 ; + thislen = *m.s++ ; + if (thislen > m.len - 1 || thislen > S6_FDHOLDER_ID_SIZE || m.s[thislen]) goto droperr ; + byte_copy(tab[i].id, thislen, m.s) ; + byte_zero(tab[i].id + thislen, S6_FDHOLDER_ID_SIZE + 1 - thislen) ; + m.s += (unsigned int)thislen + 1 ; m.len -= (unsigned int)thislen + 1 ; + tab[i].fd = m.fds[i] ; + } + genalloc_setlen(s6_fdholder_fd_t, g, genalloc_len(s6_fdholder_fd_t, g) + m.nfds) ; + } + else unixmessage_drop(&m) ; + } + + if (!ok) return (errno = ENOMEM, 0) ; + return 1 ; + + droperr: + unixmessage_drop(&m) ; + errno = EPROTO ; + err: + { + int e = errno ; + i = genalloc_len(s6_fdholder_fd_t, g) ; + while (i-- > oldlen) fd_close(genalloc_s(s6_fdholder_fd_t, g)[i].fd) ; + genalloc_setlen(s6_fdholder_fd_t, g, oldlen) ; + errno = e ; + } + return 0 ; +} diff --git a/src/libs6/s6_fdholder_list.c b/src/libs6/s6_fdholder_list.c new file mode 100644 index 0000000..4f804aa --- /dev/null +++ b/src/libs6/s6_fdholder_list.c @@ -0,0 +1,19 @@ + /* ISC license. */ + +#include <errno.h> +#include <skalibs/error.h> +#include <skalibs/tai.h> +#include <skalibs/unixmessage.h> +#include <s6/s6-fdholder.h> + +int s6_fdholder_list (s6_fdholder_t *a, stralloc *sa, tain_t const *deadline, tain_t *stamp) +{ + s6_fdholder_list_result_t res = { .sa = sa } ; + unixmessage_t m ; + if (!s6_fdholder_list_async(a)) return -1 ; + if (!unixmessage_sender_timed_flush(&a->connection.out, deadline, stamp)) return -1 ; + if (!unixmessage_timed_receive(&a->connection.in, &m, deadline, stamp)) return -1 ; + if (!s6_fdholder_list_cb(&m, &res)) return -1 ; + if (res.err) return (errno = res.err, -1) ; + return (int)res.n ; +} diff --git a/src/libs6/s6_fdholder_list_async.c b/src/libs6/s6_fdholder_list_async.c new file mode 100644 index 0000000..fc62ff8 --- /dev/null +++ b/src/libs6/s6_fdholder_list_async.c @@ -0,0 +1,11 @@ + /* ISC license. */ + +#include <errno.h> +#include <skalibs/unixmessage.h> +#include <s6/s6-fdholder.h> + +int s6_fdholder_list_async (s6_fdholder_t *a) +{ + unixmessage_t m = { .s = "L", .len = 1, .fds = 0, .nfds = 0 } ; + return unixmessage_put(&a->connection.out, &m) ; +} diff --git a/src/libs6/s6_fdholder_list_cb.c b/src/libs6/s6_fdholder_list_cb.c new file mode 100644 index 0000000..bfdee50 --- /dev/null +++ b/src/libs6/s6_fdholder_list_cb.c @@ -0,0 +1,31 @@ + /* ISC license. */ + +#include <errno.h> +#include <skalibs/uint32.h> +#include <skalibs/error.h> +#include <skalibs/stralloc.h> +#include <skalibs/unixmessage.h> +#include <s6/s6-fdholder.h> + +int s6_fdholder_list_cb (unixmessage_t const *m, void *p) +{ + uint32 n ; + register s6_fdholder_list_result_t *res = p ; + if (m->nfds) goto droperr ; + if (m->len < 5) goto err ; + if (m->s[0]) + { + res->err = m->s[0] ; + return 1 ; + } + uint32_unpack_big(m->s + 1, &n) ; + if (!stralloc_catb(res->sa, m->s + 5, m->len - 5)) return 0 ; + res->n = n ; + res->err = 0 ; + return 1 ; + + droperr: + unixmessage_drop(m) ; + err: + return (errno = EPROTO, 0) ; +} diff --git a/src/libs6/s6_fdholder_retrieve.c b/src/libs6/s6_fdholder_retrieve.c new file mode 100644 index 0000000..e2888a9 --- /dev/null +++ b/src/libs6/s6_fdholder_retrieve.c @@ -0,0 +1,18 @@ + /* ISC license. */ + +#include <errno.h> +#include <skalibs/tai.h> +#include <skalibs/unixmessage.h> +#include <s6/s6-fdholder.h> + +int s6_fdholder_retrieve_maybe_delete (s6_fdholder_t *a, char const *id, int dodelete, tain_t const *deadline, tain_t *stamp) +{ + unixmessage_t m ; + s6_fdholder_retrieve_result_t res ; + if (!s6_fdholder_retrieve_maybe_delete_async(a, id, dodelete)) return -1 ; + if (!unixmessage_sender_timed_flush(&a->connection.out, deadline, stamp)) return -1 ; + if (!unixmessage_timed_receive(&a->connection.in, &m, deadline, stamp)) return -1 ; + if (!s6_fdholder_retrieve_cb(&m, &res)) return -1 ; + if (res.err) return (errno = res.err, -1) ; + return res.fd ; +} diff --git a/src/libs6/s6_fdholder_retrieve_async.c b/src/libs6/s6_fdholder_retrieve_async.c new file mode 100644 index 0000000..bc7077c --- /dev/null +++ b/src/libs6/s6_fdholder_retrieve_async.c @@ -0,0 +1,20 @@ + /* ISC license. */ + +#include <errno.h> +#include <skalibs/bytestr.h> +#include <skalibs/tai.h> +#include <skalibs/siovec.h> +#include <skalibs/unixmessage.h> +#include <s6/s6-fdholder.h> + +int s6_fdholder_retrieve_maybe_delete_async (s6_fdholder_t *a, char const *id, int dodelete) +{ + unsigned int idlen = str_len(id) ; + char pack[3] = "R" ; + siovec_t v[2] = { { .s = pack, .len = 3 }, { .s = (char *)id, .len = idlen + 1 } } ; + unixmessage_v_t m = { .v = v, .vlen = 2, .fds = 0, .nfds = 0 } ; + if (idlen > S6_FDHOLDER_ID_SIZE) return (errno = ENAMETOOLONG, 0) ; + pack[1] = !!dodelete ; + pack[2] = (unsigned char)idlen ; + return unixmessage_putv(&a->connection.out, &m) ; +} diff --git a/src/libs6/s6_fdholder_retrieve_cb.c b/src/libs6/s6_fdholder_retrieve_cb.c new file mode 100644 index 0000000..9197b22 --- /dev/null +++ b/src/libs6/s6_fdholder_retrieve_cb.c @@ -0,0 +1,26 @@ + /* ISC license. */ + +#include <errno.h> +#include <skalibs/error.h> +#include <skalibs/unixmessage.h> +#include <s6/s6-fdholder.h> + +int s6_fdholder_retrieve_cb (unixmessage_t const *m, void *p) +{ + register s6_fdholder_retrieve_result_t *res = p ; + if (m->len != 1) goto err ; + if (m->s[0]) + { + if (m->nfds) goto err ; + res->err = m->s[0] ; + return 1 ; + } + if (m->nfds != 1) goto err ; + res->fd = m->fds[0] ; + res->err = 0 ; + return 1 ; + + err: + unixmessage_drop(m) ; + return (errno = EPROTO, 0) ; +} diff --git a/src/libs6/s6_fdholder_setdump.c b/src/libs6/s6_fdholder_setdump.c new file mode 100644 index 0000000..e5825dc --- /dev/null +++ b/src/libs6/s6_fdholder_setdump.c @@ -0,0 +1,74 @@ + /* ISC license. */ + +#include <errno.h> +#include <skalibs/uint32.h> +#include <skalibs/bytestr.h> +#include <skalibs/error.h> +#include <skalibs/tai.h> +#include <skalibs/siovec.h> +#include <skalibs/unixmessage.h> +#include <s6/s6-fdholder.h> + +int s6_fdholder_setdump (s6_fdholder_t *a, s6_fdholder_fd_t const *list, unsigned int ntot, tain_t const *deadline, tain_t *stamp) +{ + uint32 trips ; + if (!ntot) return 1 ; + unsigned int i = 0 ; + for (; i < ntot ; i++) + { + unsigned int zpos = byte_chr(list[i].id, S6_FDHOLDER_ID_SIZE + 1, 0) ; + if (!zpos || zpos >= S6_FDHOLDER_ID_SIZE + 1) return (errno = EINVAL, 0) ; + } + { + char pack[5] = "!" ; + unixmessage_t m = { .s = pack, .len = 5, .fds = 0, .nfds = 0 } ; + uint32_pack_big(pack+1, ntot) ; + if (!unixmessage_put(&a->connection.out, &m)) return 0 ; + if (!unixmessage_sender_timed_flush(&a->connection.out, deadline, stamp)) return 0 ; + if (!unixmessage_timed_receive(&a->connection.in, &m, deadline, stamp)) return 0 ; + 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) ; + if (trips != 1 + (ntot-1) / UNIXMESSAGE_MAXFDS) return (errno = EPROTO, 0) ; + } + for (i = 0 ; i < trips ; i++, ntot -= UNIXMESSAGE_MAXFDS) + { + { + unsigned int n = ntot > UNIXMESSAGE_MAXFDS ? UNIXMESSAGE_MAXFDS : ntot ; + unsigned int j = 0 ; + siovec_t v[1 + (n<<1)] ; + int fds[n] ; + unixmessage_v_t m = { .v = v, .vlen = 1 + (n<<1), .fds = fds, .nfds = n } ; + char pack[n * (TAIN_PACK+1)] ; + v[0].s = "." ; v[0].len = 1 ; + for (; j < n ; j++, list++, ntot--) + { + unsigned int len = str_len(list->id) ; + 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 ; + v[2 + (j<<1)].s = (char *)list->id ; + v[2 + (j<<1)].len = len ; + fds[j] = list->fd ; + } + if (!unixmessage_putv(&a->connection.out, &m)) return 0 ; + } + if (!unixmessage_sender_timed_flush(&a->connection.out, deadline, stamp)) return 0 ; + { + unixmessage_t m ; + if (!unixmessage_timed_receive(&a->connection.in, &m, deadline, stamp)) return 0 ; + if (m.len != 1 || m.nfds) + { + unixmessage_drop(&m) ; + return (errno = EPROTO, 0) ; + } + if (!error_isagain(m.s[0]) && i < trips-1) + return errno = m.s[0] ? m.s[0] : EPROTO, 0 ; + if (i == trips - 1 && m.s[0]) + return errno = error_isagain(m.s[0]) ? EPROTO : m.s[0], 0 ; + } + } + return 1 ; +} diff --git a/src/libs6/s6_fdholder_store.c b/src/libs6/s6_fdholder_store.c new file mode 100644 index 0000000..4241d8d --- /dev/null +++ b/src/libs6/s6_fdholder_store.c @@ -0,0 +1,21 @@ + /* ISC license. */ + +#include <errno.h> +#include <skalibs/error.h> +#include <skalibs/tai.h> +#include <skalibs/unixmessage.h> +#include <s6/s6-fdholder.h> + +int s6_fdholder_store (s6_fdholder_t *a, int fd, char const *id, tain_t const *limit, tain_t const *deadline, tain_t *stamp) +{ + unixmessage_t m ; + if (!s6_fdholder_store_async(a, fd, id, limit)) return 0 ; + if (!unixmessage_sender_timed_flush(&a->connection.out, deadline, stamp)) return 0 ; + if (!unixmessage_timed_receive(&a->connection.in, &m, deadline, stamp)) return 0 ; + if (m.len != 1 || m.nfds) + { + unixmessage_drop(&m) ; + return (errno = EPROTO, 0) ; + } + return m.s[0] ? (errno = m.s[0], 0) : 1 ; +} diff --git a/src/libs6/s6_fdholder_store_async.c b/src/libs6/s6_fdholder_store_async.c new file mode 100644 index 0000000..dfaab05 --- /dev/null +++ b/src/libs6/s6_fdholder_store_async.c @@ -0,0 +1,20 @@ + /* ISC license. */ + +#include <errno.h> +#include <skalibs/bytestr.h> +#include <skalibs/tai.h> +#include <skalibs/siovec.h> +#include <skalibs/unixmessage.h> +#include <s6/s6-fdholder.h> + +int s6_fdholder_store_async (s6_fdholder_t *a, int fd, char const *id, tain_t const *limit) +{ + unsigned int idlen = str_len(id) ; + char pack[2 + TAIN_PACK] = "S" ; + siovec_t v[2] = { { .s = pack, .len = 2 + TAIN_PACK }, { .s = id, .len = idlen + 1 } } ; + unixmessage_v_t m = { .v = v, .vlen = 2, .fds = &fd, .nfds = 1 } ; + if (idlen > S6_FDHOLDER_ID_SIZE) return (errno = ENAMETOOLONG, 0) ; + pack[1] = (unsigned char)idlen ; + tain_pack(pack + 2, limit) ; + return unixmessage_putv(&a->connection.out, &m) ; +} diff --git a/src/libs6/s6_svc_main.c b/src/libs6/s6_svc_main.c deleted file mode 100644 index ead74cd..0000000 --- a/src/libs6/s6_svc_main.c +++ /dev/null @@ -1,39 +0,0 @@ -/* ISC license. */ - -#include <skalibs/bytestr.h> -#include <skalibs/sgetopt.h> -#include <skalibs/strerr2.h> -#include <s6/s6-supervise.h> - -#define DATASIZE 256 - -int s6_svc_main (int argc, char const *const *argv, char const *optstring, char const *usage, char const *controldir) -{ - char data[DATASIZE] ; - unsigned int datalen = 0 ; - register int r ; - for (;;) - { - register int opt = subgetopt(argc, argv, optstring) ; - if (opt == -1) break ; - if (opt == '?') strerr_dieusage(100, usage) ; - if (datalen >= DATASIZE) strerr_dief1x(100, "too many commands") ; - data[datalen++] = opt ; - } - argc -= subgetopt_here.ind ; argv += subgetopt_here.ind ; - if (!argc) strerr_dieusage(100, usage) ; - - { - unsigned int arglen = str_len(*argv) ; - unsigned int cdirlen = str_len(controldir) ; - char tmp[arglen + cdirlen + 10] ; - byte_copy(tmp, arglen, *argv) ; - tmp[arglen] = '/' ; - byte_copy(tmp + arglen + 1, cdirlen, controldir) ; - byte_copy(tmp + arglen + 1 + cdirlen, 9, "/control") ; - r = s6_svc_write(tmp, data, datalen) ; - } - if (r < 0) strerr_diefu2sys(111, "control ", *argv) ; - else if (!r) strerr_diefu3x(100, "control ", *argv, ": supervisor not listening") ; - return 0 ; -} diff --git a/src/libs6/s6_svstatus_pack.c b/src/libs6/s6_svstatus_pack.c index 2d5baf6..2b1f102 100644 --- a/src/libs6/s6_svstatus_pack.c +++ b/src/libs6/s6_svstatus_pack.c @@ -1,6 +1,7 @@ /* ISC license. */ #include <skalibs/uint32.h> +#include <skalibs/uint64.h> #include <skalibs/tai.h> #include <s6/s6-supervise.h> @@ -10,4 +11,5 @@ void s6_svstatus_pack (char *pack, s6_svstatus_t const *sv) uint32_pack(pack + 12, (uint32)sv->pid) ; pack[16] = sv->flagpaused | (sv->flagfinishing << 1) ; pack[17] = sv->flagwant ? sv->flagwantup ? 'u' : 'd' : 0 ; + uint64_pack(pack + 18, (uint64)sv->wstat) ; } diff --git a/src/libs6/s6_svstatus_read.c b/src/libs6/s6_svstatus_read.c index 32ec660..59a31a5 100644 --- a/src/libs6/s6_svstatus_read.c +++ b/src/libs6/s6_svstatus_read.c @@ -4,7 +4,7 @@ #include <skalibs/djbunix.h> #include <s6/s6-supervise.h> -int s6_svstatus_read (char const *dir, s6_svstatus_t_ref status) +int s6_svstatus_read (char const *dir, s6_svstatus_t *status) { unsigned int n = str_len(dir) ; char pack[S6_SVSTATUS_SIZE] ; diff --git a/src/libs6/s6_svstatus_unpack.c b/src/libs6/s6_svstatus_unpack.c index cce6989..3fbc205 100644 --- a/src/libs6/s6_svstatus_unpack.c +++ b/src/libs6/s6_svstatus_unpack.c @@ -1,15 +1,19 @@ /* ISC license. */ #include <skalibs/uint32.h> +#include <skalibs/uint64.h> #include <skalibs/tai.h> #include <s6/s6-supervise.h> -void s6_svstatus_unpack (char const *pack, s6_svstatus_t_ref sv) +void s6_svstatus_unpack (char const *pack, s6_svstatus_t *sv) { uint32 pid ; + uint64 wstat ; tain_unpack(pack, &sv->stamp) ; uint32_unpack(pack + 12, &pid) ; - sv->pid = (int)pid ; + sv->pid = (unsigned int)pid ; + uint64_unpack(pack + 18, &wstat) ; + sv->wstat = (unsigned int)wstat ; sv->flagpaused = pack[16] & 1 ; sv->flagfinishing = (pack[16] >> 1) & 1 ; switch (pack[17]) diff --git a/src/supervision/s6-supervise.c b/src/supervision/s6-supervise.c index 65cbd9d..bb4e761 100644 --- a/src/supervision/s6-supervise.c +++ b/src/supervision/s6-supervise.c @@ -45,7 +45,7 @@ typedef void action_t (void) ; typedef action_t *action_t_ref ; static tain_t deadline ; -static s6_svstatus_t status = { .stamp = TAIN_ZERO, .pid = 0, .flagwant = 1, .flagwantup = 1, .flagpaused = 0, .flagfinishing = 0 } ; +static s6_svstatus_t status = { .stamp = TAIN_ZERO, .pid = 0, .flagwant = 1, .flagwantup = 1, .flagpaused = 0, .flagfinishing = 0, .wstat = 0 } ; static state_t state = DOWN ; static int flagsetsid = 1 ; static int cont = 1 ; @@ -166,7 +166,7 @@ static void trystart (void) if (flagsetsid) setsid() ; execve("./run", (char *const *)cargv, (char *const *)environ) ; fd_write(p[1], "", 1) ; - strerr_dieexec(111, "run") ; + strerr_dieexec(127, "run") ; } fd_close(p[1]) ; { @@ -194,7 +194,7 @@ static void trystart (void) status.pid = pid ; tain_copynow(&status.stamp) ; announce() ; - ftrigw_notify(S6_SUPERVISE_EVENTDIR, 'u') ; + ftrigw_notifyb_nosig(S6_SUPERVISE_EVENTDIR, "u", 1) ; } static void downtimeout (void) @@ -230,7 +230,7 @@ static void down_d (void) announce() ; } -static void tryfinish (int wstat, int islast) +static inline void tryfinish (int islast) { register pid_t pid = fork() ; if (pid < 0) @@ -238,7 +238,6 @@ static void tryfinish (int wstat, int islast) strerr_warnwu2sys("fork for ", "./finish") ; if (islast) bail() ; state = DOWN ; - status.pid = 0 ; settimeout(1) ; return ; } @@ -248,16 +247,15 @@ static void tryfinish (int wstat, int islast) char fmt1[UINT_FMT] ; char *cargv[4] = { "finish", fmt0, fmt1, 0 } ; selfpipe_finish() ; - fmt0[uint_fmt(fmt0, WIFSIGNALED(wstat) ? 255 : WEXITSTATUS(wstat))] = 0 ; - fmt1[uint_fmt(fmt1, WTERMSIG(wstat))] = 0 ; + fmt0[uint_fmt(fmt0, WIFSIGNALED(status.wstat) ? 256 : WEXITSTATUS(status.wstat))] = 0 ; + fmt1[uint_fmt(fmt1, WTERMSIG(status.wstat))] = 0 ; if (flagsetsid) setsid() ; execve("./finish", cargv, (char *const *)environ) ; - _exit(111) ; + _exit(127) ; } status.pid = pid ; status.flagfinishing = 1 ; state = islast ? LASTFINISH : FINISH ; - settimeout(5) ; } static void uptimeout (void) @@ -268,18 +266,20 @@ static void uptimeout (void) static void uplastup_z (int islast) { - int wstat = status.pid ; + status.wstat = status.pid ; status.pid = 0 ; tain_copynow(&status.stamp) ; + tryfinish(islast) ; announce() ; - ftrigw_notify(S6_SUPERVISE_EVENTDIR, 'd') ; + ftrigw_notifyb_nosig(S6_SUPERVISE_EVENTDIR, "d", 1) ; if (unlink(S6_SUPERVISE_READY_FILENAME) < 0 && errno != ENOENT) strerr_warnwu1sys("unlink " S6_SUPERVISE_READY_FILENAME) ; - tryfinish(wstat, islast) ; + settimeout(5) ; } static void up_z (void) { + status.flagpaused = 0 ; uplastup_z(0) ; } @@ -401,7 +401,7 @@ static void handle_signals (void) if (errno != ECHILD) strerr_diefu1sys(111, "wait_pid_nohang") ; else break ; else if (!r) break ; - status.pid = wstat ; + status.pid = wstat ; /* don't overwrite status.wstat if it's ./finish */ (*actions[state][V_CHLD])() ; } break ; @@ -490,7 +490,7 @@ int main (int argc, char const *const *argv) settimeout(0) ; tain_copynow(&status.stamp) ; announce() ; - ftrigw_notify(S6_SUPERVISE_EVENTDIR, 's') ; + ftrigw_notifyb_nosig(S6_SUPERVISE_EVENTDIR, "s", 1) ; while (cont) { @@ -506,7 +506,7 @@ int main (int argc, char const *const *argv) } } - ftrigw_notify(S6_SUPERVISE_EVENTDIR, 'x') ; + ftrigw_notifyb_nosig(S6_SUPERVISE_EVENTDIR, "x", 1) ; } return 0 ; } diff --git a/src/supervision/s6-svscan.c b/src/supervision/s6-svscan.c index 8b0f82e..e07ff35 100644 --- a/src/supervision/s6-svscan.c +++ b/src/supervision/s6-svscan.c @@ -29,7 +29,7 @@ #define DIR_RETRY_TIMEOUT 3 #define CHECK_RETRY_TIMEOUT 4 -struct svinfo +struct svinfo_s { dev_t dev ; ino_t ino ; @@ -39,9 +39,8 @@ struct svinfo unsigned int flagactive : 1 ; unsigned int flaglog : 1 ; } ; -#define SVINFO_ZERO { -1, -1, { TAIN_ZERO, TAIN_ZERO }, { 0, 0 }, { -1, -1 }, 0, 0, 0 } ; -static struct svinfo *services ; +static struct svinfo_s *services ; static unsigned int max = 500 ; static unsigned int n = 0 ; static tain_t deadline, defaulttimeout ; @@ -452,7 +451,7 @@ int main (int argc, char const *const *argv) { - struct svinfo blob[max] ; /* careful with that stack, Eugene */ + struct svinfo_s blob[max] ; /* careful with that stack, Eugene */ services = blob ; tain_now_g() ; diff --git a/src/supervision/s6-svscanctl.c b/src/supervision/s6-svscanctl.c index 48e6420..6529e9c 100644 --- a/src/supervision/s6-svscanctl.c +++ b/src/supervision/s6-svscanctl.c @@ -1,12 +1,65 @@ /* ISC license. */ +#include <skalibs/bytestr.h> +#include <skalibs/sgetopt.h> #include <skalibs/strerr2.h> #include <s6/s6-supervise.h> #define USAGE "s6-svscanctl [ -phratszbnNiq0678 ] svscandir" +#define dieusage() strerr_dieusage(100, USAGE) + +#define DATASIZE 64 int main (int argc, char const *const *argv) { + char data[DATASIZE] ; + unsigned int datalen = 0 ; + int r ; PROG = "s6-svscanctl" ; - return s6_svc_main(argc, argv, "phratszbnNiq0678", USAGE, ".s6-svscan") ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "phratszbnNiq0678", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'p' : + case 'h' : + case 'r' : + case 'a' : + case 't' : + case 's' : + case 'z' : + case 'b' : + case 'n' : + case 'N' : + case 'i' : + case 'q' : + case '0' : + case '6' : + case '7' : + case '8' : + { + if (datalen >= DATASIZE) strerr_dief1x(100, "too many commands") ; + data[datalen++] = opt ; + break ; + } + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) dieusage() ; + + { + unsigned int arglen = str_len(*argv) ; + char tmp[arglen + 20] ; + byte_copy(tmp, arglen, *argv) ; + byte_copy(tmp + arglen, 20, "/.s6-svscan/control") ; + r = s6_svc_write(tmp, data, datalen) ; + } + if (r < 0) strerr_diefu2sys(111, "control ", *argv) ; + else if (!r) strerr_diefu3x(100, "control ", *argv, ": supervisor not listening") ; + return 0 ; } diff --git a/src/supervision/s6-svstat.c b/src/supervision/s6-svstat.c index c986b8d..a4facf5 100644 --- a/src/supervision/s6-svstat.c +++ b/src/supervision/s6-svstat.c @@ -1,27 +1,46 @@ /* ISC license. */ -#include <errno.h> #include <sys/types.h> #include <sys/stat.h> +#include <sys/wait.h> +#include <errno.h> #include <skalibs/uint64.h> #include <skalibs/uint.h> #include <skalibs/bytestr.h> #include <skalibs/buffer.h> #include <skalibs/strerr2.h> +#include <skalibs/sgetopt.h> +#include <skalibs/sig.h> #include <skalibs/tai.h> #include <skalibs/djbunix.h> #include <s6/s6-supervise.h> -#define USAGE "s6-svstat servicedir" +#define USAGE "s6-svstat [ -n ] servicedir" +#define dieusage() strerr_dieusage(100, USAGE) int main (int argc, char const *const *argv) { s6_svstatus_t status ; - char fmt[UINT_FMT] ; + int flagnum = 0 ; int isup, normallyup ; + char fmt[UINT_FMT] ; PROG = "s6-svstat" ; - if (argc < 2) strerr_dieusage(100, USAGE) ; - argv++ ; argc-- ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "n", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'n' : flagnum = 1 ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) dieusage() ; + if (!s6_svstatus_read(*argv, &status)) strerr_diefu2sys(111, "read status for ", *argv) ; @@ -48,7 +67,24 @@ int main (int argc, char const *const *argv) buffer_putnoflush(buffer_1small, fmt, uint_fmt(fmt, status.pid)) ; buffer_putnoflush(buffer_1small, ") ", 2) ; } - else buffer_putnoflush(buffer_1small, "down ", 5) ; + else + { + buffer_putnoflush(buffer_1small, "down (", 6) ; + if (WIFSIGNALED(status.wstat)) + { + buffer_putnoflush(buffer_1small, "signal ", 7) ; + if (flagnum) + buffer_putnoflush(buffer_1small, fmt, uint_fmt(fmt, WTERMSIG(status.wstat))) ; + else + buffer_putsnoflush(buffer_1small, sig_name(WTERMSIG(status.wstat))) ; + } + else + { + buffer_putnoflush(buffer_1small, "exitcode ", 9) ; + buffer_putnoflush(buffer_1small, fmt, uint_fmt(fmt, WEXITSTATUS(status.wstat))) ; + } + buffer_putnoflush(buffer_1small, ") ", 2) ; + } buffer_putnoflush(buffer_1small, fmt, uint64_fmt(fmt, status.stamp.sec.x)) ; buffer_putnoflush(buffer_1small," seconds", 8) ; |