aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2026-06-14 04:37:32 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2026-06-14 04:37:32 +0000
commit87b8fcabeecf2a9cff2ca596da54d6c1cf17d89f (patch)
treebc07d6d01afac944925d43108fda8b91ef2fe12f
parent958958d74337a6ddaf649968d188e768984100e0 (diff)
downloads6-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--.gitignore1
-rw-r--r--NEWS2
-rw-r--r--doc/faq.html7
-rw-r--r--doc/index.html5
-rw-r--r--doc/overview.html10
-rw-r--r--doc/s6-rc-bundle.html138
-rw-r--r--doc/s6-rc-compile.html26
-rw-r--r--doc/s6-rc.html3
-rw-r--r--doc/upgrade.html13
-rw-r--r--package/info2
-rw-r--r--package/modes1
-rw-r--r--package/targets.mak1
-rw-r--r--src/include/s6-rc/s6rc-db.h4
-rw-r--r--src/libs6rc/s6rc_db_read.c2
-rw-r--r--src/libs6rc/s6rc_servicedir_internal.c17
-rw-r--r--src/s6-rc/s6-rc-bundle.c341
-rw-r--r--src/s6-rc/s6-rc-compile.c285
-rw-r--r--src/s6-rc/s6-rc-format-upgrade.c77
-rw-r--r--src/s6-rc/s6-rc-init.c3
-rw-r--r--src/s6-rc/s6-rc-oneshot-run.c36
-rw-r--r--src/s6-rc/s6-rc.c230
21 files changed, 376 insertions, 828 deletions
diff --git a/.gitignore b/.gitignore
index 0e74e9e..45ac2ce 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,7 +8,6 @@
/s6-rc-compile
/s6-rc-dryrun
/s6-rc-db
-/s6-rc-bundle
/s6-rc-init
/s6-rc
/s6-rc-update
diff --git a/NEWS b/NEWS
index 9a4a32f..2862d00 100644
--- a/NEWS
+++ b/NEWS
@@ -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&nbsp;<em>compiled</em></tt>&nbsp;: operate on a
-compiled service database in <em>compiled</em> instead of
-the current live one. </li>
- <li> <tt>-l&nbsp;<em>live</em></tt>&nbsp;: 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>&nbsp;: 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>&nbsp;: 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))) ;
}
}
}