diff options
| author | Laurent Bercot <ska-skaware@skarnet.org> | 2026-06-14 04:37:32 +0000 |
|---|---|---|
| committer | Laurent Bercot <ska-skaware@skarnet.org> | 2026-06-14 04:37:32 +0000 |
| commit | 87b8fcabeecf2a9cff2ca596da54d6c1cf17d89f (patch) | |
| tree | bc07d6d01afac944925d43108fda8b91ef2fe12f | |
| parent | 958958d74337a6ddaf649968d188e768984100e0 (diff) | |
| download | s6-rc-87b8fcabeecf2a9cff2ca596da54d6c1cf17d89f.tar.gz | |
Prepare for 0.7.0.0; lots of changes!
- s6-rc-bundle deleted. Changing bundles without recompiling is not
supported anymore. (It works, but it incentivizes poor workflows; it is
better to handle stuff at the source level and recompile when in doubt,
that's what s6-frontend does.)
- new db format, need to recompile and use s6-rc-format-upgrade on new live db
- support for the reload-signal file in service directories
- new reload scripts for oneshots (which is why the db format has changed)
- new "s6-rc reload" command, calling s6-svc -l on longruns (which makes use
of reload-signal, HUP by default) and the reload script on oneshots
- the live state now tracks when a service has been explicitly brought up
as opposed to by pulled by dependencies. Nothing uses the feature for now
but now the tech is there for an auto-stop-if-unneeded feature.
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | NEWS | 2 | ||||
| -rw-r--r-- | doc/faq.html | 7 | ||||
| -rw-r--r-- | doc/index.html | 5 | ||||
| -rw-r--r-- | doc/overview.html | 10 | ||||
| -rw-r--r-- | doc/s6-rc-bundle.html | 138 | ||||
| -rw-r--r-- | doc/s6-rc-compile.html | 26 | ||||
| -rw-r--r-- | doc/s6-rc.html | 3 | ||||
| -rw-r--r-- | doc/upgrade.html | 13 | ||||
| -rw-r--r-- | package/info | 2 | ||||
| -rw-r--r-- | package/modes | 1 | ||||
| -rw-r--r-- | package/targets.mak | 1 | ||||
| -rw-r--r-- | src/include/s6-rc/s6rc-db.h | 4 | ||||
| -rw-r--r-- | src/libs6rc/s6rc_db_read.c | 2 | ||||
| -rw-r--r-- | src/libs6rc/s6rc_servicedir_internal.c | 17 | ||||
| -rw-r--r-- | src/s6-rc/s6-rc-bundle.c | 341 | ||||
| -rw-r--r-- | src/s6-rc/s6-rc-compile.c | 285 | ||||
| -rw-r--r-- | src/s6-rc/s6-rc-format-upgrade.c | 77 | ||||
| -rw-r--r-- | src/s6-rc/s6-rc-init.c | 3 | ||||
| -rw-r--r-- | src/s6-rc/s6-rc-oneshot-run.c | 36 | ||||
| -rw-r--r-- | src/s6-rc/s6-rc.c | 230 |
21 files changed, 376 insertions, 828 deletions
@@ -8,7 +8,6 @@ /s6-rc-compile /s6-rc-dryrun /s6-rc-db -/s6-rc-bundle /s6-rc-init /s6-rc /s6-rc-update @@ -1,6 +1,6 @@ Changelog for s6-rc. -In 0.6.2.0 +In 0.7.0.0 ---------- - Bugfixes. diff --git a/doc/faq.html b/doc/faq.html index 23797f1..59b1d82 100644 --- a/doc/faq.html +++ b/doc/faq.html @@ -339,13 +339,6 @@ you don't want up anymore: <tt>s6-rc -p change runlevel-2</tt>. <p> Bundles are easy to use, they're flexible, and they're powerful. They give you the same level of functionality as runlevels would, and more. -You can even add bundles to compiled service databases - including the -live one - or remove bundles from them without having to recompile them: -that's what the <a href="s6-rc-bundle.html">s6-rc-bundle</a> utility is -for. -</p> - -<p> When in doubt, use bundles. </p> diff --git a/doc/index.html b/doc/index.html index 426bdb5..1278c18 100644 --- a/doc/index.html +++ b/doc/index.html @@ -69,8 +69,8 @@ requirement if you link against the shared version of the skalibs library. </li> <ul> <li> The current released version of s6-rc is -<a href="s6-rc-0.6.2.0.tar.gz">0.6.2.0</a>. -You can access its checksum <a href="s6-rc-0.6.2.0.tar.gz.sha256">here</a>. </li> +<a href="s6-rc-0.7.0.0.tar.gz">0.7.0.0</a>. +You can access its checksum <a href="s6-rc-0.7.0.0.tar.gz.sha256">here</a>. </li> <li> Alternatively, you can checkout a copy of the <a href="//git.skarnet.org/cgi-bin/cgit.cgi/s6-rc/">s6-rc git repository</a>: @@ -106,7 +106,6 @@ the previous versions of s6-rc and the current one. </li> <ul> <li> <a href="s6-rc-compile.html">The <tt>s6-rc-compile</tt> program</a> </li> <li> <a href="s6-rc-db.html">The <tt>s6-rc-db</tt> program</a> </li> - <li> <a href="s6-rc-bundle.html">The <tt>s6-rc-bundle</tt> program</a> </li> </ul> <h4> Online tools: managing your live services </h4> diff --git a/doc/overview.html b/doc/overview.html index e563256..1dfd4dc 100644 --- a/doc/overview.html +++ b/doc/overview.html @@ -219,16 +219,6 @@ provided in the packages, an invocation of keep the live state up to date. </p> -<h2> Live bundle modifications </h2> - -<p> - It is possible to change bundle definitions in a compiled service -database, including the live one, without recompiling everything by -calling <a href="s6-rc-compile.html">s6-rc-compile</a>. The -<a href="s6-rc-bundle.html">s6-rc-bundle</a> tool can edit compiled -databases to add bundles to them, or delete bundles from them. -</p> - <h2> Management of source definition directories </h2> <p> diff --git a/doc/s6-rc-bundle.html b/doc/s6-rc-bundle.html deleted file mode 100644 index fbe8d06..0000000 --- a/doc/s6-rc-bundle.html +++ /dev/null @@ -1,138 +0,0 @@ -<html> - <head> - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - <meta name="color-scheme" content="dark light" /> - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> - <meta http-equiv="Content-Language" content="en" /> - <title>s6-rc: the s6-rc-bundle program</title> - <meta name="Description" content="s6-rc: the s6-rc-bundle program" /> - <meta name="Keywords" content="s6-rc offline database dump command rc init dependency state management services" /> - <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> --> - </head> -<body> - -<p> -<a href="index.html">s6-rc</a><br /> -<a href="//skarnet.org/software/">Software</a><br /> -<a href="//skarnet.org/">skarnet.org</a> -</p> - -<h1> The s6-rc-bundle program </h1> - -<p> - s6-rc-bundle is a tool to add or delete bundles from a compiled -service database without having to recompile it from source. -</p> - -<p> - It is an <em>offline tool</em>, i.e. you can run it on any -compiled service database without actually having a live set -of services managed by s6-rc. However, if you do have a live -set, you can still run s6-rc-bundle on the current database (and -it is the default); it won't interfere with your normal service -operation. -</p> - -<h2> Interface </h2> - -<pre> - s6-rc-bundle help - s6-rc-bundle [ -f ] [ -l <em>live</em> ] [ -c <em>compiled</em> ] [ -b ] add <em>bundlename</em> <em>contents...</em> - s6-rc-bundle [ -f ] [ -l <em>live</em> ] [ -c <em>compiled</em> ] [ -b ] delete <em>bundlenames...</em> - s6-rc-bundle [ -f ] [ -l <em>live</em> ] [ -c <em>compiled</em> ] [ -b ] multiple <em>args...</em> -</pre> - -<ul> - <li> s6-rc-bundle expects to find a <em>compiled service database</em> -in <em>compiled</em>; by default it uses the service database -used by the live state in <em>live</em>. </li> - <li> Depending on the arguments, it adds a bundle definition to this database, or -deletes a bundle definition from it, or performs multiple additions/deletions. </li> -</ul> - -<h2> Options </h2> - -<ul> - <li> <tt>-c <em>compiled</em></tt> : operate on a -compiled service database in <em>compiled</em> instead of -the current live one. </li> - <li> <tt>-l <em>live</em></tt> : assume the live -state is in <em>live</em>. This option is ignored if the -<tt>-c</tt> option has been given. Default is -<tt>/run/s6-rc</tt>. The default can be changed at package -compilation time, by giving the <tt>--livedir=<em>live</em></tt> -option to <tt>./configure</tt>. </li> - <li> <tt>-f</tt> : force. s6-rc-bundle will not complain -when given a nonexisting name to delete (it will do nothing), or -when given an existing name to add (it will replace the definition). -By default, s6-rc-bundle will complain and exit when asked to delete a -nonexistent name or to add an existing name. </li> - <li> <tt>-b</tt> : blocking lock. If the database is currently -being used by another program, s6-rc-bundle will wait until that -other program has released its lock on the database, then proceed. -By default, s6-rc-bundle fails with an error message if the database -is currently in use. </li> -</ul> - -<h2> Exit codes </h2> - -<ul> - <li> 0: success </li> - <li> 1: identifier already exists in service database </li> - <li> 3: identifier not found in service database </li> - <li> 4: invalid or corrupted service database </li> - <li> 5: wrong identifier type for the given command </li> - <li> 100: wrong usage </li> - <li> 111: system call failed </li> -</ul> - -<h2> Subcommands </h2> - -<h3> s6-rc-bundle help </h3> - -<p> - Prints a help message on stdout. -</p> - -<h3> s6-rc-bundle add <em>bundlename</em> <em>contents...</em> </h3> - -<p> - Adds a bundle named <em>bundlename</em> to the database, representing -the services listed in <em>contents</em>. The arguments in <em>contents...</em> -are resolved <em>before</em> the database is modified by the -s6-rc-bundle invocation. -</p> - -<h3> s6-rc-bundle delete <em>bundlenames...</em> </h3> - -<p> - Deletes bundles listed in <em>bundlenames...</em>. -</p> - -<h3> s6-rc-bundle multiple <em>args...</em> </h3> - -<p> - Performs multiple bundle deletions and additions. This subcommand is best -used in an <a href="//skarnet.org/software/execline/">execline</a> -script, because it uses -<a href="//skarnet.org/software/execline/el_semicolon.html">blocks</a>. -</p> - -<p> -<em>args...</em> is composed of: -</p> - -<ul> - <li> One block listing bundle names that will be -deleted from the database. </li> - <li> Zero or more addition definitions, each of them composed of: - <ul> - <li> One argument that is the name of the bundle to add </li> - <li> One block listing the services contained in the -new bundle. The names in the block are resolved before any addition -or deletion is made to the database. </li> - </ul> </li> -</ul> - -</body> -</html> diff --git a/doc/s6-rc-compile.html b/doc/s6-rc-compile.html index 07625ac..d207b6c 100644 --- a/doc/s6-rc-compile.html +++ b/doc/s6-rc-compile.html @@ -198,30 +198,30 @@ complain and exit 1. <h4> For oneshots </h4> <ul> - <li> Two regular files named <tt>up</tt> and <tt>down</tt>, which -must each contain a single Unix command line. The files will be interpreted by the + <li> Three regular files named <tt>up</tt>, <tt>down</tt>, and <tt>reload</tt>, +which must each contain a single Unix command line. The <tt>up</tt> file is +mandatory, the other two are optional; if they are absent, they are considered +empty, i.e. nothing happens when the corresponding script is executed and the +operation is considered a success. +The files will be interpreted by the <a href="//skarnet.org/software/execline/execlineb.html">execlineb</a> lexer at compile time and the results will be stored into the compiled database in an internal form. <tt>up</tt> will be run when -the service is started, and <tt>down</tt> will be executed when the service -is stopped. <tt>up</tt> is mandatory, but <tt>down</tt> is optional; -if no <tt>down</tt> file is provided in the source definition directory, -then it is treated as the empty script. If a script is empty, -then s6-rc will consider that the corresponding transition for this service -does nothing and always succeeds. </li> +the service is started, <tt>down</tt> will be executed when the service +is stopped, and <tt>reload</tt> will be executed when the service is +reloaded </li> </ul> <p> - <tt>up</tt> and <tt>down</tt> are interpreted by + <tt>up</tt>, <tt>down</tt> and <tt>reload</tt> are interpreted by <a href="//skarnet.org/software/execline/execlineb.html">execlineb</a>, but that does not mean they have to be entirely written in the <a href="//skarnet.org/software/execline/">execline</a> language. The <a href="//skarnet.org/software/execline/execlineb.html">execlineb</a> lexer is only used because it can compile a Unix command line from a text file and store the compiled result, whereas a shell would have to be invoked -everytime the script is run. There are many ways to write <tt>up</tt> and -<tt>down</tt> scripts: +everytime the script is run. There are many ways to write these scripts: </p> <ul> @@ -239,8 +239,8 @@ while <tt>down</tt> contains <tt>/etc/init.d/<em>service</em> stop</tt>, and <p> Don't think you have to learn all the intricacies of the execline language -just because the <tt>up</tt> and <tt>down</tt> scripts get lexed by it. -You don't. +just because the <tt>up</tt>, <tt>down</tt> and <tt>reload</tt>scripts get +lexed by it. You don't. </p> <h4> For longruns </h4> diff --git a/doc/s6-rc.html b/doc/s6-rc.html index bb16113..afd6795 100644 --- a/doc/s6-rc.html +++ b/doc/s6-rc.html @@ -252,8 +252,7 @@ given on the command line, which must all be up. For a longrun, <tt>s6-rc reload</tt> sends an <a href="//skarnet.org/software/s6/s6-svc.html">s6-svc -l</a> command to the service, which causes it to receive a SIGHUP, or any overriding signal configured in the <tt>reload-signal</tt> file. -For a oneshot, the service's <tt>up</tt> script is executed, with -an additional <tt>RC_RELOAD</tt> environment variable containing 1. +For a oneshot, the service's <tt>reload</tt> script is executed. </p> <p> diff --git a/doc/upgrade.html b/doc/upgrade.html index 0aac5cf..f61933c 100644 --- a/doc/upgrade.html +++ b/doc/upgrade.html @@ -31,7 +31,7 @@ minor and bugfix version changes. <h1> What has changed in s6-rc </h1> -<h2> in 0.6.2.0 </h2> +<h2> in 0.7.0.0 </h2> <ul> <li> <a href="//skarnet.org/software/skalibs/">skalibs</a> @@ -39,8 +39,17 @@ dependency bumped to 2.15.0.1. </li> <li> <a href="//skarnet.org/software/execline/">execline</a> dependency bumped to 2.9.9.2. </li> <li> <a href="//skarnet.org/software/s6/">s6</a> -dependency bumped to 2.15.0.1. </li> +dependency bumped to 2.15.1.0. </li> <li> New <a href="s6-rc.html">s6-rc reload</a> command. </li> + <li> The database format has changed! To safely upgrade a running s6-rc installation: + <ul> + <li> Compile your current live database from the <strong>same source</strong> +using the latest <a href="s6-rc-compile.html">s6-rc-compile</a> </li> + <li> Run the latest <a href="s6-rc-format-upgrade.html">s6-rc-format-upgrade</a> with the +newly obtained database </li> + <li> Run the latest <a href="s6-rc-update.html">s6-rc-update</a> with the same database </li> + <li> Your system is now running the latest version of s6-rc; you can delete your old database </li> + </ul> </ul> <h2> in 0.6.1.1 </h2> diff --git a/package/info b/package/info index 0b55290..c0cd306 100644 --- a/package/info +++ b/package/info @@ -1,4 +1,4 @@ package=s6-rc -version=0.6.2.0 +version=0.7.0.0 category=admin package_macro_name=S6RC diff --git a/package/modes b/package/modes index 0676950..c76a046 100644 --- a/package/modes +++ b/package/modes @@ -1,7 +1,6 @@ s6-rc-compile 0755 s6-rc-db 0755 s6-rc-dryrun 0755 -s6-rc-bundle 0755 s6-rc-init 0755 s6-rc 0755 s6-rc-update 0755 diff --git a/package/targets.mak b/package/targets.mak index fe89f89..0dd4abf 100644 --- a/package/targets.mak +++ b/package/targets.mak @@ -2,7 +2,6 @@ BIN_TARGETS := \ s6-rc-compile \ s6-rc-dryrun \ s6-rc-db \ -s6-rc-bundle \ s6-rc-init \ s6-rc \ s6-rc-update \ diff --git a/src/include/s6-rc/s6rc-db.h b/src/include/s6-rc/s6rc-db.h index 0f03967..9b156f8 100644 --- a/src/include/s6-rc/s6rc-db.h +++ b/src/include/s6-rc/s6rc-db.h @@ -18,8 +18,8 @@ typedef struct s6rc_oneshot_s s6rc_oneshot_t, *s6rc_oneshot_t_ref ; struct s6rc_oneshot_s { - uint32_t argc[2] ; - uint32_t argv[2] ; + uint32_t argc[3] ; + uint32_t argv[3] ; } ; typedef struct s6rc_longrun_s s6rc_longrun_t, *s6rc_longrun_t_ref ; diff --git a/src/libs6rc/s6rc_db_read.c b/src/libs6rc/s6rc_db_read.c index b233cfe..46fb939 100644 --- a/src/libs6rc/s6rc_db_read.c +++ b/src/libs6rc/s6rc_db_read.c @@ -72,7 +72,7 @@ static inline int s6rc_db_read_services (buffer *b, s6rc_db_t *db) else { unsigned int j = 0 ; - for (; j < 2 ; j++) + for (; j < 3 ; j++) { uint32_t pos, argc ; if (!s6rc_db_read_uint32(b, &argc)) return -1 ; diff --git a/src/libs6rc/s6rc_servicedir_internal.c b/src/libs6rc/s6rc_servicedir_internal.c index e81f378..5c55d28 100644 --- a/src/libs6rc/s6rc_servicedir_internal.c +++ b/src/libs6rc/s6rc_servicedir_internal.c @@ -27,7 +27,7 @@ static s6_servicedir_desc const svdir_file_list[] = { .name = "down-signal", .type = S6_FILETYPE_NORMAL, .options = 0 }, { .name = "reload-signal", .type = S6_FILETYPE_NORMAL, .options = 0 }, { .name = "flag-newpidns", .type = S6_FILETYPE_EMPTY, .options = 0 }, - { .name = "template", .type = S6_FILETYPE_DIR, .options = 0 }, + { .name = "template", .type = S6_FILETYPE_TEMPLATE, .options = 0 }, { .name = "data", .type = S6_FILETYPE_DIR, .options = 0 }, { .name = "env", .type = S6_FILETYPE_DIR, .options = 0 }, { .name = 0, .options = 0 } @@ -61,7 +61,7 @@ int s6rc_servicedir_copy_one (char const *src, char const *dst, s6_servicedir_de break ; } case S6_FILETYPE_EMPTY : - if (access(srcfn, F_OK) < 0) + if (access(srcfn, F_OK) == -1) { if (errno != ENOENT || p->options & S6_SVFILE_MANDATORY) return 0 ; } @@ -81,16 +81,17 @@ int s6rc_servicedir_copy_one (char const *src, char const *dst, s6_servicedir_de } break ; } + case S6_FILETYPE_TEMPLATE : case S6_FILETYPE_DIR : if (!hiercopy(srcfn, dstfn)) { - if (errno != ENOENT || p->options & S6_SVFILE_MANDATORY) return 0 ; - } - if (!strcmp(p->name, "template")) - { - memcpy(dstfn + dstlen + 1, "instance", 9) ; - if (mkdir(dstfn, 0755) == -1 && errno != EEXIST) return 0 ; + if (errno != ENOENT) return 0 ; + if (p->options & S6_SVFILE_MANDATORY) return 0 ; + break ; } + if (p->type != S6_FILETYPE_TEMPLATE) break ; + memcpy(dstfn + dstlen + 1, "instance", 9) ; + if (mkdir(dstfn, 0755) == -1 && errno != EEXIST) return 0 ; break ; default : return (errno = EDOM, 0) ; } diff --git a/src/s6-rc/s6-rc-bundle.c b/src/s6-rc/s6-rc-bundle.c deleted file mode 100644 index d2b447a..0000000 --- a/src/s6-rc/s6-rc-bundle.c +++ /dev/null @@ -1,341 +0,0 @@ -/* ISC license. */ - -#include <string.h> -#include <stdint.h> -#include <unistd.h> -#include <errno.h> -#include <stdio.h> - -#include <skalibs/posixplz.h> -#include <skalibs/uint32.h> -#include <skalibs/buffer.h> -#include <skalibs/strerr.h> -#include <skalibs/sgetopt.h> -#include <skalibs/bitarray.h> -#include <skalibs/djbunix.h> -#include <skalibs/cdb.h> -#include <skalibs/cdbmake.h> -#include <skalibs/unix-transactional.h> - -#include <execline/execline.h> - -#include <s6-rc/config.h> -#include <s6-rc/s6rc.h> - -#define USAGE "s6-rc-bundle [ -l live ] [ -c compiled ] [ -b ] command... (use s6-rc-bundle help for more information)" -#define dieusage() strerr_dieusage(100, USAGE) - -static void cleanup (char const *compiled) -{ - size_t len = strlen(compiled) ; - char fn[len + sizeof("/resolve.cdb.new")] ; - memcpy(fn, compiled, len) ; - memcpy(fn + len, "/resolve.cdb.new", sizeof("/resolve.cdb.new")) ; - unlink_void(fn) ; -} - - - /* TODO: switch to renameat when it's more portable */ - -static inline int renameit (char const *compiled, char const *src, char const *dst) -{ - size_t clen = strlen(compiled) ; - size_t srclen = strlen(src) ; - size_t dstlen = strlen(dst) ; - char srcfn[clen + srclen + 2] ; - char dstfn[clen + dstlen + 2] ; - memcpy(srcfn, compiled, clen) ; - srcfn[clen] = '/' ; - memcpy(srcfn + clen + 1, src, srclen + 1) ; - memcpy(dstfn, compiled, clen) ; - dstfn[clen] = '/' ; - memcpy(dstfn + clen + 1, dst, dstlen + 1) ; - return rename(srcfn, dstfn) ; -} - -static void check (cdb const *cr, s6rc_db_t *db, char const *name, int h, int force, char const *compiled) -{ - size_t namelen = strlen(name) ; - cdb_data data ; - int r = cdb_find(cr, &data, name, namelen) ; - if (r < 0) strerr_diefu3sys(111, "cdb_find in ", compiled, "/resolve.cdb") ; - if (!r) - { - if (!h && !force) - strerr_dief4x(3, "identifier ", name, " does not exist in database ", compiled) ; - return ; - } - if (h && !force) - strerr_dief4x(1, "identifier ", name, " already exists in database ", compiled) ; - if (data.len == 4) - { - uint32_t x ; - uint32_unpack_big(data.s, &x) ; - if (x >= db->nshort + db->nlong) - strerr_dief2x(4, "invalid database in ", compiled) ; - if (!strcmp(name, db->string + db->services[x].name)) - strerr_dief4x(5, "identifier ", name, " does not represent a bundle for database ", compiled) ; - } -} - -static void modify_resolve (int fdcompiled, s6rc_db_t *db, char const *const *todel, unsigned int todeln, char const *const *toadd, char const *const *const *toadd_contents, unsigned int toaddn, int force, char const *compiled) -{ - cdb cr = CDB_ZERO ; - cdbmaker cw = CDBMAKER_ZERO ; - uint32_t pos = CDB_TRAVERSE_INIT() ; - unsigned int i = toaddn ; - int fdw ; - unsigned int n = db->nlong + db->nshort ; - unsigned char bits[bitarray_div8(n)] ; - if (!cdb_init_at(&cr, fdcompiled, "resolve.cdb")) - strerr_diefu3sys(111, "cdb_init ", compiled, "/resolve.cdb") ; - while (i--) check(&cr, db, toadd[i], 1, force, compiled) ; - i = todeln ; - while (i--) check(&cr, db, todel[i], 0, force, compiled) ; - fdw = open_truncatb(fdcompiled, "resolve.cdb.new") ; - if (fdw < 0) strerr_diefu3sys(111, "open ", compiled, "/resolve.cdb.new") ; - if (!cdbmake_start(&cw, fdw)) - { - cleanup(compiled) ; - strerr_diefu1sys(111, "cdbmake_start") ; - } - for (;;) - { - cdb_data key, data ; - int r = cdb_traverse_next(&cr, &key, &data, &pos) ; - if (r < 0) - { - cleanup(compiled) ; - strerr_dief3x(4, "invalid cdb in ", compiled, "/resolve.cdb") ; - } - if (!r) break ; - for (i = 0 ; i < todeln ; i++) if (key.len == strlen(todel[i]) && !strncmp(todel[i], key.s, key.len)) break ; - if (i < todeln) continue ; - for (i = 0 ; i < toaddn ; i++) if (key.len == strlen(toadd[i]) && !strncmp(toadd[i], key.s, key.len)) break ; - if (i < toaddn) continue ; - if (!cdbmake_add(&cw, key.s, key.len, data.s, data.len)) - { - cleanup(compiled) ; - strerr_diefu1sys(111, "cdb_make_add") ; - } - } - i = toaddn ; - while (i--) - { - char const *const *p = toadd_contents[i] ; - unsigned int total = 0 ; - memset(bits, 0, bitarray_div8(n)) ; - for (; *p ; p++) - { - cdb_data data ; - int r = cdb_find(&cr, &data, *p, strlen(*p)) ; - if (r < 0) strerr_diefu3x(4, "invalid cdb in ", compiled, "/resolve.cdb") ; - if (!r) strerr_dief4x(3, "identifier ", *p, " does not exist in database ", compiled) ; - for (uint32_t j = 0 ; j < data.len ; j += 4) - { - uint32_t x ; - uint32_unpack_big(data.s + j, &x) ; - if (x >= db->nshort + db->nlong) - strerr_dief2x(4, "invalid database in ", compiled) ; - if (!bitarray_testandset(bits, x)) total++ ; - } - } - { - char pack[total << 2 ? total << 2 : 1] ; - char *s = pack ; - uint32_t j = n ; - while (j--) if (bitarray_peek(bits, j)) - { - uint32_pack_big(s, j) ; - s += 4 ; - } - if (!cdbmake_add(&cw, toadd[i], strlen(toadd[i]), pack, total << 2)) - { - cleanup(compiled) ; - strerr_diefu1sys(111, "cdbmake_add") ; - } - } - } - cdb_free(&cr) ; - if (!cdbmake_finish(&cw) || fsync(fdw) < 0) - { - cleanup(compiled) ; - strerr_diefu3sys(111, "write to ", compiled, "/resolve.cdb.new") ; - } - close(fdw) ; - if (renameit(compiled, "resolve.cdb.new", "resolve.cdb") < 0) - { - cleanup(compiled) ; - strerr_diefu2sys(111, "rename resolve.cdb.new to resolve.cdb in ", compiled) ; - } -} - -static inline void parse_multiple (int argc, char const **argv, unsigned int *todeln, unsigned int *toaddn, char const **toadd, char const *const **toadd_contents) -{ - unsigned int m = 0 ; - int argc1 = el_semicolon(argv) ; - if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ; - *todeln = argc1 ; - argv += argc1 + 1 ; argc -= argc1 + 1 ; - while (argc) - { - toadd[m] = *argv++ ; - if (!--argc) strerr_dief1x(100, "missing bundle contents block") ; - argc1 = el_semicolon(argv) ; - if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ; - argv[argc1] = 0 ; - toadd_contents[m++] = argv ; - argv += argc1 + 1 ; argc -= argc1 + 1 ; - } - *toaddn = m ; -} - -static inline void print_help (void) -{ - static char const *help = -"s6-rc-bundle help\n" -"s6-rc-bundle add bundlename contents...\n" -"s6-rc-bundle delete bundlenames...\n" -"s6-rc-bundle multiple { to-delete } to-add { contents... } ... (execlineb syntax)\n" ; - if (buffer_putsflush(buffer_1, help) < 0) - strerr_diefu1sys(111, "write to stdout") ; -} - -static inline unsigned int lookup (char const *const *table, char const *command) -{ - unsigned int i = 0 ; - for (; table[i] ; i++) if (!strcmp(command, table[i])) break ; - return i ; -} - -static inline unsigned int parse_command (char const *command) -{ - static char const *const command_table[5] = - { - "help", - "add", - "delete", - "multiple", - 0 - } ; - unsigned int i = lookup(command_table, command) ; - if (!command_table[i]) dieusage() ; - return i ; -} - -int main (int argc, char const **argv) -{ - char const *live = S6RC_LIVEDIR ; - char const *compiled = 0 ; - unsigned int what ; - int force = 0 ; - int blocking = 0 ; - PROG = "s6-rc-bundle" ; - { - subgetopt l = SUBGETOPT_ZERO ; - for (;;) - { - int opt = subgetopt_r(argc, argv, "fl:c:b", &l) ; - if (opt == -1) break ; - switch (opt) - { - case 'f' : force = 1 ; break ; - case 'l' : live = l.arg ; break ; - case 'c' : compiled = l.arg ; break ; - case 'b' : blocking = 1 ; break ; - default : dieusage() ; - } - } - argc -= l.ind ; argv += l.ind ; - } - - if (!argc) dieusage() ; - what = parse_command(*argv++) ; - if (!what) - { - print_help() ; - return 0 ; - } - if (!--argc) dieusage() ; - if (what != 2 && argc < 2) dieusage() ; - - { - size_t livelen = strlen(live) ; - int fdcompiled = -1 ; - int compiledlock ; - s6rc_db_t dbblob ; - char compiledblob[compiled ? strlen(compiled) : livelen + 10] ; - - if (!compiled) - { - memcpy(compiledblob, live, livelen) ; - memcpy(compiledblob + livelen, "/compiled", 10) ; - compiled = compiledblob ; - } - - if (!s6rc_lock(0, 0, 0, compiled, 2, &compiledlock, blocking)) - 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, &dbblob)) - strerr_diefu3sys(111, "read ", compiled, "/n") ; - - - /* Allocate enough stack for the db */ - - { - unsigned int n = dbblob.nshort + dbblob.nlong ; - s6rc_service_t serviceblob[n] ; - char const *argvblob[dbblob.nargvs] ; - uint32_t depsblob[dbblob.ndeps << 1] ; - uint32_t producersblob[dbblob.nproducers] ; - char stringblob[dbblob.stringlen] ; - int r ; - - dbblob.services = serviceblob ; - dbblob.argvs = argvblob ; - dbblob.deps = depsblob ; - dbblob.producers = producersblob ; - dbblob.string = stringblob ; - - - /* Read the db from the file */ - - r = s6rc_db_read(fdcompiled, &dbblob) ; - if (r < 0) strerr_diefu3sys(111, "read ", compiled, "/db") ; - if (!r) strerr_dief3x(4, "invalid service database in ", compiled, "/db") ; - - - /* Perform the action */ - - switch (what) - { - case 1 : /* add */ - { - char const *const *contents = argv + 1 ; - modify_resolve(fdcompiled, &dbblob, 0, 0, argv, &contents, 1, force, compiled) ; - break ; - } - case 2 : /* delete */ - modify_resolve(fdcompiled, &dbblob, argv, argc, 0, 0, 0, force, compiled) ; - break ; - case 3 : /* multiple */ - { - unsigned int toaddn, todeln ; - char const *toadd[argc - 1] ; - char const *const *toadd_contents[argc - 1] ; - parse_multiple(argc, argv, &todeln, &toaddn, toadd, toadd_contents) ; - modify_resolve(fdcompiled, &dbblob, argv, todeln, toadd, toadd_contents, toaddn, force, compiled) ; - break ; - } - } - } - } - return 0 ; -} diff --git a/src/s6-rc/s6-rc-compile.c b/src/s6-rc/s6-rc-compile.c index 2947c14..62b9aef 100644 --- a/src/s6-rc/s6-rc-compile.c +++ b/src/s6-rc/s6-rc-compile.c @@ -23,7 +23,7 @@ #define USAGE "s6-rc-compile [ -v verbosity ] [ -h fdholder_user ] [ -b ] destdir sources..." #define dieusage() strerr_dieusage(100, USAGE) -#define dienomem() strerr_dief1x(111, "out of memory") ; +#define dienomem() strerr_dief(111, "out of memory") ; #define S6RC_INTERNALS "s6-rc-compile internals" @@ -97,8 +97,8 @@ typedef struct oneshot_s oneshot_t, *oneshot_t_ref ; struct oneshot_s { common_t common ; - unsigned int argvindex[2] ; /* pos in keep */ - unsigned int argc[2] ; + unsigned int argvindex[3] ; /* pos in keep */ + unsigned int argc[3] ; } ; typedef struct longrun_s longrun_t, *longrun_t_ref ; @@ -166,7 +166,7 @@ static int add_name_nocheck (before_t *be, char const *srcdir, char const *name, { uint32_t id ; if (verbosity >= 4) - strerr_warnt6x("from ", srcdir, ": adding identifier ", name, " of type ", typestr(type)) ; + strerr_warnt("from ", srcdir, ": adding identifier ", name, " of type ", typestr(type)) ; if (avltree_search(&names_map, name, &id)) { @@ -174,7 +174,7 @@ static int add_name_nocheck (before_t *be, char const *srcdir, char const *name, if (type == SVTYPE_UNDEFINED) { if (verbosity >= 4) - strerr_warnt4x("identifier ", name, " was already declared with type ", typestr(info->type)) ; + strerr_warnt("identifier ", name, " was already declared with type ", typestr(info->type)) ; switch (info->type) { case SVTYPE_ONESHOT : @@ -186,7 +186,7 @@ static int add_name_nocheck (before_t *be, char const *srcdir, char const *name, { info->type = type ; if (verbosity >= 4) - strerr_warnt4x("previously encountered identifier ", name, " now has type ", typestr(type)) ; + strerr_warnt("previously encountered identifier ", name, " now has type ", typestr(type)) ; switch (type) { case SVTYPE_UNDEFINED : break ; @@ -205,7 +205,7 @@ static int add_name_nocheck (before_t *be, char const *srcdir, char const *name, break ; } } - else strerr_dief6x(1, "duplicate service definition: ", name, " defined in ", srcdir, " is already defined and has type ", typestr(info->type)) ; + else strerr_dief(1, "duplicate service definition: ", name, " defined in ", srcdir, " is already defined and has type ", typestr(info->type)) ; *pos = info->pos ; *kpos = info->kpos ; return 1 ; @@ -238,7 +238,7 @@ static int add_name_nocheck (before_t *be, char const *srcdir, char const *name, static void check_identifier (char const *srcdir, char const *s) { if (!strncmp(s, "s6rc-", 5) || !strncmp(s, "s6-rc-", 6)) - strerr_dief5x(1, "in ", srcdir, ": identifier ", s, " starts with reserved prefix") ; + strerr_dief(1, "in ", srcdir, ": identifier ", s, " starts with reserved prefix") ; } static int add_name (before_t *be, char const *srcdir, char const *name, servicetype_t type, unsigned int *pos, unsigned int *kpos) @@ -286,7 +286,7 @@ static int add_namelist (before_t *be, int dfd, char const *srcdir, char const * if (fd < 0) { if (errno == ENOENT) return 0 ; - strerr_diefu6sys(111, "open ", srcdir, "/", name, "/", list) ; + strerr_diefusys(111, "open ", srcdir, "/", name, "/", list) ; } buffer_init(&b, &buffer_read, fd, buf, 2048) ; *listindex = genalloc_len(unsigned int, &be->indices) ; @@ -299,7 +299,7 @@ static int add_namelist (before_t *be, int dfd, char const *srcdir, char const * size_t i = start ; if (r < 0) { - if (errno != EPIPE) strerr_diefu6sys(111, "read ", srcdir, "/", name, "/", list) ; + if (errno != EPIPE) strerr_diefusys(111, "read ", srcdir, "/", name, "/", list) ; if (!stralloc_0(&satmp)) dienomem() ; cont = 0 ; } @@ -315,7 +315,7 @@ static int add_namelist (before_t *be, int dfd, char const *srcdir, char const * dienomem() ; } else if (verbosity >= 2) - strerr_warnw8x("in ", srcdir, "/", name, "/", list, ": name listed more than once: ", satmp.s + i) ; + strerr_warnw("in ", srcdir, "/", name, "/", list, ": name listed more than once: ", satmp.s + i) ; } satmp.len = start ; } @@ -331,7 +331,7 @@ static int add_namelistd (before_t *be, int dfd, char const *srcdir, char const if (!dir) { if (errno == ENOENT) return 0 ; - strerr_diefu6sys(111, "opendir ", srcdir, "/", name, "/", list) ; + strerr_diefusys(111, "opendir ", srcdir, "/", name, "/", list) ; } *listindex = genalloc_len(unsigned int, &be->indices) ; for (;;) @@ -346,7 +346,7 @@ static int add_namelistd (before_t *be, int dfd, char const *srcdir, char const if (!genalloc_append(unsigned int, &be->indices, &pos)) dienomem() ; } dir_close(dir) ; - if (errno) strerr_diefu4sys(111, "readdir ", srcdir, "/", list) ; + if (errno) strerr_diefusys(111, "readdir ", srcdir, "/", list) ; *n = genalloc_len(unsigned int, &be->indices) - *listindex ; return 1 ; } @@ -356,10 +356,10 @@ static void read_script (before_t *be, int dfd, char const *srcdir, char const * int r = 0 ; int fd = open_readatb(dfd, script) ; *argvindex = keep.len ; - if (fd < 0) + if (fd == -1) { if (errno != ENOENT || mandatory) - strerr_diefu6sys(111, "open ", srcdir, "/", name, "/", script) ; + strerr_diefusys(111, "open ", srcdir, "/", name, "/", script) ; } else { @@ -368,10 +368,10 @@ static void read_script (before_t *be, int dfd, char const *srcdir, char const * r = el_parse_from_buffer(&keep, &b) ; switch (r) { - case -4 : strerr_dief8x(1, "syntax error in ", srcdir, "/", name, "/", script, ": unmatched ", "}"); - case -3 : strerr_dief8x(1, "syntax error in ", srcdir, "/", name, "/", script, ": unmatched ", "{"); - case -2 : strerr_dief6x(1, "syntax error in ", srcdir, "/", name, "/", script) ; - case -1 : strerr_diefu6sys(111, "parse ", srcdir, "/", name, "/", script) ; + case -4 : strerr_dief(1, "syntax error in ", srcdir, "/", name, "/", script, ": unmatched ", "}"); + case -3 : strerr_dief(1, "syntax error in ", srcdir, "/", name, "/", script, ": unmatched ", "{"); + case -2 : strerr_dief(1, "syntax error in ", srcdir, "/", name, "/", script) ; + case -1 : strerr_diefusys(111, "parse ", srcdir, "/", name, "/", script) ; } close(fd) ; } @@ -387,7 +387,7 @@ static uint32_t read_timeout (int dfd, char const *srcdir, char const *name, cha if (r == -1) { if (errno && errno != ENOENT) - strerr_diefu6sys(111, "read ", srcdir, "/", name, "/", tname) ; + strerr_diefusys(111, "read ", srcdir, "/", name, "/", tname) ; } else { @@ -414,7 +414,7 @@ static uint32_t read_flags (int dfd, char const *srcdir, char const *name) if (access_at(dfd, files[i], F_OK, 0) < 0) { if (errno != ENOENT) - strerr_diefu6sys(111, "read ", srcdir, "/", name, "/", files[i]) ; + strerr_diefusys(111, "read ", srcdir, "/", name, "/", files[i]) ; } else flags |= 1 << i ; } @@ -439,8 +439,9 @@ static void add_common (before_t *be, int dfd, char const *srcdir, char const *n static inline void add_oneshot (before_t *be, int dfd, char const *srcdir, char const *name) { oneshot_t service ; - if (verbosity >= 3) strerr_warni3x(name, " has type ", "oneshot") ; + if (verbosity >= 3) strerr_warni(name, " has type ", "oneshot") ; add_common(be, dfd, srcdir, name, &service.common, SVTYPE_ONESHOT) ; + read_script(be, dfd, srcdir, name, "reload", &service.argvindex[2], &service.argc[2], 0) ; read_script(be, dfd, srcdir, name, "up", &service.argvindex[1], &service.argc[1], 1) ; read_script(be, dfd, srcdir, name, "down", &service.argvindex[0], &service.argc[0], 0) ; if (!genalloc_append(unsigned int, &be->indices, &be->specialdeps[0])) dienomem() ; @@ -453,7 +454,7 @@ static inline void add_oneshot (before_t *be, int dfd, char const *srcdir, char while (i--) { fmt[uint_fmt(fmt, *p)] = 0 ; - strerr_warnt7x("dependency from ", name, " to ", data.s + *p, " (", fmt, ")") ; + strerr_warnt("dependency from ", name, " to ", data.s + *p, " (", fmt, ")") ; p++ ; } } @@ -465,34 +466,34 @@ static inline void add_longrun (before_t *be, int dfd, char const *srcdir, char longrun_t service = { .srcdir = srcdir, .nproducers = 0, .prodindex = 0, .consumer = 0, .pipelinename = 0 } ; unsigned int relatedindex, n ; int fd ; - if (verbosity >= 3) strerr_warni3x(name, " has type ", "longrun") ; + if (verbosity >= 3) strerr_warni(name, " has type ", "longrun") ; add_common(be, dfd, srcdir, name, &service.common, SVTYPE_LONGRUN) ; fd = open_readat(dfd, "run") ; - if (fd < 0) + if (fd == -1) { if (errno == ENOENT) - strerr_diefu5x(1, "find a run script in ", srcdir, "/", name, "/run") ; - else strerr_diefu5sys(111, "open ", srcdir, "/", name, "/run") ; + strerr_diefu(1, "find a run script in ", srcdir, "/", name, "/run") ; + else strerr_diefusys(111, "open ", srcdir, "/", name, "/run") ; } else { struct stat st ; if (fstat(fd, &st) < 0) - strerr_diefu5sys(111, "stat ", srcdir, "/", name, "/run") ; + strerr_diefusys(111, "stat ", srcdir, "/", name, "/run") ; if (!S_ISREG(st.st_mode)) - strerr_dief4x(1, srcdir, "/", name, "/run is not a regular file") ; + strerr_dief(1, srcdir, "/", name, "/run is not a regular file") ; } close(fd) ; fd = 0 ; if (add_namelist(be, dfd, srcdir, name, "producer-for", &relatedindex, &n)) { if (n != 1) - strerr_dief5x(1, srcdir, "/", name, "/producer-for", " should only contain one service name") ; + strerr_dief(1, srcdir, "/", name, "/producer-for", " should only contain one service name") ; service.consumer = genalloc_s(unsigned int, &be->indices)[relatedindex] ; if (!genalloc_append(unsigned int, &be->indices, &be->specialdeps[1])) dienomem() ; service.common.ndeps += 2 ; if (verbosity >= 3) - strerr_warni3x(name, " is a producer for ", data.s + service.consumer) ; + strerr_warni(name, " is a producer for ", data.s + service.consumer) ; fd = 1 ; } if (add_namelist(be, dfd, srcdir, name, "consumer-for", &service.prodindex, &service.nproducers) && service.nproducers) @@ -508,14 +509,14 @@ static inline void add_longrun (before_t *be, int dfd, char const *srcdir, char } if (verbosity >= 3) for (unsigned int i = 0 ; i < service.nproducers ; i++) - strerr_warni3x(name, " is a consumer for ", data.s + genalloc_s(unsigned int, &be->indices)[service.prodindex + i]) ; + strerr_warni(name, " is a consumer for ", data.s + genalloc_s(unsigned int, &be->indices)[service.prodindex + i]) ; } if (fd == 2) { if (add_namelist(be, dfd, srcdir, name, "pipeline-name", &relatedindex, &n)) { if (n != 1) - strerr_dief5x(1, srcdir, "/", name, "/pipeline-name", " should only contain one name") ; + strerr_dief(1, srcdir, "/", name, "/pipeline-name", " should only contain one name") ; service.pipelinename = genalloc_s(unsigned int, &be->indices)[relatedindex] ; genalloc_setlen(unsigned int, &be->indices, relatedindex) ; } @@ -523,10 +524,10 @@ static inline void add_longrun (before_t *be, int dfd, char const *srcdir, char else if (access_at(dfd, "pipeline-name", F_OK, 0) < 0) { if (errno != ENOENT) - strerr_diefu5sys(111, "access ", srcdir, "/", name, "/pipeline-name") ; + strerr_diefusys(111, "access ", srcdir, "/", name, "/pipeline-name") ; } else if (verbosity) - strerr_warnw4x(srcdir, "/", name, " contains a pipeline-name file despite not being a last consumer; this file will be ignored") ; + strerr_warnw(srcdir, "/", name, " contains a pipeline-name file despite not being a last consumer; this file will be ignored") ; if (!genalloc_append(longrun_t, &be->longruns, &service)) dienomem() ; } @@ -534,25 +535,25 @@ static inline void add_bundle (before_t *be, int dfd, char const *srcdir, char c { bundle_t bundle ; unsigned int dummy ; - if (verbosity >= 3) strerr_warni3x(name, " has type ", "bundle") ; + if (verbosity >= 3) strerr_warni(name, " has type ", "bundle") ; add_name(be, srcdir, name, SVTYPE_BUNDLE, &bundle.name, &dummy) ; if (!add_namelistd(be, dfd, srcdir, name, "contents.d", &bundle.listindex, &bundle.n) && !add_namelist(be, dfd, srcdir, name, "contents", &bundle.listindex, &bundle.n)) - strerr_diefu5sys(111, "open ", srcdir, "/", name, "/contents") ; + strerr_diefusys(111, "open ", srcdir, "/", name, "/contents") ; bundle.annotation_flags = read_flags(dfd, srcdir, name) ; if (!genalloc_append(bundle_t, &be->bundles, &bundle)) dienomem() ; } static inline void add_source (before_t *be, int dfd, char const *srcdir, char const *name) { - if (verbosity >= 3) strerr_warni4x("parsing ", srcdir, "/", name) ; + if (verbosity >= 3) strerr_warni("parsing ", srcdir, "/", name) ; switch (type_check(dfd)) { - case 0 : strerr_dief6x(1, "invalid ", srcdir, "/", name, "/type", ": must be oneshot, longrun, or bundle") ; + case 0 : strerr_dief(1, "invalid ", srcdir, "/", name, "/type", ": must be oneshot, longrun, or bundle") ; case 1 : add_longrun(be, dfd, srcdir, name) ; break ; case 2 : add_oneshot(be, dfd, srcdir, name) ; break ; case 3 : add_bundle(be, dfd, srcdir, name) ; break ; - default : strerr_diefu5sys(111, "read ", srcdir, "/", name, "/type") ; + default : strerr_diefusys(111, "read ", srcdir, "/", name, "/type") ; } } @@ -561,7 +562,7 @@ static inline void add_sources (before_t *be, char const *srcdir, stralloc *sa) unsigned int n = 0 ; int fdsrc ; DIR *dir = opendir(srcdir) ; - if (!dir) strerr_diefu2sys(111, "opendir ", srcdir) ; + if (!dir) strerr_diefusys(111, "opendir ", srcdir) ; if (verbosity >= 2) strerr_warni("adding sources from ", srcdir) ; fdsrc = dir_fd(dir) ; for (;;) @@ -573,15 +574,15 @@ static inline void add_sources (before_t *be, char const *srcdir, stralloc *sa) if (!d) break ; if (d->d_name[0] == '.') continue ; if (strchr(d->d_name, '\n')) - strerr_dief3x(1, "subdirectory of ", srcdir, " contains a newline character") ; + strerr_dief(1, "subdirectory of ", srcdir, " contains a newline character") ; check_identifier(srcdir, d->d_name) ; if (stat_at(fdsrc, d->d_name, &st) < 0) - strerr_diefu4sys(111, "stat ", srcdir, "/", d->d_name) ; + strerr_diefusys(111, "stat ", srcdir, "/", d->d_name) ; if (!S_ISDIR(st.st_mode)) continue ; n++ ; if (!stralloc_catb(sa, d->d_name, strlen(d->d_name)+1)) dienomem() ; } - if (errno) strerr_diefu2sys(111, "readdir ", srcdir) ; + if (errno) strerr_diefusys(111, "readdir ", srcdir) ; if (n) { size_t pos = 0 ; @@ -595,13 +596,13 @@ static inline void add_sources (before_t *be, char const *srcdir, stralloc *sa) for (unsigned int i = 0 ; i < n ; i++) { int fd = open_readatb(fdsrc, names[i]) ; - if (fd < 0) strerr_diefu4sys(111, "open ", srcdir, "/", names[i]) ; + if (fd < 0) strerr_diefusys(111, "open ", srcdir, "/", names[i]) ; add_source(be, fd, srcdir, names[i]) ; close(fd) ; } sa->len = 0 ; } - else if (verbosity) strerr_warnw3x("source ", srcdir, " is empty") ; + else if (verbosity) strerr_warnw("source ", srcdir, " is empty") ; dir_close(dir) ; } @@ -624,16 +625,16 @@ static servicetype_t add_tree_to_bundle_rec (struct pipeline_recinfo_s *recinfo, } if (info->type != SVTYPE_LONGRUN) return info->type ; if (recinfo->bundle.n++ >= recinfo->nlong) - strerr_dief4x(1, "pipeline ", data.s + recinfo->pipelinename, " is too long: possible loop involving ", name) ; + strerr_dief(1, "pipeline ", data.s + recinfo->pipelinename, " is too long: possible loop involving ", name) ; if (verbosity >= 4) - strerr_warni4x("adding ", name, " to pipeline ", data.s + recinfo->pipelinename) ; + strerr_warni("adding ", name, " to pipeline ", data.s + recinfo->pipelinename) ; if (!genalloc_append(unsigned int, &recinfo->be->indices, &info->pos)) dienomem() ; for (unsigned int i = 0 ; i < recinfo->longruns[info->i].nproducers ; i++) { char *prodname = data.s + genalloc_s(unsigned int, &recinfo->be->indices)[recinfo->longruns[info->i].prodindex + i] ; servicetype_t type = add_tree_to_bundle_rec(recinfo, prodname) ; if (type != SVTYPE_LONGRUN) - strerr_dief6x(1, "longrun ", name, " declares a producer ", prodname, " of type ", typestr(type)) ; + strerr_dief(1, "longrun ", name, " declares a producer ", prodname, " of type ", typestr(type)) ; } return SVTYPE_LONGRUN ; } @@ -642,7 +643,7 @@ static inline void add_pipeline_bundles (before_t *be) { longrun_t const *longruns = genalloc_s(longrun_t, &be->longruns) ; unsigned int i = genalloc_len(longrun_t, &be->longruns) ; - if (verbosity >= 2) strerr_warni1x("making bundles for pipelines") ; + if (verbosity >= 2) strerr_warni("making bundles for pipelines") ; while (i--) if (longruns[i].pipelinename) { struct pipeline_recinfo_s recinfo = @@ -654,7 +655,7 @@ static inline void add_pipeline_bundles (before_t *be) .pipelinename = longruns[i].pipelinename } ; if (verbosity >= 3) - strerr_warni2x("creating bundle for pipeline ", data.s + recinfo.pipelinename) ; + strerr_warni("creating bundle for pipeline ", data.s + recinfo.pipelinename) ; { uint32_t dummy ; add_name(be, S6RC_INTERNALS, data.s + recinfo.pipelinename, SVTYPE_BUNDLE, &recinfo.bundle.name, &dummy) ; @@ -690,7 +691,7 @@ static void resolve_bundle_rec (bundle_recinfo_t *recinfo, unsigned int i) unsigned int const *listindex = recinfo->indices + me->listindex ; unsigned int j = 0 ; if (recinfo->mark[i] & 1) - strerr_dief4x(1, "cyclic bundle definition: resolution of ", data.s + recinfo->oldb[recinfo->source].name, " encountered a cycle involving ", data.s + me->name) ; + strerr_dief(1, "cyclic bundle definition: resolution of ", data.s + recinfo->oldb[recinfo->source].name, " encountered a cycle involving ", data.s + me->name) ; recinfo->mark[i] |= 1 ; for (; j < me->n ; j++) { @@ -711,7 +712,7 @@ static void resolve_bundle_rec (bundle_recinfo_t *recinfo, unsigned int i) bitarray_or(recinfo->barray + i * recinfo->nbits, recinfo->barray + i * recinfo->nbits, recinfo->barray + p->i * recinfo->nbits, recinfo->n) ; break ; default : - strerr_dief4x(1, "during resolution of bundle ", data.s + me->name, ": undefined service name ", data.s + p->pos) ; + strerr_dief(1, "during resolution of bundle ", data.s + me->name, ": undefined service name ", data.s + p->pos) ; } } recinfo->mark[i] |= 2 ; @@ -723,7 +724,7 @@ static inline unsigned int resolve_bundles (bundle_t const *oldb, bundle_t *newb unsigned int total = 0, i = 0 ; unsigned char mark[nbundles] ; bundle_recinfo_t recinfo = { .oldb = oldb, .newb = newb, .n = nshort + nlong, .nlong = nlong, .nbits = bitarray_div8(nshort + nlong), .indices = indices, .barray = barray, .mark = mark } ; - if (verbosity >= 2) strerr_warni1x("resolving bundle names") ; + if (verbosity >= 2) strerr_warni("resolving bundle names") ; memset(barray, 0, recinfo.nbits * nbundles) ; memset(mark, 0, nbundles) ; for (; i < nbundles ; i++) @@ -745,7 +746,7 @@ static inline unsigned int resolve_bundles (bundle_t const *oldb, bundle_t *newb static inline void flatlist_bundles (bundle_t *bundles, unsigned int nbundles, unsigned int nbits, unsigned char const *barray, uint32_t *bdeps) { unsigned int i = 0 ; - if (verbosity >= 3) strerr_warni1x("converting bundle array") ; + if (verbosity >= 3) strerr_warni("converting bundle array") ; for (; i < nbundles ; i++) { unsigned char const *mybits = barray + i * nbits ; @@ -773,7 +774,7 @@ static void resolve_deps (common_t const *me, unsigned int nlong, unsigned int n { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, nlong + p->i)] = 0 ; - strerr_warnt6x(keep.s + me->kname, " depends on oneshot ", data.s + p->pos, " (", fmt, ")") ; + strerr_warnt(keep.s + me->kname, " depends on oneshot ", data.s + p->pos, " (", fmt, ")") ; } break ; case SVTYPE_LONGRUN : @@ -782,7 +783,7 @@ static void resolve_deps (common_t const *me, unsigned int nlong, unsigned int n { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, p->i)] = 0 ; - strerr_warnt6x(keep.s + me->kname, " depends on longrun ", data.s + p->pos, " (", fmt, ")") ; + strerr_warnt(keep.s + me->kname, " depends on longrun ", data.s + p->pos, " (", fmt, ")") ; } break ; case SVTYPE_BUNDLE : @@ -791,11 +792,11 @@ static void resolve_deps (common_t const *me, unsigned int nlong, unsigned int n { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, nlong + p->i)] = 0 ; - strerr_warnt3x(keep.s + me->kname, " depends on bundle ", data.s + p->pos) ; + strerr_warnt(keep.s + me->kname, " depends on bundle ", data.s + p->pos) ; } break ; default : - strerr_dief4x(1, "during dependency resolution for service ", keep.s + me->kname, ": undefined service name ", data.s + p->pos) ; + strerr_dief(1, "during dependency resolution for service ", keep.s + me->kname, ": undefined service name ", data.s + p->pos) ; } } } @@ -810,7 +811,7 @@ static inline uint32_t resolve_prodcons (s6rc_longrun_t *l, longrun_t const *lon avltree_search(&names_map, data.s + longruns[n].consumer, &j) ; p = genalloc_s(nameinfo_t, &nameinfo) + j ; if (p->type != SVTYPE_LONGRUN) - strerr_dief6x(1, "longrun service ", keep.s + longruns[n].common.kname, " declares being a producer for a service named ", data.s + p->pos, " of type ", typestr(p->type)) ; + strerr_dief(1, "longrun service ", keep.s + longruns[n].common.kname, " declares being a producer for a service named ", data.s + p->pos, " of type ", typestr(p->type)) ; for (; i < longruns[p->i].nproducers ; i++) { uint32_t k ; @@ -818,11 +819,11 @@ static inline uint32_t resolve_prodcons (s6rc_longrun_t *l, longrun_t const *lon avltree_search(&names_map, data.s + indices[longruns[p->i].prodindex + i], &k) ; q = genalloc_s(nameinfo_t, &nameinfo) + k ; if (q->type != SVTYPE_LONGRUN) - strerr_dief6x(1, "longrun service ", data.s + p->pos, " declares a consumer ", data.s + q->pos, " of type ", typestr(q->type)) ; + strerr_dief(1, "longrun service ", data.s + p->pos, " declares a consumer ", data.s + q->pos, " of type ", typestr(q->type)) ; if (q->i == n) break ; } if (i == longruns[p->i].nproducers) - strerr_dief5x(1, "longrun service ", keep.s + longruns[n].common.kname, " declares being a producer for a service named ", data.s + p->pos, " that does not declare it back") ; + strerr_dief(1, "longrun service ", keep.s + longruns[n].common.kname, " declares being a producer for a service named ", data.s + p->pos, " that does not declare it back") ; l->consumer = p->i ; } else l->consumer = nlong ; @@ -835,13 +836,13 @@ static inline uint32_t resolve_prodcons (s6rc_longrun_t *l, longrun_t const *lon avltree_search(&names_map, data.s + indices[longruns[n].prodindex + i], &j) ; p = genalloc_s(nameinfo_t, &nameinfo) + j ; if (p->type != SVTYPE_LONGRUN) - strerr_dief6x(1, "longrun service ", keep.s + longruns[n].common.kname, " declares being the consumer for a service named ", data.s + p->pos, " of type ", typestr(p->type)) ; + strerr_dief(1, "longrun service ", keep.s + longruns[n].common.kname, " declares being the consumer for a service named ", data.s + p->pos, " of type ", typestr(p->type)) ; avltree_search(&names_map, data.s + longruns[p->i].consumer, &k) ; q = genalloc_s(nameinfo_t, &nameinfo) + k ; if (q->type != SVTYPE_LONGRUN) - strerr_dief6x(1, "longrun service ", data.s + p->pos, " declares a producer ", data.s + q->pos, " of type ", typestr(q->type)) ; + strerr_dief(1, "longrun service ", data.s + p->pos, " declares a producer ", data.s + q->pos, " of type ", typestr(q->type)) ; if (q->i != n) - strerr_dief5x(1, "longrun service ", keep.s + longruns[n].common.kname, " declares being the consumer for a service named ", data.s + p->pos, " that does not declare it back") ; + strerr_dief(1, "longrun service ", keep.s + longruns[n].common.kname, " declares being the consumer for a service named ", data.s + p->pos, " that does not declare it back") ; prodlist[prodindex + i] = p->i ; } l->producers = prodindex ; @@ -852,8 +853,7 @@ static inline uint32_t resolve_prodcons (s6rc_longrun_t *l, longrun_t const *lon static inline unsigned int ugly_bitarray_vertical_countones (unsigned char const *sarray, unsigned int n, unsigned int i) { unsigned int m = 0, j = 0, nbits = bitarray_div8(n) ; - for (; j < n ; j++) - if (bitarray_peek(sarray + j * nbits, i)) m++ ; + for (; j < n ; j++) if (bitarray_peek(sarray + j * nbits, i)) m++ ; return m ; } @@ -867,7 +867,7 @@ static inline void resolve_services (s6rc_db_t *db, before_t const *be, char con uint32_t prodindex = 0 ; uint32_t i = 0 ; uint32_t total[2] = { 0, 0 } ; - if (verbosity >= 2) strerr_warni1x("resolving service names") ; + if (verbosity >= 2) strerr_warni("resolving service names") ; memset(sarray, 0, nbits * n) ; for (; i < db->nlong ; i++) { @@ -889,6 +889,8 @@ static inline void resolve_services (s6rc_db_t *db, before_t const *be, char con db->services[db->nlong + i].x.oneshot.argv[0] = oneshots[i].argvindex[0] ; db->services[db->nlong + i].x.oneshot.argc[1] = oneshots[i].argc[1] ; db->services[db->nlong + i].x.oneshot.argv[1] = oneshots[i].argvindex[1] ; + db->services[db->nlong + i].x.oneshot.argc[2] = oneshots[i].argc[2] ; + db->services[db->nlong + i].x.oneshot.argv[2] = oneshots[i].argvindex[2] ; resolve_deps(&oneshots[i].common, db->nlong, n, nbits, indices, sarray + (db->nlong + i) * nbits, barray) ; } @@ -903,7 +905,7 @@ static inline void resolve_services (s6rc_db_t *db, before_t const *be, char con } if (total[0] != total[1]) - strerr_dief1x(101, "database inconsistency: dependencies and reverse dependencies do not match. Please submit a bug-report.") ; + strerr_dief(101, "database inconsistency: dependencies and reverse dependencies do not match. Please submit a bug-report.") ; db->ndeps = total[1] ; } @@ -914,7 +916,7 @@ static inline void flatlist_services (s6rc_db_t *db, unsigned char const *sarray diuint32 problem ; unsigned int i = 0 ; int r ; - if (verbosity >= 3) strerr_warni1x("converting service dependency array") ; + if (verbosity >= 3) strerr_warni("converting service dependency array") ; for (; i < n ; i++) { uint32_t *mydeps = db->deps + db->services[i].deps[0] ; @@ -927,16 +929,16 @@ static inline void flatlist_services (s6rc_db_t *db, unsigned char const *sarray if (bitarray_peek(sarray + i * nbits, j)) mydeps[k++] = j ; } - if (verbosity >= 3) strerr_warni1x("checking database correctness") ; + if (verbosity >= 3) strerr_warni("checking database correctness") ; if (s6rc_db_check_depcycles(db, 1, &problem)) - strerr_dief5x(1, "cyclic service dependency", " reached from ", db->string + db->services[problem.left].name, " and involving ", db->string + db->services[problem.right].name) ; + strerr_dief(1, "cyclic service dependency", " reached from ", db->string + db->services[problem.left].name, " and involving ", db->string + db->services[problem.right].name) ; r = s6rc_db_check_pipelines(db, &problem) ; if (r) { if (r == 1) - strerr_dief5x(1, "cyclic longrun pipeline", " reached from ", db->string + db->services[problem.left].name, " and involving ", db->string + db->services[problem.right].name) ; + strerr_dief(1, "cyclic longrun pipeline", " reached from ", db->string + db->services[problem.left].name, " and involving ", db->string + db->services[problem.right].name) ; else - strerr_dief5x(1, "longrun pipeline collision", " reached from ", db->string + db->services[problem.left].name, " and involving ", db->string + db->services[problem.right].name) ; + strerr_dief(1, "longrun pipeline collision", " reached from ", db->string + db->services[problem.left].name, " and involving ", db->string + db->services[problem.right].name) ; } } @@ -969,7 +971,7 @@ static void auto_dir (char const *compiled, char const *dir) if (mkdir(fn, 0755) < 0) { cleanup(compiled) ; - strerr_diefu2sys(111, "mkdir ", fn) ; + strerr_diefusys(111, "mkdir ", fn) ; } } @@ -984,7 +986,7 @@ static void auto_file (char const *compiled, char const *file, char const *s, un if (!openwritenclose_unsafe(fn, s, n)) { cleanup(compiled) ; - strerr_diefu2sys(111, "write to ", fn) ; + strerr_diefusys(111, "write to ", fn) ; } } @@ -999,7 +1001,7 @@ static void auto_symlink (char const *compiled, char const *name, char const *ta if (symlink(target, fn) < 0) { cleanup(compiled) ; - strerr_diefu4sys(111, "symlink ", target, " to ", fn) ; + strerr_diefusys(111, "symlink ", target, " to ", fn) ; } } @@ -1014,7 +1016,7 @@ static void auto_rights (char const *compiled, char const *file, mode_t mode) if (chmod(fn, mode) < 0) { cleanup(compiled) ; - strerr_diefu2sys(111, "chmod ", fn) ; + strerr_diefusys(111, "chmod ", fn) ; } } @@ -1022,16 +1024,16 @@ static inline void init_compiled (char const *compiled) { int compiledlock ; if (mkdir(compiled, 0755) < 0) - strerr_diefu2sys(111, "mkdir ", compiled) ; + strerr_diefusys(111, "mkdir ", compiled) ; if (!s6rc_lock(0, 0, 0, compiled, 2, &compiledlock, 0)) - strerr_diefu2sys(111, "take lock on ", compiled) ; + strerr_diefusys(111, "take lock on ", compiled) ; auto_dir(compiled, "servicedirs") ; } static inline void write_sizes (char const *compiled, s6rc_db_t const *db) { char pack[24] ; - if (verbosity >= 3) strerr_warni3x("writing ", compiled, "/n") ; + if (verbosity >= 3) strerr_warni("writing ", compiled, "/n") ; uint32_pack_big(pack, (uint32_t)db->nshort) ; uint32_pack_big(pack + 4, (uint32_t)db->nlong) ; uint32_pack_big(pack + 8, (uint32_t)db->stringlen) ; @@ -1078,7 +1080,7 @@ static inline void write_oneshot_runner (char const *compiled, int blocking) size_t base = satmp.len ; make_skel(compiled, S6RC_ONESHOT_RUNNER, 3) ; if (!stralloc_cats(&satmp, "#!" - EXECLINE_SHEBANGPREFIX "execlineb -P\n" + EXECLINE_SHEBANGPREFIX "execlineb -s1\n" EXECLINE_EXTBINPREFIX "fdmove -c 2 1\n" EXECLINE_EXTBINPREFIX "fdmove 1 3\n" S6_EXTBINPREFIX "s6-ipcserver-socketbinder -- s\n" @@ -1087,7 +1089,11 @@ static inline void write_oneshot_runner (char const *compiled, int blocking) S6_EXTBINPREFIX "s6-sudod -t 30000 --\n" S6RC_EXTLIBEXECPREFIX "s6-rc-oneshot-run -l ../.. ") || (blocking && !stralloc_cats(&satmp, "-b ")) - || !stralloc_cats(&satmp, "--\n")) dienomem() ; + || !stralloc_cats(&satmp, "--\n")) + { + cleanup(compiled) ; + dienomem() ; + } auto_file(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER "/run", satmp.s + base, satmp.len - base) ; satmp.len = base ; auto_rights(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER "/run", 0755) ; @@ -1117,7 +1123,7 @@ static inline void write_fdholder (char const *compiled, s6rc_db_t const *db, ch if (db->services[j].x.longrun.nproducers) { if (!stralloc_cats(&satmp, db->string + db->services[j].name) - || !stralloc_catb(&satmp, "\n", 1)) dienomem() ; + || !stralloc_catb(&satmp, "\n", 1)) goto err ; nfds += 2 ; } if (nfds < 240) nfds = 256 ; else nfds += (nfds >> 4) + 2 ; @@ -1126,7 +1132,7 @@ static inline void write_fdholder (char const *compiled, s6rc_db_t const *db, ch satmp.len = base ; if (!stralloc_cats(&satmp, - "#!" EXECLINE_SHEBANGPREFIX "execlineb -P\n" + "#!" EXECLINE_SHEBANGPREFIX "execlineb -s1\n" EXECLINE_EXTBINPREFIX "pipeline -dw --\n{\n " EXECLINE_EXTBINPREFIX "if --\n {\n " EXECLINE_EXTBINPREFIX "forstdin -x0 -- i\n " @@ -1135,28 +1141,33 @@ static inline void write_fdholder (char const *compiled, s6rc_db_t const *db, ch EXECLINE_EXTBINPREFIX "redirfd -r 0 ./data/autofilled\n " S6_EXTBINPREFIX "s6-ipcclient -l0 -- s\n " S6RC_EXTLIBEXECPREFIX "s6-rc-fdholder-filler -1 --\n }\n " - S6_EXTBINPREFIX "s6-svc -t .\n}\n")) dienomem() ; + S6_EXTBINPREFIX "s6-svc -t .\n}\n")) goto err ; if (fdhuser) { if (!stralloc_cats(&satmp, S6_EXTBINPREFIX "s6-envuidgid -i -- ") || !string_quote(&satmp, fdhuser, strlen(fdhuser)) - || !stralloc_catb(&satmp, "\n", 1)) dienomem() ; + || !stralloc_catb(&satmp, "\n", 1)) goto err ; } - if (!stralloc_cats(&satmp, S6_EXTBINPREFIX "s6-fdholder-daemon -1 -n ")) dienomem() ; + if (!stralloc_cats(&satmp, S6_EXTBINPREFIX "s6-fdholder-daemon -1 -n ")) goto err ; { char fmt[UINT_FMT] ; size_t len = uint_fmt(fmt, nfds) ; fmt[len++] = ' ' ; - if (!stralloc_catb(&satmp, fmt, len)) dienomem() ; + if (!stralloc_catb(&satmp, fmt, len)) goto err ; } if (fdhuser) { - if (!stralloc_cats(&satmp, "-U ")) dienomem() ; + if (!stralloc_cats(&satmp, "-U ")) goto err ; } - if (!stralloc_cats(&satmp, "-i data/rules -- s\n")) dienomem() ; + if (!stralloc_cats(&satmp, "-i data/rules -- s\n")) goto err ; auto_file(compiled, "servicedirs/" S6RC_FDHOLDER "/run", satmp.s + base, satmp.len - base) ; satmp.len = base ; auto_rights(compiled, "servicedirs/" S6RC_FDHOLDER "/run", 0755) ; + return ; + + err: + cleanup(compiled) ; + dienomem() ; } static inline void write_resolve (char const *compiled, s6rc_db_t const *db, bundle_t const *bundles, unsigned int nbundles, uint32_t const *bdeps) @@ -1166,19 +1177,19 @@ static inline void write_resolve (char const *compiled, s6rc_db_t const *db, bun cdbmaker c = CDBMAKER_ZERO ; unsigned int i = db->nshort + db->nlong ; char fn[clen + 13] ; - if (verbosity >= 3) strerr_warni3x("writing ", compiled, "/resolve.cdb") ; + if (verbosity >= 3) strerr_warni("writing ", compiled, "/resolve.cdb") ; memcpy(fn, compiled, clen) ; memcpy(fn + clen, "/resolve.cdb", 13) ; fd = open_trunc(fn) ; if (fd < 0 || ndelay_off(fd) < 0) { cleanup(compiled) ; - strerr_diefu2sys(111, "open_trunc ", fn) ; + strerr_diefusys(111, "open_trunc ", fn) ; } if (!cdbmake_start(&c, fd)) { cleanup(compiled) ; - strerr_diefu2sys(111, "cdbmake_start on ", fn) ; + strerr_diefusys(111, "cdbmake_start on ", fn) ; } /* atomic services */ @@ -1189,7 +1200,7 @@ static inline void write_resolve (char const *compiled, s6rc_db_t const *db, bun if (!cdbmake_add(&c, db->string + db->services[i].name, strlen(db->string + db->services[i].name), pack, 4)) { cleanup(compiled) ; - strerr_diefu1sys(111, "cdbmake_add") ; + strerr_diefusys(111, "cdbmake_add") ; } } @@ -1204,14 +1215,14 @@ static inline void write_resolve (char const *compiled, s6rc_db_t const *db, bun if (!cdbmake_add(&c, data.s + bundles[i].name, strlen(data.s + bundles[i].name), pack, bundles[i].n << 2)) { cleanup(compiled) ; - strerr_diefu1sys(111, "cdbmake_add") ; + strerr_diefusys(111, "cdbmake_add") ; } } if (!cdbmake_finish(&c)) { cleanup(compiled) ; - strerr_diefu2sys(111, "write to ", fn) ; + strerr_diefusys(111, "write to ", fn) ; } close(fd) ; } @@ -1223,17 +1234,17 @@ static int dircopy (char const *compiled, char const *srcfn, char const *dstfn) { if (errno == ENOENT) return 0 ; cleanup(compiled) ; - strerr_diefu2sys(111, "stat ", srcfn) ; + strerr_diefusys(111, "stat ", srcfn) ; } if (!S_ISDIR(st.st_mode)) { cleanup(compiled) ; - strerr_dief2x(1, srcfn, " is not a directory") ; + strerr_dief(1, srcfn, " is not a directory") ; } if (!hiercopy(srcfn, dstfn)) { cleanup(compiled) ; - strerr_diefu4sys(111, "recursively copy ", srcfn, " to ", dstfn) ; + strerr_diefusys(111, "recursively copy ", srcfn, " to ", dstfn) ; } return 1 ; } @@ -1241,12 +1252,12 @@ static int dircopy (char const *compiled, char const *srcfn, char const *dstfn) static void write_exe_wrapper (char const *compiled, char const *fn, s6rc_db_t const *db, unsigned int i, char const *exe) { size_t base = satmp.len ; - if (!stralloc_cats(&satmp, "#!" EXECLINE_SHEBANGPREFIX "execlineb -S0\n")) dienomem() ; + if (!stralloc_cats(&satmp, "#!" EXECLINE_SHEBANGPREFIX "execlineb -S0\n")) goto err ; if (db->services[i].x.longrun.nproducers) { if (!stralloc_cats(&satmp, S6_EXTBINPREFIX "s6-fdholder-retrieve ../s6rc-fdholder/s \"pipe:s6rc-r-") || !string_quote_nodelim(&satmp, db->string + db->services[i].name, strlen(db->string + db->services[i].name)) - || !stralloc_cats(&satmp, "\"\n")) dienomem() ; + || !stralloc_cats(&satmp, "\"\n")) goto err ; } if (db->services[i].x.longrun.consumer < db->nlong) { @@ -1255,23 +1266,28 @@ static void write_exe_wrapper (char const *compiled, char const *fn, s6rc_db_t c S6_EXTBINPREFIX "s6-fdholder-retrieve ../s6rc-fdholder/s \"pipe:s6rc-w-") || !string_quote_nodelim(&satmp, consumername, strlen(consumername)) || !stralloc_cats(&satmp, "\"\n" - EXECLINE_EXTBINPREFIX "fdswap 0 1\n")) dienomem() ; + EXECLINE_EXTBINPREFIX "fdswap 0 1\n")) goto err ; } if (!stralloc_cats(&satmp, "./") || !stralloc_cats(&satmp, exe) - || !stralloc_cats(&satmp, ".user $@\n")) dienomem() ; + || !stralloc_cats(&satmp, ".user $@\n")) goto err ; auto_file(compiled, fn, satmp.s + base, satmp.len - base) ; satmp.len = base ; auto_rights(compiled, fn, 0755) ; + return ; + + err: + cleanup(compiled) ; + dienomem() ; } static int copy_uint (char const *compiled, char const *srcfn, char const *dstfn, unsigned int *u) { int r = s6rc_read_uint(srcfn, u) ; - if (r < 0) + if (r == -1) { cleanup(compiled) ; - strerr_diefu2sys(111, "read ", srcfn) ; + strerr_diefusys(111, "read ", srcfn) ; } if (r) { @@ -1281,12 +1297,12 @@ static int copy_uint (char const *compiled, char const *srcfn, char const *dstfn if (!openwritenclose_unsafe(dstfn, fmt, len)) { cleanup(compiled) ; - strerr_diefu2sys(111, "write to ", dstfn) ; + strerr_diefusys(111, "write to ", dstfn) ; } if (chmod(dstfn, 0644) == -1) { cleanup(compiled) ; - strerr_diefu2sys(111, "set permissions on ", dstfn) ; + strerr_diefusys(111, "set permissions on ", dstfn) ; } return 1 ; } @@ -1299,13 +1315,13 @@ static int copy_empty (char const *compiled, char const *srcfn, char const *dstf { if (errno == ENOENT) return 0 ; cleanup(compiled) ; - strerr_diefu2sys(111, "access ", srcfn) ; + strerr_diefusys(111, "access ", srcfn) ; } if (!openwritenclose_unsafe(dstfn, "", 0)) { cleanup(compiled) ; - strerr_diefu2sys(111, "create ", dstfn) ; + strerr_diefusys(111, "create ", dstfn) ; } return 1 ; } @@ -1314,7 +1330,7 @@ static inline void write_servicedirs (char const *compiled, s6rc_db_t const *db, { size_t clen = strlen(compiled) ; unsigned int i = 2 ; - if (verbosity >= 3) strerr_warni3x("writing ", compiled, "/servicedirs") ; + if (verbosity >= 3) strerr_warni("writing ", compiled, "/servicedirs") ; for (; i < db->nlong ; i++) { size_t srcdirlen = strlen(srcdirs[i]) ; @@ -1330,7 +1346,7 @@ static inline void write_servicedirs (char const *compiled, s6rc_db_t const *db, if (mkdir(dstfn, 0755) < 0) { cleanup(compiled) ; - strerr_diefu2sys(111, "mkdir ", dstfn) ; + strerr_diefusys(111, "mkdir ", dstfn) ; } dstfn[clen + len + 13] = '/' ; memcpy(srcfn, srcdirs[i], srcdirlen) ; @@ -1350,7 +1366,7 @@ static inline void write_servicedirs (char const *compiled, s6rc_db_t const *db, if (!filecopy_unsafe(srcfn, dstfn, 0755)) { cleanup(compiled) ; - strerr_diefu4sys(111, "copy ", srcfn, " to ", dstfn) ; + strerr_diefusys(111, "copy ", srcfn, " to ", dstfn) ; } } @@ -1364,7 +1380,7 @@ static inline void write_servicedirs (char const *compiled, s6rc_db_t const *db, if (!filecopy_unsafe(srcfn, dstfn, 0755)) { cleanup(compiled) ; - strerr_diefu4sys(111, "copy ", srcfn, " to ", dstfn) ; + strerr_diefusys(111, "copy ", srcfn, " to ", dstfn) ; } memcpy(srcfn + srcdirlen + len + 2, "notification-fd", 16) ; @@ -1377,7 +1393,7 @@ static inline void write_servicedirs (char const *compiled, s6rc_db_t const *db, { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, u)] = 0 ; - strerr_warnw4x("longrun ", db->string + db->services[i].name, " has a notification-fd of ", fmt) ; + strerr_warnw("longrun ", db->string + db->services[i].name, " has a notification-fd of ", fmt) ; } } else fdnotif = u ; @@ -1393,7 +1409,7 @@ static inline void write_servicedirs (char const *compiled, s6rc_db_t const *db, { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, u)] = 0 ; - strerr_warnw4x("longrun ", db->string + db->services[i].name, " has a lock-fd of ", fmt) ; + strerr_warnw("longrun ", db->string + db->services[i].name, " has a lock-fd of ", fmt) ; } } else if (fdnotif == u) @@ -1423,6 +1439,10 @@ static inline void write_servicedirs (char const *compiled, s6rc_db_t const *db, memcpy(dstfn + clen + 14 + len, "down-signal", 12) ; filecopy_unsafe(srcfn, dstfn, 0644) ; + memcpy(srcfn + srcdirlen + len + 2, "reload-signal", 14) ; + memcpy(dstfn + clen + 14 + len, "reload-signal", 14) ; + filecopy_unsafe(srcfn, dstfn, 0644) ; + memcpy(srcfn + srcdirlen + len + 2, "flag-newpidns", 14) ; memcpy(dstfn + clen + 14 + len, "flag-newpidns", 14) ; copy_empty(compiled, srcfn, dstfn) ; @@ -1435,13 +1455,13 @@ static inline void write_servicedirs (char const *compiled, s6rc_db_t const *db, if (mkdir(dstfn, 0755) == -1) { cleanup(compiled) ; - strerr_diefu2sys(111, "mkdir ", dstfn) ; + strerr_diefusys(111, "mkdir ", dstfn) ; } dstfn[clen + 22 + len] = 0 ; if (mkdir(dstfn, 0755) == -1) { cleanup(compiled) ; - strerr_diefu2sys(111, "mkdir ", dstfn) ; + strerr_diefusys(111, "mkdir ", dstfn) ; } } @@ -1457,7 +1477,7 @@ static inline void write_servicedirs (char const *compiled, s6rc_db_t const *db, static int write_service (buffer *b, s6rc_service_t const *sv, int type) { - char pack[49] ; + char pack[57] ; unsigned int m ; uint32_pack_big(pack, sv->name) ; uint32_pack_big(pack + 4, sv->flags) ; @@ -1480,7 +1500,9 @@ static int write_service (buffer *b, s6rc_service_t const *sv, int type) uint32_pack_big(pack + 36, sv->x.oneshot.argv[0]) ; uint32_pack_big(pack + 40, sv->x.oneshot.argc[1]) ; uint32_pack_big(pack + 44, sv->x.oneshot.argv[1]) ; - m = 48 ; + uint32_pack_big(pack + 48, sv->x.oneshot.argc[2]) ; + uint32_pack_big(pack + 52, sv->x.oneshot.argv[2]) ; + m = 56 ; } pack[m++] = '\376' ; return (buffer_put(b, pack, m) == m) ; @@ -1495,24 +1517,24 @@ static inline void write_db (char const *compiled, s6rc_db_t const *db) char dbfn[clen + 4] ; memcpy(dbfn, compiled, clen) ; memcpy(dbfn + clen, "/db", 4) ; - if (verbosity >= 3) strerr_warni2x("writing ", dbfn) ; + if (verbosity >= 3) strerr_warni("writing ", dbfn) ; fd = open_trunc(dbfn) ; - if (fd < 0) + if (fd == -1) { cleanup(compiled) ; - strerr_diefu3sys(111, "open ", dbfn, " for writing") ; + strerr_diefusys(111, "open ", dbfn, " for writing") ; } - if (ndelay_off(fd) < 0) + if (ndelay_off(fd) == -1) { cleanup(compiled) ; - strerr_diefu2sys(111, "ndelay_off ", dbfn) ; + strerr_diefusys(111, "ndelay_off ", dbfn) ; } buffer_init(&b, &buffer_write, fd, buf, 4096) ; - if (buffer_put(&b, S6RC_DB_BANNER_START, S6RC_DB_BANNER_START_LEN) < 0) + if (buffer_put(&b, S6RC_DB_BANNER_START, S6RC_DB_BANNER_START_LEN) < S6RC_DB_BANNER_START_LEN) goto err ; - if (buffer_put(&b, db->string, db->stringlen) < 0) goto err ; + if (buffer_put(&b, db->string, db->stringlen) < db->stringlen) goto err ; { unsigned int i = db->ndeps << 1 ; @@ -1540,14 +1562,15 @@ static inline void write_db (char const *compiled, s6rc_db_t const *db) while (i--) if (!write_service(&b, sv++, 0)) goto err ; } - if (buffer_putflush(&b, S6RC_DB_BANNER_END, S6RC_DB_BANNER_END_LEN) < 0) + if (buffer_putflush(&b, S6RC_DB_BANNER_END, S6RC_DB_BANNER_END_LEN) < S6RC_DB_BANNER_END_LEN) goto err ; close(fd) ; return ; + err: cleanup(compiled) ; - strerr_diefu2sys(111, "write to ", dbfn) ; + strerr_diefusys(111, "write to ", dbfn) ; } static inline void write_compiled ( @@ -1560,7 +1583,7 @@ static inline void write_compiled ( char const *fdhuser, int blocking) { - if (verbosity >= 2) strerr_warni2x("writing compiled information to ", compiled) ; + if (verbosity >= 2) strerr_warni("writing compiled information to ", compiled) ; init_compiled(compiled) ; write_sizes(compiled, db) ; write_resolve(compiled, db, bundles, nbundles, bdeps) ; @@ -1595,7 +1618,7 @@ int main (int argc, char const *const *argv) if (wgola[GOLA_VERBOSITY]) { if (!uint0_scan(wgola[GOLA_VERBOSITY], &verbosity)) - strerr_dief1x(100, "verbosity must be an unsigned integer") ; + strerr_dief(100, "verbosity must be an unsigned integer") ; } compiled = *argv++ ; diff --git a/src/s6-rc/s6-rc-format-upgrade.c b/src/s6-rc/s6-rc-format-upgrade.c index e7e29b5..eeb3c18 100644 --- a/src/s6-rc/s6-rc-format-upgrade.c +++ b/src/s6-rc/s6-rc-format-upgrade.c @@ -1,10 +1,12 @@ /* ISC license. */ #include <string.h> +#include <unistd.h> #include <skalibs/types.h> +#include <skalibs/prog.h> #include <skalibs/strerr.h> -#include <skalibs/sgetopt.h> +#include <skalibs/gol.h> #include <skalibs/tai.h> #include <skalibs/unix-transactional.h> @@ -14,6 +16,19 @@ #define USAGE "s6-rc-format-upgrade [ -v verbosity ] [ -t timeout ] [ -l live ] [ -b ] newdb" #define dieusage() strerr_dieusage(100, USAGE) +enum golb_e +{ + GOLB_BLOCK = 0x01, +} ; + +enum gola_e +{ + GOLA_VERBOSITY, + GOLA_LIVEDIR, + GOLA_TIMEOUT, + GOLA_N +} ; + static unsigned int verbosity = 1 ; @@ -26,47 +41,53 @@ static inline void update_livedir (char const *live, char const *newcompiled, ta memcpy(cfn, live, livelen) ; memcpy(cfn + livelen, "/compiled", 10) ; if (!atomic_symlink4(newcompiled, cfn, 0, 0)) - strerr_diefu4sys(111, "atomic_symlink4 ", cfn, " to ", newcompiled) ; + strerr_diefusys(111, "atomic_symlink4 ", cfn, " to ", newcompiled) ; } - int main (int argc, char const *const *argv, char const *const *envp) { - tain deadline ; - char const *live = S6RC_LIVEDIR ; - int blocking = 0 ; + static gol_bool const rgolb[] = + { + { .so = 'b', .lo = "block", .clear = 0, .set = GOLB_BLOCK }, + } ; + static gol_arg const rgola[] = + { + { .so = 'v', .lo = "verbosity", .i = GOLA_VERBOSITY }, + { .so = 'l', .lo = "livedir", .i = GOLA_LIVEDIR }, + { .so = 't', .lo = "timeout", .i = GOLA_TIMEOUT }, + } ; + uint64_t wgolb = 0 ; + char const *wgola[GOLA_N] = { 0 } ; + tain deadline = TAIN_INFINITE_RELATIVE ; int livelock ; + wgola[GOLA_LIVEDIR] = S6RC_LIVEDIR ; PROG = "s6-rc-format-upgrade" ; + + { + unsigned int golc = GOL_main(argc, argv, rgolb, rgola, &wgolb, wgola) ; + argc -= golc ; argv += golc ; + } + + if (wgola[GOLA_VERBOSITY] && !uint0_scan(wgola[GOLA_VERBOSITY], &verbosity)) + strerr_dief(100, "verbosity", " must be an unsigned integer") ; + if (wgola[GOLA_TIMEOUT]) { - unsigned int t = 0 ; - subgetopt l = SUBGETOPT_ZERO ; - for (;;) - { - int opt = subgetopt_r(argc, argv, "v:t:l:b", &l) ; - if (opt == -1) break ; - switch (opt) - { - case 'v' : if (!uint0_scan(l.arg, &verbosity)) dieusage() ; break ; - case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ; - case 'l' : live = l.arg ; break ; - case 'b' : blocking = 1 ; break ; - default : dieusage() ; - } - } - argc -= l.ind ; argv += l.ind ; + unsigned int t ; + if (!uint0_scan(wgola[GOLA_TIMEOUT], &t)) + strerr_dief(100, "timeout", " must be an unsigned integer") ; if (t) tain_from_millisecs(&deadline, t) ; - else deadline = tain_infinite_relative ; } + if (!argc) dieusage() ; if (argv[0][0] != '/') - strerr_dief2x(100, argv[0], " is not an absolute path") ; + strerr_dief(100, argv[0], " is not an absolute path") ; tain_now_set_stopwatch_g() ; tain_add_g(&deadline, &deadline) ; - if (!s6rc_lock(live, 2, &livelock, 0, 0, 0, blocking)) - strerr_diefu2sys(111, "take lock on ", live) ; + if (!s6rc_lock(wgola[GOLA_LIVEDIR], 2, &livelock, 0, 0, 0, wgolb & GOLB_BLOCK)) + strerr_diefusys(111, "take lock on ", wgola[GOLA_LIVEDIR]) ; - update_livedir(live, argv[0], &deadline) ; - return 0 ; + update_livedir(wgola[GOLA_LIVEDIR], argv[0], &deadline) ; + _exit(0) ; } diff --git a/src/s6-rc/s6-rc-init.c b/src/s6-rc/s6-rc-init.c index b1a9624..7d41584 100644 --- a/src/s6-rc/s6-rc-init.c +++ b/src/s6-rc/s6-rc-init.c @@ -178,6 +178,7 @@ int main (int argc, char const *const *argv) if (!argc) dieusage() ; if (argv[0][0] != '/') strerr_dief(100, "scandir", " must be an absolute path") ; + if (wgola[GOLA_LIVEDIR][0] != '/') strerr_dief(100, "livedir", " must be an absolute path") ; if (wgola[GOLA_TIMEOUT]) { unsigned int t = 0 ; @@ -212,7 +213,7 @@ int main (int argc, char const *const *argv) { size_t llen = strlen(wgola[GOLA_LIVEDIR]) ; char *d = strrchr(wgola[GOLA_LIVEDIR], '/') ; - if (!d || d == wgola[GOLA_LIVEDIR]) strerr_dief(102, "invalid existing livedir: ", wgola[GOLA_LIVEDIR]) ; + if (d == wgola[GOLA_LIVEDIR]) strerr_dief(102, "invalid existing livedir: ", wgola[GOLA_LIVEDIR]) ; dirlen = d - wgola[GOLA_LIVEDIR] ; if (find_livedir(wgola[GOLA_LIVEDIR], llen, dirlen, argv[0], wgola[GOLA_PREFIX], wgola[GOLA_BOOTDB], &sa)) { diff --git a/src/s6-rc/s6-rc-oneshot-run.c b/src/s6-rc/s6-rc-oneshot-run.c index dc7bf06..baa0609 100644 --- a/src/s6-rc/s6-rc-oneshot-run.c +++ b/src/s6-rc/s6-rc-oneshot-run.c @@ -14,14 +14,12 @@ #include <s6-rc/config.h> #include <s6-rc/s6rc.h> -#define USAGE "s6-rc-oneshot-run [ -l live ] [ -b ] up|down servicenumber" +#define USAGE "s6-rc-oneshot-run [ -l live ] [ -b ] up|down|reload servicenumber" #define dieusage() strerr_dieusage(100, USAGE) enum golb_e { - GOLB_UP = 0x01, - GOLB_BLOCK = 0x02, - GOLB_RELOAD = 0x04, + GOLB_BLOCK = 0x01, } ; enum gola_e @@ -41,19 +39,19 @@ int main (int argc, char const *const *argv) { { .so = 'l', .lo = "livedir", .i = GOLA_LIVEDIR }, } ; + static char const *const whatstr[3] = { "down", "up", "reload" } ; uint64_t wgolb = 0 ; char const *wgola[GOLA_N] = { [GOLA_LIVEDIR] = S6RC_LIVEDIR } ; unsigned int number ; + unsigned int what = 0 ; PROG = "s6-rc-oneshot-run" ; number = GOL_main(argc, argv, rgolb, rgola, &wgolb, wgola) ; argc -= number ; argv += number ; if (argc < 2) dieusage() ; - if (!strcasecmp(argv[0], "up")) wgolb |= GOLB_UP ; - else if (!strcasecmp(argv[0], "down")) wgolb &= ~GOLB_UP ; - else if (!strcasecmp(argv[0], "reload")) wgolb |= GOLB_UP | GOLB_RELOAD ; - else dieusage() ; + for (; what < 3 ; what++) if (!strcmp(argv[0], whatstr[what])) break ; + if (what >= 3) dieusage() ; if (!uint0_scan(argv[1], &number)) dieusage() ; { @@ -105,23 +103,15 @@ int main (int argc, char const *const *argv) close(fdcompiled) ; close(compiledlock) ; + /* Run the script */ - { - s6rc_service_t const *sv = db.services + number ; - unsigned int namelen = strlen(db.string + sv->name) ; - unsigned int sargc = sv->x.oneshot.argc[!!(wgolb & GOLB_UP)] ; - char const *const *sargv = db.argvs + sv->x.oneshot.argv[!!(wgolb & GOLB_UP)] ; - char const *newargv[sargc + 1] ; - char const **p = newargv ; - char modif[namelen + 21] ; - memcpy(modif, "RC_NAME=", 8) ; - memcpy(modif + 8, db.string + sv->name, namelen + 1) ; - if (wgolb & GOLB_RELOAD) memcpy(modif + 9 + namelen, "RC_RELOAD=1", 12) ; - while (sargc--) *p++ = *sargv++ ; - *p = 0 ; - xmexec0_n(newargv, modif, namelen + (wgolb & GOLB_RELOAD ? 21 : 9), 1 + !!(wgolb & GOLB_RELOAD)) ; - } + s6rc_service_t const *sv = db.services + number ; + size_t namelen = strlen(db.string + sv->name) ; + char modif[namelen + 9] ; + memcpy(modif, "RC_NAME=", 8) ; + memcpy(modif + 8, db.string + sv->name, namelen + 1) ; + xmexec0_n(db.argvs + sv->x.oneshot.argv[what], modif, namelen + 9, 1) ; } } } diff --git a/src/s6-rc/s6-rc.c b/src/s6-rc/s6-rc.c index b74b902..38f4a13 100644 --- a/src/s6-rc/s6-rc.c +++ b/src/s6-rc/s6-rc.c @@ -80,6 +80,20 @@ static tain deadline = TAIN_INFINITE_RELATIVE ; static int lameduck = 0 ; static char dryrun[UINT_FMT] = "" ; + /* + state bits: + - exported to state file + 0x01 - up or down + 0x02 - explicitly wanted up + 0x04 - unused + 0x08 - unused + - not exported, reserved for s6-rc internal work + 0x10 - in the selection + 0x20 - mark for recursive stuff + 0x40 - unused + 0x80 - unused + */ + static inline void announce (void) { unsigned int i = n ; @@ -88,9 +102,9 @@ static inline void announce (void) if (dryrun[0]) return ; memcpy(fn, live, livelen) ; memcpy(fn + livelen, "/state", 7) ; - while (i--) tmpstate[i] = !!(state[i] & 1) ; + while (i--) tmpstate[i] = state[i] & 0x0f ; if (!openwritenclose_suffix(fn, tmpstate, n, ".new")) - strerr_diefu2sys(111, "write ", fn) ; + strerr_diefusys(111, "write ", fn) ; } static inline int print_services (void) @@ -98,7 +112,7 @@ static inline int print_services (void) for (unsigned int i = 0 ; i < n ; i++) { if (wgolb & GOLB_HIDEESSENTIALS && db->services[i].flags & S6RC_DB_FLAG_ESSENTIAL) continue ; - if (state[i] & 2) + if (state[i] & 0x10) { if (buffer_puts(buffer_1, db->string + db->services[i].name) < 0 || buffer_put(buffer_1, "\n", 1) < 0) goto err ; @@ -108,7 +122,7 @@ static inline int print_services (void) return 0 ; err: - strerr_diefu1sys(111, "write to stdout") ; + strerr_diefusys(111, "write to stdout") ; } static inline int print_diff (void) @@ -124,7 +138,7 @@ static inline int print_diff (void) memcpy(fn + livelen, "/servicedirs/", 13) ; memcpy(fn + livelen + 13, db->string + db->services[i].name, namelen + 1) ; if (!s6_svstatus_read(fn, &status)) - strerr_diefu2sys(111, "read longrun status for ", fn) ; + strerr_diefusys(111, "read longrun status for ", fn) ; if ((state[i] & 1) != status.flagwantup) { e = 1 ; @@ -137,12 +151,12 @@ static inline int print_diff (void) return e ; err: - strerr_diefu1sys(111, "write to stdout") ; + strerr_diefusys(111, "write to stdout") ; } static uint32_t compute_timeout (unsigned int i, int h) { - uint32_t t = db->services[i].timeout[h] ; + uint32_t t = db->services[i].timeout[!!h] ; int globalt ; tain globaltto ; tain_sub(&globaltto, &deadline, &STAMP) ; @@ -153,6 +167,12 @@ static uint32_t compute_timeout (unsigned int i, int h) return t ; } +static void invert_selection (void) +{ + unsigned int i = n ; + while (i--) state[i] ^= 0x10 ; +} + static inline pid_t start_oneshot (unsigned int i, int h) { unsigned int m = 0 ; @@ -183,7 +203,7 @@ static inline pid_t start_oneshot (unsigned int i, int h) newargv[m++] = tfmt ; newargv[m++] = "--" ; newargv[m++] = socketfn ; - newargv[m++] = h == 3 ? "reload" : h ? "up" : "down" ; + newargv[m++] = h == 2 ? "reload" : h ? "up" : "down" ; newargv[m++] = ifmt ; if (dryrun[0]) { @@ -205,14 +225,14 @@ static inline pid_t start_longrun (unsigned int i, int h) memcpy(servicefn, live, livelen) ; memcpy(servicefn + livelen, "/servicedirs/", 13) ; memcpy(servicefn + livelen + 13, db->string + db->services[i].name, svdlen) ; - if (h) + if (h == 1) { memcpy(servicefn + livelen + 13 + svdlen, "/notification-fd", 17) ; - if (access(servicefn, F_OK) < 0) + if (access(servicefn, F_OK) == -1) { - h = 2 ; + h = 5 ; if (verbosity >= 2 && errno != ENOENT) - strerr_warnwu2sys("access ", servicefn) ; + strerr_warnwusys("access ", servicefn) ; } } servicefn[livelen + 13 + svdlen] = 0 ; @@ -228,7 +248,7 @@ static inline pid_t start_longrun (unsigned int i, int h) newargv[m++] = "--" ; } newargv[m++] = S6_EXTBINPREFIX "s6-svc" ; - newargv[m++] = h == 3 ? "-l" : h ? h == 2 ? "-uwu" : "-uwU" : "-dwD" ; + newargv[m++] = h == 2 ? "-l" : h ? h & 4 ? "-uwu" : "-uwU" : "-dwD" ; newargv[m++] = "-T" ; newargv[m++] = fmt ; newargv[m++] = "--" ; @@ -250,7 +270,7 @@ static inline void success_longrun (unsigned int i, int h) if (h) { if (unlink(fn) == -1 && verbosity) - strerr_warnwu2sys("unlink ", fn) ; + strerr_warnwusys("unlink ", fn) ; } else { @@ -258,7 +278,7 @@ static inline void success_longrun (unsigned int i, int h) if (fd == -1) { if (verbosity) - strerr_warnwu2sys("touch ", fn) ; + strerr_warnwusys("touch ", fn) ; } else fd_close(fd) ; } @@ -276,7 +296,7 @@ static inline void failure_longrun (unsigned int i, int h) memcpy(fn + livelen, "/servicedirs/", 13) ; memcpy(fn + livelen + 13, db->string + db->services[i].name, svdlen + 1) ; if (!cspawn(newargv[0], newargv, (char const *const *)environ, CSPAWN_FLAGS_SELFPIPE_FINISH, 0, 0)) - strerr_warnwu2sys("spawn ", newargv[0]) ; + strerr_warnwusys("spawn ", newargv[0]) ; } } @@ -284,20 +304,20 @@ static void broadcast_success (unsigned int, int) ; static void examine (unsigned int i, int h) { - if (state[i] & 2 && !pendingdeps[i] && !(state[i] & 4)) + if (state[i] & 0x10 && !pendingdeps[i] && !(state[i] & 0x20)) { char const *name = db->string + db->services[i].name ; - state[i] |= 4 ; - if ((state[i] & 1) == h) + state[i] |= 0x20 ; + if ((state[i] & 0x01) == h) { if (verbosity >= 3) - strerr_warni4x("service ", name, ": already ", h ? "up" : "down") ; + strerr_warni("service ", name, ": already ", h ? "up" : "down") ; broadcast_success(i, h) ; } else if (!h && !(wgolb & GOLB_HIDEESSENTIALS) && db->services[i].flags & S6RC_DB_FLAG_ESSENTIAL) { if (verbosity) - strerr_warnw3x("service ", name, " is marked as essential, not stopping it") ; + strerr_warnw("service ", name, " is marked as essential, not stopping it") ; } else { @@ -307,15 +327,15 @@ static void examine (unsigned int i, int h) pidindex[npids++].i = i ; if (verbosity >= 2) { - strerr_warni5x(dryrun[0] ? "dry run: " : "", "service ", name, ": ", h ? "starting" : "stopping") ; + strerr_warni(dryrun[0] ? "dry run: " : "", "service ", name, ": ", h ? "starting" : "stopping") ; } } else { if (verbosity) - strerr_warnwu2sys("spawn subprocess for ", name) ; + strerr_warnwusys("spawn subprocess for ", name) ; if (verbosity >= 2) - strerr_warni4x("service ", name, ": failed to ", h ? "start" : "stop") ; + strerr_warni("service ", name, ": failed to ", h ? "start" : "stop") ; } } } @@ -334,29 +354,28 @@ static void broadcast_success (unsigned int i, int h) static inline void on_success (unsigned int i, int h) { - if (h != 3) + if (h < 2) { if (i < db->nlong) success_longrun(i, h) ; if (h) state[i] |= 1 ; else state[i] &= 254 ; announce() ; + if (!lameduck) broadcast_success(i, h) ; } if (verbosity >= 2) - strerr_warni5x(dryrun[0] ? "dry run: " : "", "service ", db->string + db->services[i].name, " successfully ", h == 3 ? "reloaded" : h ? "started" : "stopped") ; - if (!lameduck && h != 3) broadcast_success(i, h) ; + strerr_warni(dryrun[0] ? "dry run: " : "", "service ", db->string + db->services[i].name, " successfully ", h == 2 ? "reloaded" : h ? "started" : "stopped") ; } static inline void on_failure (unsigned int i, int h, int crashed, unsigned int code) { - if (h != 3 && i < db->nlong) failure_longrun(i, h) ; + if (h < 2 && i < db->nlong) failure_longrun(i, h) ; if (verbosity) { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, code)] = 0 ; - strerr_warnwu7x(dryrun[0] ? "(dry run) " : "", h == 3 ? "reload" : h ? "start" : "stop", " service ", db->string + db->services[i].name, ": command ", crashed ? "crashed with signal " : "exited ", fmt) ; + strerr_warnwu(dryrun[0] ? "(dry run) " : "", h == 2 ? "reload" : h ? "start" : "stop", " service ", db->string + db->services[i].name, ": command ", crashed ? "crashed with signal " : "exited ", fmt) ; } } -/* static inline void kill_oneshots (void) { char fn[livelen + S6RC_ONESHOT_RUNNER_LEN + 14] ; @@ -367,7 +386,6 @@ static inline void kill_oneshots (void) if (!cspawn(newargv[0], newargv, (char const *const *)environ, CSPAWN_FLAGS_SELFPIPE_FINISH, 0, 0)) strerr_warnwu2sys("spawn ", newargv[0]) ; } -*/ static inline void kill_longruns (void) { @@ -384,7 +402,7 @@ static inline int handle_signals (int h) int sig = selfpipe_read() ; switch (sig) { - case -1 : strerr_diefu1sys(111, "selfpipe_read()") ; + case -1 : strerr_diefusys(111, "selfpipe_read()") ; case 0 : return ok ; case SIGCHLD : for (;;) @@ -392,9 +410,9 @@ static inline int handle_signals (int h) unsigned int j = 0 ; int wstat ; pid_t r = wait_nohang(&wstat) ; - if (r < 0) + if (r == -1) if (errno == ECHILD) break ; - else strerr_diefu1sys(111, "wait for children") ; + else strerr_diefusys(111, "wait for children") ; else if (!r) break ; for (; j < npids ; j++) if (pidindex[j].pid == r) break ; if (j < npids) @@ -414,81 +432,70 @@ static inline int handle_signals (int h) case SIGTERM : case SIGINT : if (verbosity >= 2) - strerr_warnw3x("received ", sig_name(sig), ", aborting longrun transitions and exiting asap") ; - /* kill_oneshots() ; */ + strerr_warnw("received ", sig_name(sig), ", aborting pending processes and exiting asap") ; + if (h == 2) kill_oneshots() ; kill_longruns() ; lameduck = 1 ; break ; - default : strerr_dief1x(101, "inconsistent signal state") ; + default : strerr_dief(101, "inconsistent signal state") ; } } } -static int doit (int h) +static inline int reload (void) { iopause_fd x = { .fd = selfpipe_fd(), .events = IOPAUSE_READ } ; int exitcode = 0 ; - unsigned int i = n ; - pidindex_t pidindexblob[n] ; - unsigned int pendingdepsblob[n] ; - pidindex = pidindexblob ; - pendingdeps = pendingdepsblob ; - - if (verbosity >= 3) - strerr_warni2x("bringing selected services ", h ? "up" : "down") ; - - while (i--) + for (unsigned int i = 0 ; i < n ; i++) if (state[i] & 0x10) npids++ ; + if (!npids) return 0 ; + pidindex_t pidi[npids] ; + pidindex = pidi ; + npids = 0 ; + for (unsigned int i = 0 ; i < n ; i++) if (state[i] & 0x10) { - state[i] &= 251 ; - pendingdeps[i] = db->services[i].ndeps[h] ; + pidi[npids].i = i ; + pidi[npids].pid = i < db->nlong ? start_longrun(i, 2) : start_oneshot(i, 2) ; + if (!pidi[npids].pid) strerr_diefusys(111, "send reload command to service ", db->string + db->services[i].name) ; + npids++ ; } - i = n ; - while (i--) examine(i, h) ; while (npids) { int r = iopause_g(&x, 1, &deadline) ; - if (r < 0) strerr_diefu1sys(111, "iopause") ; - if (!r) strerr_dief1x(2, "timed out") ; - if (!handle_signals(h)) exitcode = 1 ; + if (r == -1) strerr_diefusys(111, "iopause") ; + if (!r) strerr_dief(2, "timed out") ; + if (!handle_signals(2)) exitcode = 1 ; } return exitcode ; } -static void invert_selection (void) -{ - unsigned int i = n ; - while (i--) state[i] ^= 2 ; -} - -static int reload (void) +static int change (int h) { iopause_fd x = { .fd = selfpipe_fd(), .events = IOPAUSE_READ } ; int exitcode = 0 ; unsigned int i = n ; pidindex_t pidindexblob[n] ; + unsigned int pendingdepsblob[n] ; pidindex = pidindexblob ; + pendingdeps = pendingdepsblob ; - while (i--) if (state[i] & 2) + if (verbosity >= 3) + strerr_warni("bringing selected services ", h ? "up" : "down") ; + + while (i--) { - pid_t pid ; - if (!(state[i] & 1)) - { - if (verbosity) strerr_warnw("service ", db->string + db->services[i].name, " is down - not reloading") ; - continue ; - } - pid = i < db->nlong ? start_longrun(i, 3) : start_oneshot(i, 3) ; - if (!pid) strerr_diefusys(111, "send reload command to service ", db->string + db->services[i].name) ; - pidindex[npids].pid = pid ; - pidindex[npids++].i = i ; + state[i] &= ~0x20 ; + pendingdeps[i] = db->services[i].ndeps[h] ; } + i = n ; + while (i--) examine(i, h) ; while (npids) { int r = iopause_g(&x, 1, &deadline) ; - if (r < 0) strerr_diefu1sys(111, "iopause") ; + if (r < 0) strerr_diefusys(111, "iopause") ; if (!r) strerr_dief(2, "timed out") ; - if (!handle_signals(3)) exitcode = 1 ; + if (!handle_signals(h)) exitcode = 1 ; } return exitcode ; } @@ -507,7 +514,7 @@ static inline enum what_e parse_command (char const *command) { .s = "stop", .e = WHAT_STOP }, } ; struct what_s const *p = bsearch(command, command_table, sizeof(command_table)/sizeof(struct what_s), sizeof(struct what_s), &stringkey_bcmp) ; - if (!p) strerr_dief2x(100, "unknown command: ", command) ; + if (!p) strerr_dief(100, "unknown command: ", command) ; return p->e ; } @@ -520,7 +527,7 @@ static inline void print_help (void) "s6-rc [ -l live ] diff\n" "s6-rc [ -l live ] [ -a ] [ -u | -d | -D ] [ -p ] [ -v verbosity ] [ -t timeout ] [ -n dryrunthrottle ] change [ servicenames... ]\n" ; if (buffer_putsflush(buffer_1, help) < 0) - strerr_diefu1sys(111, "write to stdout") ; + strerr_diefusys(111, "write to stdout") ; } int main (int argc, char const *const *argv) @@ -554,19 +561,19 @@ int main (int argc, char const *const *argv) } if (wgola[GOLA_VERBOSITY] && !uint0_scan(wgola[GOLA_VERBOSITY], &verbosity)) - strerr_dief1x(100, "verbosity must be an unsigned integer") ; + strerr_dief(100, "verbosity must be an unsigned integer") ; if (wgola[GOLA_DRYRUN]) { unsigned int d ; if (!uint0_scan(wgola[GOLA_DRYRUN], &d)) - strerr_dief1x(100, "dry-run must be an unsigned integer") ; + strerr_dief(100, "dry-run must be an unsigned integer") ; dryrun[uint_fmt(dryrun, d)] = 0 ; } if (wgola[GOLA_TIMEOUT]) { unsigned int t ; if (!uint0_scan(wgola[GOLA_TIMEOUT], &t)) - strerr_dief1x(100, "verbosity must be an unsigned integer") ; + strerr_dief(100, "verbosity must be an unsigned integer") ; if (t) tain_from_millisecs(&deadline, t) ; } if (wgola[GOLA_LIVEDIR]) live = wgola[GOLA_LIVEDIR] ; @@ -604,11 +611,11 @@ int main (int argc, char const *const *argv) { int livelock, compiledlock ; if (!s6rc_lock(live, 1 + (what >= 4), &livelock, dbfn, 1, &compiledlock, !!(wgolb & GOLB_BLOCK))) - strerr_diefu1sys(111, "take locks") ; + strerr_diefusys(111, "take locks") ; if (coe(livelock) < 0) - strerr_diefu3sys(111, "coe ", live, "/lock") ; + strerr_diefusys(111, "coe ", live, "/lock") ; if (compiledlock >= 0 && coe(compiledlock) < 0) - strerr_diefu4sys(111, "coe ", live, "/compiled", "/lock") ; + strerr_diefusys(111, "coe ", live, "/compiled", "/lock") ; /* locks leak, but we don't care */ } @@ -617,7 +624,7 @@ int main (int argc, char const *const *argv) fdcompiled = open_readb(dbfn) ; if (!s6rc_db_read_sizes(fdcompiled, &dbblob)) - strerr_diefu3sys(111, "read ", dbfn, "/n") ; + strerr_diefusys(111, "read ", dbfn, "/n") ; n = dbblob.nshort + dbblob.nlong ; @@ -639,16 +646,16 @@ int main (int argc, char const *const *argv) state = stateblob ; - /* Read live state in bit 0 of state */ + /* Read live state */ memcpy(dbfn + livelen + 1, "state", 6) ; { ssize_t r = openreadnclose(dbfn, (char *)state, n) ; - if (r == -1) strerr_diefu2sys(111, "read ", dbfn) ; - if (r < n) strerr_diefu2x(4, "read valid state in ", dbfn) ; + if (r == -1) strerr_diefusys(111, "read ", dbfn) ; + if (r < n) strerr_diefu(4, "read valid state in ", dbfn) ; { unsigned int i = n ; - while (i--) state[i] &= 1 ; + while (i--) state[i] &= 0x0f ; } } dbfn[livelen] = 0 ; @@ -658,7 +665,7 @@ int main (int argc, char const *const *argv) { int r = s6rc_db_read(fdcompiled, &dbblob) ; if (r < 0) strerr_diefu3sys(111, "read ", dbfn, "/db") ; - if (!r) strerr_dief3x(4, "invalid service database in ", dbfn, "/db") ; + if (!r) strerr_dief(4, "invalid service database in ", dbfn, "/db") ; } @@ -672,24 +679,28 @@ int main (int argc, char const *const *argv) { cdb c = CDB_ZERO ; if (!cdb_init_at(&c, fdcompiled, "resolve.cdb")) - strerr_diefu3sys(111, "cdb_init ", dbfn, "/resolve.cdb") ; + strerr_diefusys(111, "cdb_init ", dbfn, "/resolve.cdb") ; for (; *argv ; argv++) { cdb_data data ; int r = cdb_find(&c, &data, *argv, strlen(*argv)) ; - if (r < 0) strerr_dief3x(4, "invalid cdb in ", dbfn, "/resolve.cdb") ; - if (!r) strerr_dief4x(3, *argv, " is not a recognized identifier in ", dbfn, "/resolve.cdb") ; + if (r < 0) strerr_dief(4, "invalid cdb in ", dbfn, "/resolve.cdb") ; + if (!r) strerr_dief(3, *argv, " is not a recognized identifier in ", dbfn, "/resolve.cdb") ; if (data.len & 3) - strerr_dief3x(4, "invalid resolve database in ", dbfn, "/resolve.cdb") ; + strerr_dief(4, "invalid resolve database in ", dbfn, "/resolve.cdb") ; if (data.len >> 2 > n) - strerr_dief3x(4, "invalid resolve database in ", dbfn, "/resolve.cdb") ; + strerr_dief(4, "invalid resolve database in ", dbfn, "/resolve.cdb") ; while (data.len) { uint32_t x ; uint32_unpack_big(data.s, &x) ; data.s += 4 ; data.len -= 4 ; if (x >= n) - strerr_dief3x(4, "invalid resolve database in ", dbfn, "/resolve.cdb") ; - state[x] |= 2 ; + strerr_dief(4, "invalid resolve database in ", dbfn, "/resolve.cdb") ; + state[x] |= 0x10 ; + if (what == WHAT_CHANGE) + { + if (wgolb & GOLB_DOWN) state[x] &= ~0x02 ; else state[x] |= 0x02 ; + } } } cdb_free(&c) ; @@ -697,21 +708,12 @@ int main (int argc, char const *const *argv) close(fdcompiled) ; - /* s6-rc reload */ - - if (what == WHAT_RELOAD) - { - if (!argc) strerr_dief(100, "reload: too few arguments") ; - _exit(reload()) ; - } - - /* Add live state to selection */ if (wgolb & GOLB_SELECTLIVE) { unsigned int i = n ; - while (i--) if (state[i] & 1) state[i] |= 2 ; + while (i--) if (state[i] & 0x01) state[i] |= 0x10 ; } @@ -723,7 +725,7 @@ int main (int argc, char const *const *argv) _exit(print_services()) ; } - s6rc_graph_closure(db, state, 1, !(wgolb & GOLB_DOWN)) ; + if (what != WHAT_RELOAD) s6rc_graph_closure(db, state, 4, !(wgolb & GOLB_DOWN)) ; /* Print the selection after closure */ @@ -734,10 +736,10 @@ int main (int argc, char const *const *argv) tain_add_g(&deadline, &deadline) ; - /* Perform a state change */ + /* Reload or state change: we need a selfpipe */ if (selfpipe_init() == -1) - strerr_diefu1sys(111, "init selfpipe") ; + strerr_diefusys(111, "init selfpipe") ; { sigset_t set ; @@ -746,19 +748,21 @@ int main (int argc, char const *const *argv) sigaddset(&set, SIGTERM) ; sigaddset(&set, SIGINT) ; if (!selfpipe_trapset(&set)) - strerr_diefu1sys(111, "trap signals") ; + strerr_diefusys(111, "trap signals") ; } + if (what == WHAT_RELOAD) _exit(reload()) ; + if (wgolb & GOLB_PRUNE) { int r ; if (!(wgolb & GOLB_DOWN)) invert_selection() ; - r = doit(0) ; + r = change(0) ; if (r) return r ; invert_selection() ; - _exit(doit(1)) ; + _exit(change(1)) ; } - else _exit(doit(!(wgolb & GOLB_DOWN))) ; + else _exit(change(!(wgolb & GOLB_DOWN))) ; } } } |
