diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libs6/s6_svc_main.c | 1 | ||||
-rw-r--r-- | src/pipe-tools/s6-ftrig-listen.c | 4 | ||||
-rw-r--r-- | src/supervision/deps-exe/s6-svlisten | 5 | ||||
-rw-r--r-- | src/supervision/deps-exe/s6-svlisten1 | 4 | ||||
-rw-r--r-- | src/supervision/s6-svc.c | 91 | ||||
-rw-r--r-- | src/supervision/s6-svlisten.c | 152 | ||||
-rw-r--r-- | src/supervision/s6-svlisten1.c | 121 | ||||
-rw-r--r-- | src/supervision/s6-svwait.c | 14 |
8 files changed, 378 insertions, 14 deletions
diff --git a/src/libs6/s6_svc_main.c b/src/libs6/s6_svc_main.c index 5d14904..ead74cd 100644 --- a/src/libs6/s6_svc_main.c +++ b/src/libs6/s6_svc_main.c @@ -3,7 +3,6 @@ #include <skalibs/bytestr.h> #include <skalibs/sgetopt.h> #include <skalibs/strerr2.h> -#include <skalibs/skamisc.h> #include <s6/s6-supervise.h> #define DATASIZE 256 diff --git a/src/pipe-tools/s6-ftrig-listen.c b/src/pipe-tools/s6-ftrig-listen.c index 3683dff..8f0d2cc 100644 --- a/src/pipe-tools/s6-ftrig-listen.c +++ b/src/pipe-tools/s6-ftrig-listen.c @@ -14,7 +14,7 @@ #include <execline/execline.h> #include <s6/ftrigr.h> -#define USAGE "s6-ftrig-listen [ -a | -o ] [ -t timeout ] ~fifodir1 ~regexp1 ... ; prog..." +#define USAGE "s6-ftrig-listen [ -a | -o ] [ -t timeout ] fifodir1 regexp1 ... \"\" prog..." #define dieusage() strerr_dieusage(100, USAGE) static void handle_signals (void) @@ -54,7 +54,7 @@ int main (int argc, char const **argv, char const *const *envp) if (t) tain_from_millisecs(&tto, t) ; else tto = tain_infinite_relative ; argc -= subgetopt_here.ind ; argv += subgetopt_here.ind ; } - if (argc < 2) dieusage() ; + if (argc < 4) dieusage() ; argc1 = el_semicolon(argv) ; if (!argc1 || (argc1 & 1) || (argc == argc1 + 1)) dieusage() ; if (argc1 >= argc) strerr_dief1x(100, "unterminated fifodir+regex block") ; diff --git a/src/supervision/deps-exe/s6-svlisten b/src/supervision/deps-exe/s6-svlisten new file mode 100644 index 0000000..3bbf778 --- /dev/null +++ b/src/supervision/deps-exe/s6-svlisten @@ -0,0 +1,5 @@ +${LIBS6} +-lexecline +-lskarnet +${SOCKET_LIB} +${TAINNOW_LIB} diff --git a/src/supervision/deps-exe/s6-svlisten1 b/src/supervision/deps-exe/s6-svlisten1 new file mode 100644 index 0000000..f3a3143 --- /dev/null +++ b/src/supervision/deps-exe/s6-svlisten1 @@ -0,0 +1,4 @@ +${LIBS6} +-lskarnet +${SOCKET_LIB} +${TAINNOW_LIB} diff --git a/src/supervision/s6-svc.c b/src/supervision/s6-svc.c index 699eefd..d8d2b2b 100644 --- a/src/supervision/s6-svc.c +++ b/src/supervision/s6-svc.c @@ -1,12 +1,97 @@ /* ISC license. */ +#include <skalibs/uint.h> +#include <skalibs/bytestr.h> +#include <skalibs/sgetopt.h> #include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> +#include <s6/config.h> #include <s6/s6-supervise.h> -#define USAGE "s6-svc [ -abqhkti12fFpcoduxO ] servicedir" +#define USAGE "s6-svc [ -D | -U ] [ -t timeout ] [ -abqhkti12pcoduxO ] servicedir" +#define dieusage() strerr_dieusage(100, USAGE) -int main (int argc, char const *const *argv) +#define DATASIZE 63 + +int main (int argc, char const *const *argv, char const *const *envp) { + char data[DATASIZE+1] = "-" ; + unsigned int datalen = 1 ; + unsigned int timeout = 0 ; + char updown[3] = "-\0" ; PROG = "s6-svc" ; - return s6_svc_main(argc, argv, "abqhkti12fFpcoduxO", USAGE, "supervise") ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "DUabqhkti12pcoduxOT:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'D' : updown[1] = 'd' ; break ; + case 'U' : updown[1] = 'U' ; break ; + case 'a' : + case 'b' : + case 'q' : + case 'h' : + case 'k' : + case 't' : + case 'i' : + case '1' : + case '2' : + case 'p' : + case 'c' : + case 'o' : + case 'd' : + case 'u' : + case 'x' : + case 'O' : + { + if (datalen >= DATASIZE) strerr_dief1x(100, "too many commands") ; + data[datalen++] = opt ; + break ; + } + case 'T' : if (!uint0_scan(l.arg, &timeout)) dieusage() ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) dieusage() ; + if (updown[1]) + { + char const *newargv[11] ; + unsigned int m = 0 ; + char fmt[UINT_FMT] ; + newargv[m++] = S6_BINPREFIX "s6-svlisten1" ; + newargv[m++] = updown ; + if (timeout) + { + fmt[uint_fmt(fmt, timeout)] = 0 ; + newargv[m++] = "-t" ; + newargv[m++] = fmt ; + } + newargv[m++] = "--" ; + newargv[m++] = argv[0] ; + newargv[m++] = S6_BINPREFIX "s6-svc" ; + newargv[m++] = data ; + newargv[m++] = "--" ; + newargv[m++] = argv[0] ; + newargv[m++] = 0 ; + pathexec_run(newargv[0], newargv, envp) ; + strerr_dieexec(111, newargv[0]) ; + } + else if (datalen > 1) + { + unsigned int arglen = str_len(argv[0]) ; + char tmp[arglen + 9 + sizeof(S6_SUPERVISE_CTLDIR)] ; + register int r ; + byte_copy(tmp, arglen, argv[0]) ; + tmp[arglen] = '/' ; + byte_copy(tmp + arglen + 1, 8 + sizeof(S6_SUPERVISE_CTLDIR), S6_SUPERVISE_CTLDIR "/control") ; + r = s6_svc_write(tmp, data + 1, datalen - 1) ; + if (r < 0) strerr_diefu2sys(111, "control ", argv[0]) ; + else if (!r) strerr_diefu3x(100, "control ", argv[0], ": supervisor not listening") ; + } + return 0 ; } diff --git a/src/supervision/s6-svlisten.c b/src/supervision/s6-svlisten.c new file mode 100644 index 0000000..709c409 --- /dev/null +++ b/src/supervision/s6-svlisten.c @@ -0,0 +1,152 @@ +/* ISC license. */ + +#include <sys/types.h> +#include <unistd.h> +#include <errno.h> +#include <skalibs/sgetopt.h> +#include <skalibs/bytestr.h> +#include <skalibs/uint16.h> +#include <skalibs/uint.h> +#include <skalibs/bitarray.h> +#include <skalibs/tai.h> +#include <skalibs/strerr2.h> +#include <skalibs/iopause.h> +#include <skalibs/djbunix.h> +#include <skalibs/sig.h> +#include <skalibs/selfpipe.h> +#include <execline/execline.h> +#include <s6/ftrigr.h> +#include <s6/s6-supervise.h> + +#define USAGE "s6-svlisten [ -U | -u | -d ] [ -A | -a | -o ] [ -t timeout ] servicedir... \"\" prog..." +#define dieusage() strerr_dieusage(100, USAGE) + +static inline int check (unsigned char const *ba, unsigned int n, int wantup, int or) +{ + return (bitarray_first(ba, n, or == wantup) < n) == or ; +} + +static void handle_signals (void) +{ + for (;;) switch (selfpipe_read()) + { + case -1 : strerr_diefu1sys(111, "selfpipe_read") ; + case 0 : return ; + case SIGCHLD : wait_reap() ; break ; + default : strerr_dief1x(101, "unexpected data in selfpipe") ; + } +} + +int main (int argc, char const **argv, char const *const *envp) +{ + ftrigr_t a = FTRIGR_ZERO ; + tain_t deadline, tto ; + int spfd ; + int argc1 ; + int or = 0 ; + int wantup = 1 ; + char re[4] = "u|d" ; + PROG = "s6-svlisten" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + unsigned int t = 0 ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "uUdAaot:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'U' : wantup = 1 ; re[0] = 'U' ; break ; + case 'u' : wantup = 1 ; re[0] = 'u' ; break ; + case 'd' : wantup = 0 ; break ; + case 'a' : or = 0 ; break ; + case 'o' : or = 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(&tto, t) ; else tto = tain_infinite_relative ; + } + if (argc < 3) dieusage() ; + + argc1 = el_semicolon(argv) ; + if (!argc1 || argc == argc1 + 1) dieusage() ; + if (argc1 >= argc) strerr_dief1x(100, "unterminated servicedir block") ; + + spfd = selfpipe_init() ; + if (spfd < 0) strerr_diefu1sys(111, "selfpipe_init") ; + if (selfpipe_trap(SIGCHLD) < 0) strerr_diefu1sys(111, "selfpipe_trap") ; + if (sig_ignore(SIGPIPE) < 0) strerr_diefu1sys(111, "sig_ignore") ; + + tain_now_g() ; + tain_add_g(&deadline, &tto) ; + + if (!ftrigr_startf_g(&a, &deadline)) strerr_diefu1sys(111, "ftrigr_startf") ; + + { + iopause_fd x[2] = { { .fd = spfd, .events = IOPAUSE_READ }, { .fd = ftrigr_fd(&a), .events = IOPAUSE_READ } } ; + pid_t pid ; + unsigned int i = 0 ; + uint16 list[argc1] ; + unsigned char states[bitarray_div8(argc1)] ; + for (; i < (unsigned int)argc1 ; i++) + { + unsigned int len = str_len(argv[i]) ; + char s[len + 1 + sizeof(S6_SUPERVISE_EVENTDIR)] ; + byte_copy(s, len, argv[i]) ; + s[len] = '/' ; + byte_copy(s + len + 1, sizeof(S6_SUPERVISE_EVENTDIR), S6_SUPERVISE_EVENTDIR) ; + list[i] = ftrigr_subscribe_g(&a, s, re, FTRIGR_REPEAT, &deadline) ; + if (!list[i]) strerr_diefu2sys(111, "subscribe to events for ", argv[i]) ; + } + + for (i = 0 ; i < (unsigned int)argc1 ; i++) + { + s6_svstatus_t st = S6_SVSTATUS_ZERO ; + int isup ; + if (!s6_svstatus_read(argv[i], &st)) strerr_diefu1sys(111, "s6_svstatus_read") ; + isup = !!st.pid ; + if (re[0] == 'U' && isup) + { + unsigned int len = str_len(argv[i]) ; + char s[len + 1 + sizeof(S6_SUPERVISE_READY_FILENAME)] ; + byte_copy(s, len, argv[i]) ; + s[len] = '/' ; + byte_copy(s + len + 1, sizeof(S6_SUPERVISE_READY_FILENAME), S6_SUPERVISE_READY_FILENAME) ; + if (access(s, F_OK) < 0) + { + if (errno == ENOENT) isup = 0 ; + else strerr_warnwu2sys("check ", s) ; + } + } + bitarray_poke(states, i, isup) ; + } + + pid = child_spawn0(argv[argc1 + 1], argv + argc1 + 1, envp) ; + if (!pid) strerr_diefu2sys(111, "spawn ", argv[argc1 + 1]) ; + + for (;;) + { + register int r ; + if (check(states, argc1, wantup, or)) break ; + r = iopause_g(x, 2, &deadline) ; + if (r < 0) strerr_diefu1sys(111, "iopause") ; + else if (!r) strerr_dief1x(1, "timed out") ; + + if (x[0].revents & IOPAUSE_READ) handle_signals() ; + if (x[1].revents & IOPAUSE_READ) + { + if (ftrigr_update(&a) < 0) strerr_diefu1sys(111, "ftrigr_update") ; + for (i = 0 ; i < (unsigned int)argc1 ; i++) + { + char what ; + register int r = ftrigr_check(&a, list[i], &what) ; + if (r < 0) strerr_diefu1sys(111, "ftrigr_check") ; + if (r) bitarray_poke(states, i, what == re[0]) ; + } + } + } + } + return 0 ; +} diff --git a/src/supervision/s6-svlisten1.c b/src/supervision/s6-svlisten1.c new file mode 100644 index 0000000..a5cecf0 --- /dev/null +++ b/src/supervision/s6-svlisten1.c @@ -0,0 +1,121 @@ +/* ISC license. */ + +#include <sys/types.h> +#include <unistd.h> +#include <errno.h> +#include <signal.h> +#include <skalibs/sgetopt.h> +#include <skalibs/bytestr.h> +#include <skalibs/uint16.h> +#include <skalibs/uint.h> +#include <skalibs/tai.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> +#include <skalibs/iopause.h> +#include <skalibs/sig.h> +#include <skalibs/selfpipe.h> +#include <s6/ftrigr.h> +#include <s6/s6-supervise.h> + +#define USAGE "s6-svlisten1 [ -U | -u | -d ] [ -t timeout ] servicedir prog..." +#define dieusage() strerr_dieusage(100, USAGE) + +static void handle_signals (void) +{ + for (;;) switch (selfpipe_read()) + { + case -1 : strerr_diefu1sys(111, "selfpipe_read") ; + case 0 : return ; + case SIGCHLD : wait_reap() ; break ; + default : strerr_dief1x(101, "unexpected data in selfpipe") ; + } +} + +int main (int argc, char const *const *argv, char const *const *envp) +{ + ftrigr_t a = FTRIGR_ZERO ; + tain_t deadline, tto ; + int spfd ; + int wantup = 1 ; + char re[4] = "u|d" ; + PROG = "s6-svlisten1" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + unsigned int t = 0 ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "uUdt:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'U' : wantup = 1 ; re[0] = 'U' ; break ; + case 'u' : wantup = 1 ; re[0] = 'u' ; break ; + case 'd' : wantup = 0 ; break ; + case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + if (t) tain_from_millisecs(&tto, t) ; else tto = tain_infinite_relative ; + } + if (!argc) dieusage() ; + + spfd = selfpipe_init() ; + if (spfd < 0) strerr_diefu1sys(111, "selfpipe_init") ; + if (selfpipe_trap(SIGCHLD) < 0) strerr_diefu1sys(111, "selfpipe_trap") ; + if (sig_ignore(SIGPIPE) < 0) strerr_diefu1sys(111, "sig_ignore") ; + + tain_now_g() ; + tain_add_g(&deadline, &tto) ; + + if (!ftrigr_startf_g(&a, &deadline)) strerr_diefu1sys(111, "ftrigr_startf") ; + + { + iopause_fd x[2] = { { .fd = spfd, .events = IOPAUSE_READ }, { .fd = ftrigr_fd(&a), .events = IOPAUSE_READ } } ; + unsigned int arglen = str_len(argv[0]) ; + pid_t pid ; + int isup ; + s6_svstatus_t st = S6_SVSTATUS_ZERO ; + uint16 id ; + char s[arglen + 1 + sizeof(S6_SUPERVISE_EVENTDIR)] ; + byte_copy(s, arglen, argv[0]) ; + s[arglen] = '/' ; + byte_copy(s + arglen + 1, sizeof(S6_SUPERVISE_EVENTDIR), S6_SUPERVISE_EVENTDIR) ; + id = ftrigr_subscribe_g(&a, s, re, FTRIGR_REPEAT, &deadline) ; + if (!id) strerr_diefu2sys(111, "subscribe to events for ", argv[0]) ; + if (!s6_svstatus_read(argv[0], &st)) strerr_diefu1sys(111, "s6_svstatus_read") ; + isup = !!st.pid ; + if (re[0] == 'U' && isup) + { + byte_copy(s + arglen + 1, sizeof(S6_SUPERVISE_READY_FILENAME), S6_SUPERVISE_READY_FILENAME) ; + if (access(s, F_OK) < 0) + { + if (errno == ENOENT) isup = 0 ; + else strerr_warnwu2sys("check ", s) ; + } + } + + pid = child_spawn0(argv[1], argv + 1, envp) ; + if (!pid) strerr_diefu2sys(111, "spawn ", argv[2]) ; + + for (;;) + { + register int r ; + if (isup == wantup) break ; + r = iopause_g(x, 2, &deadline) ; + if (r < 0) strerr_diefu1sys(111, "iopause") ; + else if (!r) strerr_dief1x(1, "timed out") ; + + if (x[0].revents & IOPAUSE_READ) handle_signals() ; + if (x[1].revents & IOPAUSE_READ) + { + char what ; + if (ftrigr_update(&a) < 0) strerr_diefu1sys(111, "ftrigr_update") ; + r = ftrigr_check(&a, id, &what) ; + if (r < 0) strerr_diefu1sys(111, "ftrigr_check") ; + if (r) isup = what == re[0] ; + } + } + } + return 0 ; +} diff --git a/src/supervision/s6-svwait.c b/src/supervision/s6-svwait.c index a6dc410..9e8520b 100644 --- a/src/supervision/s6-svwait.c +++ b/src/supervision/s6-svwait.c @@ -13,7 +13,7 @@ #include <s6/ftrigr.h> #include <s6/s6-supervise.h> -#define USAGE "s6-svwait [ -U | -u | -d ] [ -A | -a | -o ] [ -t timeout ] servicedir..." +#define USAGE "s6-svwait [ -U | -u | -d ] [ -a | -o ] [ -t timeout ] servicedir..." #define dieusage() strerr_dieusage(100, USAGE) static inline int check (unsigned char const *ba, unsigned int n, int wantup, int or) @@ -25,7 +25,6 @@ int main (int argc, char const *const *argv) { tain_t deadline, tto ; ftrigr_t a = FTRIGR_ZERO ; - uint32 options = FTRIGR_REPEAT ; int or = 0 ; int wantup = 1 ; char re[4] = "u|d" ; @@ -35,16 +34,15 @@ int main (int argc, char const *const *argv) unsigned int t = 0 ; for (;;) { - register int opt = subgetopt_r(argc, argv, "uUdAaot:", &l) ; + register int opt = subgetopt_r(argc, argv, "uUdaot:", &l) ; if (opt == -1) break ; switch (opt) { case 'U' : wantup = 1 ; re[0] = 'U' ; break ; case 'u' : wantup = 1 ; re[0] = 'u' ; break ; case 'd' : wantup = 0 ; break ; - case 'A' : or = 0 ; options |= FTRIGR_REPEAT ; break ; - case 'a' : or = 0 ; options &= ~FTRIGR_REPEAT ; break ; - case 'o' : or = 1 ; options &= ~FTRIGR_REPEAT ; break ; + case 'a' : or = 0 ; break ; + case 'o' : or = 1 ; break ; case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ; default : dieusage() ; } @@ -72,8 +70,8 @@ int main (int argc, char const *const *argv) byte_copy(s, len, argv[i]) ; s[len] = '/' ; byte_copy(s + len + 1, sizeof(S6_SUPERVISE_EVENTDIR), S6_SUPERVISE_EVENTDIR) ; - list[i] = ftrigr_subscribe_g(&a, s, re, options, &deadline) ; - if (!list[i]) strerr_diefu2sys(111, "ftrigr_subscribe to ", argv[i]) ; + list[i] = ftrigr_subscribe_g(&a, s, re, FTRIGR_REPEAT, &deadline) ; + if (!list[i]) strerr_diefu2sys(111, "subscribe to events for", argv[i]) ; } for (i = 0 ; i < (unsigned int)argc ; i++) |