aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2026-06-19 02:29:06 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2026-06-19 02:29:06 +0000
commit8eb000d3d22fcf7850b43f75ed52068693430d3b (patch)
tree9ce6403d9206a0707a44312a5ae7069e50a7e3d6
parent135468b32b12e2f2974b72c61e9d8390e562741e (diff)
downloads6-frontend-8eb000d3d22fcf7850b43f75ed52068693430d3b.tar.gz
Add s6 set apply and s6 apply
-rw-r--r--doc/overview.html5
-rw-r--r--doc/s6.html1
-rw-r--r--doc/s6_set.html57
-rw-r--r--package/deps.mak3
-rw-r--r--src/s6-frontend/deps-exe/s6-frontend1
-rw-r--r--src/s6-frontend/main.help.txt8
-rw-r--r--src/s6-frontend/s6-frontend-internal.h2
-rw-r--r--src/s6-frontend/s6-frontend.c1
-rw-r--r--src/s6-frontend/set.c1
-rw-r--r--src/s6-frontend/set.help.txt13
-rw-r--r--src/s6-frontend/set_apply.c143
-rw-r--r--src/s6-frontend/set_change.c6
12 files changed, 233 insertions, 8 deletions
diff --git a/doc/overview.html b/doc/overview.html
index 84a81e1..f7f2c87 100644
--- a/doc/overview.html
+++ b/doc/overview.html
@@ -303,8 +303,9 @@ changes effective, the user needs to run <tt>s6 set commit</tt> then
<tr>
<td> <tt>openrc sysinit &amp;&amp; openrc boot &amp;&amp; openrc default</tt> </td>
<td> <tt>s6 system boot</tt> </td>
- <td> The existence of the <tt>sysinit</tt> and <tt>boot</tt> runlevels are a
-historical wart that OpenRC still has to deal with; s6-frontend does not. </td>
+ <td> The <tt>sysinit</tt> and <tt>boot</tt> runlevels in OpenRC are only distinct
+for historical reasons. s6-frontend does not make the distinction, all the services it
+starts at boot time are in the <em>default bundle</em>. </td>
</tr>
<tr>
<td> <tt>reboot</tt> </td>
diff --git a/doc/s6.html b/doc/s6.html
index 0f6fc39..f148a23 100644
--- a/doc/s6.html
+++ b/doc/s6.html
@@ -232,6 +232,7 @@ The details are available <a href="s6_system.html">here</a>.
<li> <tt>s6 start</tt> is a shortcut for <a href="s6_live.html#start"><tt>s6 live start</tt></a>. </li>
<li> <tt>s6 stop</tt> is a shortcut for <a href="s6_live.html#stop"><tt>s6 live stop</tt></a>. </li>
<li> <tt>s6 kill</tt> is a shortcut for <a href="s6_process.html#kill"><tt>s6 process kill</tt></a>. </li>
+ <li> <tt>s6 apply</tt> is a shortcut for <a href="s6_set.html#apply"><tt>s6 set apply</tt></a>. </li>
</ul>
<h2 id="notes"> Notes </h2>
diff --git a/doc/s6_set.html b/doc/s6_set.html
index bd74233..a38a57d 100644
--- a/doc/s6_set.html
+++ b/doc/s6_set.html
@@ -343,5 +343,62 @@ and that is fine. </dd>
<dd> Commit the set named <em>setname</em>, rather than <tt>current</tt>. </dd>
</dl>
+<h3 id="apply"> apply </h3>
+
+<h4> Interface </h4>
+
+<pre>
+ s6 set apply [ -b ] [ -D <em>defaultbundle</em> ] [ -h <em>fdhuser</em> ] [ -s <em>setname</em> ] [ -t <em>timeout</em> ]
+</pre>
+
+<ul>
+ <li> <tt>s6 set apply</tt> is different from other <tt>s6 set</tt> commands
+in that it does several things in succession, and <em>impacts the live state</em>
+of the machine. It does the following:
+ <ul>
+ <li> <em>Commit</em> the working set, just like <tt>s6 set commit</tt> </li>
+ <li> <em>Install</em> the working set, just like <tt>s6 live install</tt> </li>
+ <li> <em>Reset</em> the live state, just like <tt>s6 live reset</tt>, so it
+matches the prescriptions of the working set exactly. </li>
+ </ul>
+ In other words, <tt>s6 set apply</tt> immediately turns the working set
+into the current live state. It is a powerful command. </li>
+ <li>
+</ul>
+
+<h4> Options </h4>
+
+<dl>
+<dt> <tt>-b</tt>, <tt>--block</tt> </dt>
+<dd> Block if something is currently holding the lock on the live service
+database. The default is to fail with an error message instead. </dd>
+
+<dt> -D <em>defaultbundle</em>, --default-bundle=<em>defaultbundle</em> </dt>
+<dd> The name of the bundle that holds all <tt>active</tt> and <tt>always</tt>
+services, which will be the ones running on the machine when the command ends.
+The default depends on the distribution and is probably called <tt>default</tt>. </dd>
+
+<dt> -h <em>fdhuser</em>, --fdholder-user=<em>fdhuser</em> </dt>
+<dd> Specify the fdholder user for the compiled database built from
+the set. This must be a user name defined in the <tt>/etc/passwd</tt>
+file or whatever user database the system uses. The default is <tt>root</tt>
+and that is fine. </dd>
+
+<dt> <tt>-f <em>convfile</em></tt>, <tt>--conversion-file=<em>convfile</em></tt> </dt>
+<dd> Use <em>convfile</em> as a <a href="//skarnet.org/software/s6-rc/s6-rc-update.html#conversion">conversion file</a> for the underlying
+<a href="//skarnet.org/software/s6-rc/s6-rc-update.html">s6-rc-update</a>
+invocation. This option should
+never be necessary if the services in the stores are properly managed. </dd>
+
+<dt> <tt>-s <em>setname</em></tt>, <tt>--set=<em>setname</em></tt> </dt>
+<dd> Apply the set named <em>setname</em>, rather than <tt>current</tt>. </dd>
+
+<dt> <tt>-t <em>timeout</em></tt>, <tt>--timeout=<em>timeout</em></tt> </dt>
+<dd> If installing the set and resetting the state still hasn't completed after <em>timeout</em>
+milliseconds, stop waiting and don't attempt to perform the remaining
+transitions. By default, <em>timeout</em> is 0, meaning infinite: the
+command will wait until the task is complete. </dd>
+</dl>
+
</body>
</html>
diff --git a/package/deps.mak b/package/deps.mak
index 923fcfc..e26a563 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -29,6 +29,7 @@ src/s6-frontend/repository_sync.o src/s6-frontend/repository_sync.lo: src/s6-fro
src/s6-frontend/s6-frontend.o src/s6-frontend/s6-frontend.lo: src/s6-frontend/s6-frontend.c src/s6-frontend/s6-frontend-internal.h src/include-local/s6f.h
src/s6-frontend/s6.o src/s6-frontend/s6.lo: src/s6-frontend/s6.c src/include/s6-frontend/config.h
src/s6-frontend/set.o src/s6-frontend/set.lo: src/s6-frontend/set.c src/s6-frontend/s6-frontend-internal.h
+src/s6-frontend/set_apply.o src/s6-frontend/set_apply.lo: src/s6-frontend/set_apply.c src/s6-frontend/s6-frontend-internal.h
src/s6-frontend/set_change.o src/s6-frontend/set_change.lo: src/s6-frontend/set_change.c src/s6-frontend/s6-frontend-internal.h
src/s6-frontend/set_check.o src/s6-frontend/set_check.lo: src/s6-frontend/set_check.c src/s6-frontend/s6-frontend-internal.h src/include/s6-frontend/config.h
src/s6-frontend/set_commit.o src/s6-frontend/set_commit.lo: src/s6-frontend/set_commit.c src/s6-frontend/s6-frontend-internal.h
@@ -55,5 +56,5 @@ endif
s6: EXTRA_LIBS :=
s6: src/s6-frontend/s6.o -lskarnet
s6-frontend: EXTRA_LIBS := ${MAYBEPTHREAD_LIB}
-s6-frontend: src/s6-frontend/s6-frontend.o src/s6-frontend/live.o src/s6-frontend/live_help.o src/s6-frontend/live_install.o src/s6-frontend/live_reload.o src/s6-frontend/live_startstop.o src/s6-frontend/live_status.o src/s6-frontend/live_start_everything.o src/s6-frontend/live_stop_everything.o src/s6-frontend/main_help.o src/s6-frontend/process.o src/s6-frontend/process_help.o src/s6-frontend/process_kill.o src/s6-frontend/process_restart.o src/s6-frontend/process_startstop.o src/s6-frontend/process_status.o src/s6-frontend/repository.o src/s6-frontend/repository_check.o src/s6-frontend/repository_help.o src/s6-frontend/repository_init.o src/s6-frontend/repository_list.o src/s6-frontend/repository_sync.o src/s6-frontend/set.o src/s6-frontend/set_change.o src/s6-frontend/set_check.o src/s6-frontend/set_commit.o src/s6-frontend/set_copy.o src/s6-frontend/set_delete.o src/s6-frontend/set_help.o src/s6-frontend/set_list.o src/s6-frontend/set_status.o src/s6-frontend/system.o src/s6-frontend/system_boot.o src/s6-frontend/system_help.o src/s6-frontend/system_hpr.o src/s6-frontend/version.o src/s6-frontend/version_export.o src/s6-frontend/version_help.o src/s6-frontend/version_show.o libs6f.a.xyzzy ${LIBNSSS} -ls6rc -ls6 -lskarnet
+s6-frontend: src/s6-frontend/s6-frontend.o src/s6-frontend/live.o src/s6-frontend/live_help.o src/s6-frontend/live_install.o src/s6-frontend/live_reload.o src/s6-frontend/live_startstop.o src/s6-frontend/live_status.o src/s6-frontend/live_start_everything.o src/s6-frontend/live_stop_everything.o src/s6-frontend/main_help.o src/s6-frontend/process.o src/s6-frontend/process_help.o src/s6-frontend/process_kill.o src/s6-frontend/process_restart.o src/s6-frontend/process_startstop.o src/s6-frontend/process_status.o src/s6-frontend/repository.o src/s6-frontend/repository_check.o src/s6-frontend/repository_help.o src/s6-frontend/repository_init.o src/s6-frontend/repository_list.o src/s6-frontend/repository_sync.o src/s6-frontend/set.o src/s6-frontend/set_apply.o src/s6-frontend/set_change.o src/s6-frontend/set_check.o src/s6-frontend/set_commit.o src/s6-frontend/set_copy.o src/s6-frontend/set_delete.o src/s6-frontend/set_help.o src/s6-frontend/set_list.o src/s6-frontend/set_status.o src/s6-frontend/system.o src/s6-frontend/system_boot.o src/s6-frontend/system_help.o src/s6-frontend/system_hpr.o src/s6-frontend/version.o src/s6-frontend/version_export.o src/s6-frontend/version_help.o src/s6-frontend/version_show.o libs6f.a.xyzzy ${LIBNSSS} -ls6rc -ls6 -lskarnet
INTERNAL_LIBS := libs6f.a.xyzzy
diff --git a/src/s6-frontend/deps-exe/s6-frontend b/src/s6-frontend/deps-exe/s6-frontend
index b6d45c0..1a47be4 100644
--- a/src/s6-frontend/deps-exe/s6-frontend
+++ b/src/s6-frontend/deps-exe/s6-frontend
@@ -20,6 +20,7 @@ repository_init.o
repository_list.o
repository_sync.o
set.o
+set_apply.o
set_change.o
set_check.o
set_commit.o
diff --git a/src/s6-frontend/main.help.txt b/src/s6-frontend/main.help.txt
index f7c03eb..7837152 100644
--- a/src/s6-frontend/main.help.txt
+++ b/src/s6-frontend/main.help.txt
@@ -11,6 +11,14 @@ Commands:
set manipulate sets of services (offline, to later install them live)
repository manipulate the service repository itself
+Shortcuts:
+ enable s6 set enable
+ disable s6 set disable
+ start s6 live start
+ stop s6 live stop
+ kill s6 process kill
+ apply s6 set apply
+
Global options:
-h --help equivalent to "s6 help"
-u --user override config values with XDG environment
diff --git a/src/s6-frontend/s6-frontend-internal.h b/src/s6-frontend/s6-frontend-internal.h
index dad191b..587b4e2 100644
--- a/src/s6-frontend/s6-frontend-internal.h
+++ b/src/s6-frontend/s6-frontend-internal.h
@@ -88,6 +88,8 @@ extern void set_make_essential (char const *const *) gccattr_noreturn ;
extern void set_check (char const *const *) gccattr_noreturn ;
extern void set_commit (char const *const *) gccattr_noreturn ;
+extern void set_apply (char const *const *) gccattr_noreturn ;
+
/* system */
diff --git a/src/s6-frontend/s6-frontend.c b/src/s6-frontend/s6-frontend.c
index c79464e..9e649a7 100644
--- a/src/s6-frontend/s6-frontend.c
+++ b/src/s6-frontend/s6-frontend.c
@@ -118,6 +118,7 @@ int main (int argc, char const *const *argv)
} ;
static struct command_s const commands[] =
{
+ { .s = "apply", .f = &set_apply },
{ .s = "disable", .f = &set_disable },
{ .s = "enable", .f = &set_enable },
{ .s = "help", .f = &main_help },
diff --git a/src/s6-frontend/set.c b/src/s6-frontend/set.c
index fe5f165..8ece627 100644
--- a/src/s6-frontend/set.c
+++ b/src/s6-frontend/set.c
@@ -23,6 +23,7 @@ void set (char const *const *argv)
{
static struct command_s const commands[] =
{
+ { .s = "apply", .f = &set_apply },
{ .s = "check", .f = &set_check },
{ .s = "commit", .f = &set_commit },
{ .s = "copy", .f = &set_copy },
diff --git a/src/s6-frontend/set.help.txt b/src/s6-frontend/set.help.txt
index 62b59ea..9113f34 100644
--- a/src/s6-frontend/set.help.txt
+++ b/src/s6-frontend/set.help.txt
@@ -12,6 +12,7 @@ Subcommands:
unmask unmask services (equivalent to "disable")
check check working set and fix inconsistencies
commit commit working set (can then be installed)
+ apply make working set live: commit + live install + live reset
s6 set copy options:
@@ -37,8 +38,8 @@ s6 set enable|disable|mask|unmask options:
-s SET --set=SET change services in set SET (default: current)
s6 set check options:
- -E --no-force-essential do not allow manual changes to essential services (default)
- -e --force-essential allow manual changes to essential services
+ -E --no-force-essentials do not allow manual changes to essential services (default)
+ -e --force-essentials allow manual changes to essential services
-F --fix try to fix inconsistencies automatically
-d --down fix by disabling or masking services if necessary (default)
-u --up fix by enabling services if necessary
@@ -51,3 +52,11 @@ s6 set commit options:
-h USER --fdholder-user=USER user for the s6-fdholderd process (default: root - it's fine)
-s SET --set=SET commit set SET (default: current)
+s6 set apply options:
+ -b --block block if another s6-rc is running (default: fail)
+ -D BUN --default-bundle=BUN name of the bundle containing enabled+essential services
+ -h USER --fdholder-user=USER user for the s6-fdholderd process (default: root - it's fine)
+ -f CONVFILE --conversion-file=CONVFILE use CONVFILE when updating the service db (default: none)
+ -s SET --set=SET apply set SET (default: current)
+ -t TIMEOUT --timeout=TIMEOUT fail after TIMEOUT milliseconds (default: 0 (=infinite))
+
diff --git a/src/s6-frontend/set_apply.c b/src/s6-frontend/set_apply.c
new file mode 100644
index 0000000..b017212
--- /dev/null
+++ b/src/s6-frontend/set_apply.c
@@ -0,0 +1,143 @@
+/* ISC license. */
+
+#include <skalibs/uint64.h>
+#include <skalibs/types.h>
+#include <skalibs/envexec.h>
+#include <skalibs/djbunix.h>
+
+#include <s6-rc/config.h>
+
+#include "s6-frontend-internal.h"
+
+enum golb_e
+{
+ GOLB_BLOCK = 0x01,
+} ;
+
+enum gola_e
+{
+ GOLA_DEFBUNDLE,
+ GOLA_FDHUSER,
+ GOLA_CONVFILE,
+ GOLA_SET,
+ GOLA_TIMEOUT,
+ GOLA_N
+} ;
+
+void set_apply (char const *const *argv)
+{
+ static gol_bool const rgolb[] =
+ {
+ { .so = 'b', .lo = "block", .clear = 0, .set = GOLB_BLOCK },
+ } ;
+ static gol_arg const rgola[] =
+ {
+ { .so = 'D', .lo = "default-bundle", .i = GOLA_DEFBUNDLE },
+ { .so = 'h', .lo = "fdholder-user", .i = GOLA_FDHUSER },
+ { .so = 'f', .lo = "conversion-file", .i = GOLA_CONVFILE },
+ { .so = 's', .lo = "set", .i = GOLA_SET },
+ { .so = 't', .lo = "timeout", .i = GOLA_TIMEOUT },
+ } ;
+ uint64_t wgolb = 0 ;
+ unsigned int timeout = 0 ;
+ unsigned int m = 0 ;
+ int wstat ;
+ pid_t pid ;
+ char const *wgola[GOLA_N] = { 0 } ;
+ char const *newargv[15] ;
+ char fmtv[UINT_FMT] ;
+ char fmtt[UINT_FMT] ;
+
+ wgola[GOLA_DEFBUNDLE] = S6_FRONTEND_DEFBUNDLE ;
+ wgola[GOLA_SET] = "current" ;
+
+ argv += GOL_argv(argv, rgolb, rgola, &wgolb, wgola) ;
+
+ if (wgola[GOLA_TIMEOUT])
+ {
+ if (!uint0_scan(wgola[GOLA_TIMEOUT], &timeout))
+ strerr_dief1x(100, "timeout must be an integer (milliseconds)") ;
+ }
+
+ /* set commit */
+ newargv[m++] = S6RC_EXTBINPREFIX "s6-rc-set-commit" ;
+ if (g->verbosity != 1)
+ {
+ fmtv[uint_fmt(fmtv, g->verbosity)] = 0 ;
+ newargv[m++] = "-v" ;
+ newargv[m++] = fmtv ;
+ }
+ newargv[m++] = "-r" ;
+ newargv[m++] = g->dirs.repo ;
+ newargv[m++] = "-D" ;
+ newargv[m++] = wgola[GOLA_DEFBUNDLE] ;
+ if (wgola[GOLA_FDHUSER])
+ {
+ newargv[m++] = "-h" ;
+ newargv[m++] = wgola[GOLA_FDHUSER] ;
+ }
+ newargv[m++] = "--" ;
+ newargv[m++] = wgola[GOLA_SET] ;
+ newargv[m++] = 0 ;
+
+ pid = main_spawn(newargv) ;
+ if (wait_pid(pid, &wstat) == -1)
+ strerr_diefusys(111, "wait for ", newargv[0]) ;
+ if (wait_estatus(wstat))
+ strerr_dief(wait_estatus(wstat), newargv[0], " failed") ;
+
+ /* live install */
+ m = 0 ;
+ newargv[m++] = S6RC_EXTBINPREFIX "s6-rc-set-install" ;
+ if (g->verbosity != 1)
+ {
+ newargv[m++] = "-v" ;
+ newargv[m++] = fmtv ;
+ }
+ newargv[m++] = "-r" ;
+ newargv[m++] = g->dirs.repo ;
+ newargv[m++] = "-c" ;
+ newargv[m++] = g->dirs.boot ;
+ newargv[m++] = "-l" ;
+ newargv[m++] = g->dirs.live ;
+
+ if (wgolb & GOLB_BLOCK) newargv[m++] = "-b" ;
+ if (wgola[GOLA_CONVFILE])
+ {
+ newargv[m++] = "-f" ;
+ newargv[m++] = wgola[GOLA_CONVFILE] ;
+ }
+ newargv[m++] = "--" ;
+ newargv[m++] = wgola[GOLA_SET] ;
+ newargv[m++] = 0 ;
+
+ pid = main_spawn(newargv) ;
+ if (wait_pid(pid, &wstat) == -1)
+ strerr_diefusys(111, "wait for ", newargv[0]) ;
+ if (wait_estatus(wstat))
+ strerr_dief(wait_estatus(wstat), newargv[0], " failed") ;
+
+ /* live reset */
+ m = 0 ;
+ newargv[m++] = S6RC_EXTBINPREFIX "s6-rc" ;
+ if (g->verbosity != 1)
+ {
+ newargv[m++] = "-v" ;
+ newargv[m++] = fmtv ;
+ }
+ if (timeout)
+ {
+ fmtt[uint_fmt(fmtt, timeout)] = 0 ;
+ newargv[m++] = "-t" ;
+ newargv[m++] = fmtt ;
+ }
+ newargv[m++] = "-pe" ;
+ newargv[m++] = "-l" ;
+ newargv[m++] = g->dirs.live ;
+ if (wgolb & GOLB_BLOCK) newargv[m++] = "-b" ;
+ newargv[m++] = "--" ;
+ newargv[m++] = "change" ;
+ newargv[m++] = wgola[GOLA_DEFBUNDLE] ;
+ newargv[m++] = 0 ;
+ main_exec(argv) ;
+}
diff --git a/src/s6-frontend/set_change.c b/src/s6-frontend/set_change.c
index a0db9b7..deefe5e 100644
--- a/src/s6-frontend/set_change.c
+++ b/src/s6-frontend/set_change.c
@@ -11,9 +11,9 @@
enum golb_e
{
- GOLB_DRYRUN = 0x02,
- GOLB_FAIL_ON_DEPS = 0x04,
- GOLB_PULL_DEPS = 0x08,
+ GOLB_DRYRUN = 0x01,
+ GOLB_FAIL_ON_DEPS = 0x02,
+ GOLB_PULL_DEPS = 0x04,
} ;
enum gola_e