diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/s6-rc/deps-exe/s6-rc-oneshot-run | 2 | ||||
-rw-r--r-- | src/s6-rc/s6-rc-oneshot-run.c | 102 |
2 files changed, 104 insertions, 0 deletions
diff --git a/src/s6-rc/deps-exe/s6-rc-oneshot-run b/src/s6-rc/deps-exe/s6-rc-oneshot-run new file mode 100644 index 0000000..152b051 --- /dev/null +++ b/src/s6-rc/deps-exe/s6-rc-oneshot-run @@ -0,0 +1,2 @@ +${LIBS6RC} +-lskarnet diff --git a/src/s6-rc/s6-rc-oneshot-run.c b/src/s6-rc/s6-rc-oneshot-run.c new file mode 100644 index 0000000..60834c8 --- /dev/null +++ b/src/s6-rc/s6-rc-oneshot-run.c @@ -0,0 +1,102 @@ +/* ISC license. */ + +#include <skalibs/uint.h> +#include <skalibs/bytestr.h> +#include <skalibs/sgetopt.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> +#include <s6-rc/config.h> +#include <s6-rc/s6rc.h> + +#define USAGE "s6-rc-oneshot-run [ -l live ] up|down servicenumber" +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv, char const *const *envp) +{ + char const *live = S6RC_LIVE_BASE ; + unsigned int number ; + int up ; + PROG = "s6-rc-db" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "l:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'l' : live = l.arg ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + } + + if (argc < 2) dieusage() ; + if (!case_diffs(argv[0], "up")) up = 1 ; + else if (!case_diffs(argv[0], "down")) up = 0 ; + else dieusage() ; + if (!uint0_scan(argv[1], &number)) dieusage() ; + + { + unsigned int livelen = str_len(live) ; + int fdcompiled, compiledlock ; + s6rc_db_t db ; + char compiled[livelen + 10] ; + byte_copy(compiled, livelen, live) ; + byte_copy(compiled + livelen, 10, "/compiled") ; + + if (!s6rc_lock(0, 0, 0, compiled, 1, &compiledlock)) + strerr_diefu2sys(111, "take lock on ", compiled) ; + fdcompiled = open_readb(compiled) ; + if (fdcompiled < 0) + strerr_diefu2sys(111, "open ", compiled) ; + + + /* Read the sizes of the compiled db */ + + fdcompiled = open_readb(compiled) ; + if (!s6rc_db_read_sizes(fdcompiled, &db)) + strerr_diefu3sys(111, "read ", compiled, "/n") ; + + if (number >= db.nshort) + strerr_dief1x(3, "invalid oneshot number") ; + + + /* Allocate enough stack for the db */ + + { + s6rc_service_t serviceblob[db.nshort + db.nlong] ; + char const *argvblob[db.nargvs] ; + uint32 depsblob[db.ndeps << 1] ; + char stringblob[db.stringlen] ; + register int r ; + + db.services = serviceblob ; + db.argvs = argvblob ; + db.deps = depsblob ; + db.string = stringblob ; + + + /* Read the db from the file */ + + r = s6rc_db_read(fdcompiled, &db) ; + if (r < 0) strerr_diefu3sys(111, "read ", compiled, "/db") ; + if (!r) strerr_dief3x(4, "invalid service database in ", compiled, "/db") ; + + + /* Run the script */ + + { + register unsigned int sargc = db.services[number].x.oneshot.argc[up] ; + char const *const *sargv = db.argvs + db.services[number].x.oneshot.argv[up] ; + char const *newargv[sargc + 1] ; + register char const **p = newargv ; + while (sargc--) *p++ = *sargv++ ; + *p = 0 ; + pathexec_run(newargv[0], newargv, envp) ; + strerr_dieexec(111, newargv[0]) ; + } + } + } +} |