From c40145fca667f8b0243bbcf276b5aade18f7ae5b Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Wed, 26 Nov 2025 10:15:55 +0000 Subject: s6-rc-set-list is now s6-rc-set-status and does everything --- .gitignore | 2 +- doc/repodefs.html | 2 + doc/s6-rc-set-list.html | 78 ------------------------ doc/s6-rc-set-status.html | 89 ++++++++++++++++++++++++++++ package/deps.mak | 6 +- package/modes | 2 +- package/targets.mak | 2 +- src/repo/deps-exe/s6-rc-set-list | 3 - src/repo/deps-exe/s6-rc-set-status | 3 + src/repo/s6-rc-set-change.c | 9 ++- src/repo/s6-rc-set-list.c | 86 --------------------------- src/repo/s6-rc-set-status.c | 118 +++++++++++++++++++++++++++++++++++++ 12 files changed, 226 insertions(+), 174 deletions(-) delete mode 100644 doc/s6-rc-set-list.html create mode 100644 doc/s6-rc-set-status.html delete mode 100644 src/repo/deps-exe/s6-rc-set-list create mode 100644 src/repo/deps-exe/s6-rc-set-status delete mode 100644 src/repo/s6-rc-set-list.c create mode 100644 src/repo/s6-rc-set-status.c diff --git a/.gitignore b/.gitignore index cf189fe..2cfcf9e 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,7 @@ /s6-rc-format-upgrade /s6-rc-repo-init /s6-rc-repo-sync -/s6-rc-set-list +/s6-rc-set-status /s6-rc-set-new /s6-rc-set-copy /s6-rc-set-delete diff --git a/doc/repodefs.html b/doc/repodefs.html index 6d0cd94..c234ba0 100644 --- a/doc/repodefs.html +++ b/doc/repodefs.html @@ -284,6 +284,8 @@ make a copy of an existing set with s6-rc-set-copy or delete sets with s6-rc-set-delete.
  • They mask, unmask, enable or disable services in their favorite set with s6-rc-set-change.
  • +
  • They can check the list of services and their subs with +s6-rc-set-status.
  • They commit the set with s6-rc-set-commit.
  • They install the set with s6-rc-set-install. This action potentially modifies the current state of the machine!
  • diff --git a/doc/s6-rc-set-list.html b/doc/s6-rc-set-list.html deleted file mode 100644 index 18a04ee..0000000 --- a/doc/s6-rc-set-list.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - s6-rc: the s6-rc-set-list program - - - - - - -

    -s6-rc
    -Software
    -skarnet.org -

    - -

    The s6-rc-set-list program

    - -

    - s6-rc-set-list lists all the services of a set, -along with the sub each service is on. -

    - -

    Interface

    - -
    -     s6-rc-set-list [ -v verbosity ] [ -r repo ] set
    -
    - - - -

    Options

    - -
    -
    -v verbosity, --verbosity=verbosity
    -
    Be more or less verbose. The default is 1, which means -that error messages and warnings will be written to stderr. 0 means that only -error messages will be written, and 2 or more adds informational messages.
    - -
    -r repo, --repository=repo
    -
    Use the repository in repo, which must exist. Default is -/var/lib/s6-rc/repository. -
    -
    - -

    Exit codes

    - -
    -
    0
    Success.
    -
    3
    Nonexistent set.
    -
    100
    Incorrect usage.
    -
    102
    Invalid repository.
    -
    111
    System call failed.
    -
    - -

    Notes

    - - - - - diff --git a/doc/s6-rc-set-status.html b/doc/s6-rc-set-status.html new file mode 100644 index 0000000..8f058ba --- /dev/null +++ b/doc/s6-rc-set-status.html @@ -0,0 +1,89 @@ + + + + + + s6-rc: the s6-rc-set-status program + + + + + + +

    +s6-rc
    +Software
    +skarnet.org +

    + +

    The s6-rc-set-status program

    + +

    + s6-rc-set-list lists some of, or all, the services of a set, +along with the sub each service is on. +

    + +

    Interface

    + +
    +     s6-rc-set-list [ -v verbosity ] [ -r repo ] [ -E | -e ] [ -L ] set [ services... ]
    +
    + + + +

    Options

    + +
    +
    -v verbosity, --verbosity=verbosity
    +
    Be more or less verbose. The default is 1, which means +that error messages and warnings will be written to stderr. 0 means that only +error messages will be written, and 2 or more adds informational messages.
    + +
    -r repo, --repository=repo
    +
    Use the repository in repo, which must exist. Default is +/var/lib/s6-rc/repository. +
    + +
    -E, --with-essentials
    +
    Do not ignore services in the always sub, i.e. services marked as +essential. This is the default.
    + +
    -e, --without-essentials
    +
    Ignore services in the always sub: do not print them.
    + +
    -L. --list
    +
    Do not print /sub at the end of each line: only print the service names.
    +
    + +

    Exit codes

    + +
    +
    0
    Success.
    +
    3
    Nonexistent set.
    +
    100
    Incorrect usage.
    +
    102
    Invalid repository.
    +
    111
    System call failed.
    +
    + +

    Notes

    + + + + + diff --git a/package/deps.mak b/package/deps.mak index 9543a02..f738d27 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -34,8 +34,8 @@ src/repo/s6-rc-set-commit.o src/repo/s6-rc-set-commit.lo: src/repo/s6-rc-set-com src/repo/s6-rc-set-copy.o src/repo/s6-rc-set-copy.lo: src/repo/s6-rc-set-copy.c src/include/s6-rc/config.h src/include/s6-rc/s6rc.h src/repo/s6-rc-set-delete.o src/repo/s6-rc-set-delete.lo: src/repo/s6-rc-set-delete.c src/include/s6-rc/config.h src/include/s6-rc/s6rc.h src/repo/s6-rc-set-install.o src/repo/s6-rc-set-install.lo: src/repo/s6-rc-set-install.c src/include/s6-rc/config.h src/include/s6-rc/s6rc.h -src/repo/s6-rc-set-list.o src/repo/s6-rc-set-list.lo: src/repo/s6-rc-set-list.c src/include/s6-rc/config.h src/include/s6-rc/repo.h src/repo/s6-rc-set-new.o src/repo/s6-rc-set-new.lo: src/repo/s6-rc-set-new.c src/include/s6-rc/config.h src/include/s6-rc/s6rc.h +src/repo/s6-rc-set-status.o src/repo/s6-rc-set-status.lo: src/repo/s6-rc-set-status.c src/include/s6-rc/config.h src/include/s6-rc/repo.h src/repo/s6rc_repo_badsub.o src/repo/s6rc_repo_badsub.lo: src/repo/s6rc_repo_badsub.c src/include/s6-rc/repo.h src/repo/s6rc_repo_checkset.o src/repo/s6rc_repo_checkset.lo: src/repo/s6rc_repo_checkset.c src/include/s6-rc/repo.h src/repo/s6rc_repo_cleanup.o src/repo/s6rc_repo_cleanup.lo: src/repo/s6rc_repo_cleanup.c src/include/s6-rc/repo.h @@ -115,10 +115,10 @@ s6-rc-set-delete: EXTRA_LIBS := ${SPAWN_LIB} s6-rc-set-delete: src/repo/s6-rc-set-delete.o ${LIBS6RCREPO} -lskarnet s6-rc-set-install: EXTRA_LIBS := ${SPAWN_LIB} s6-rc-set-install: src/repo/s6-rc-set-install.o ${LIBS6RCREPO} -lskarnet -s6-rc-set-list: EXTRA_LIBS := ${SPAWN_LIB} -s6-rc-set-list: src/repo/s6-rc-set-list.o ${LIBS6RCREPO} -lskarnet s6-rc-set-new: EXTRA_LIBS := ${SPAWN_LIB} s6-rc-set-new: src/repo/s6-rc-set-new.o ${LIBS6RCREPO} -lskarnet +s6-rc-set-status: EXTRA_LIBS := ${SPAWN_LIB} +s6-rc-set-status: src/repo/s6-rc-set-status.o ${LIBS6RCREPO} -lskarnet s6-rc: EXTRA_LIBS := ${SYSCLOCK_LIB} ${SPAWN_LIB} s6-rc: src/s6-rc/s6-rc.o ${LIBS6RC} -ls6 -lskarnet s6-rc-bundle: EXTRA_LIBS := diff --git a/package/modes b/package/modes index 95ee646..6ef7f93 100644 --- a/package/modes +++ b/package/modes @@ -10,7 +10,7 @@ s6-rc-oneshot-run 0755 s6-rc-format-upgrade 0755 s6-rc-repo-init 0755 s6-rc-repo-sync 0755 -s6-rc-set-list 0755 +s6-rc-set-status 0755 s6-rc-set-new 0755 s6-rc-set-copy 0755 s6-rc-set-delete 0755 diff --git a/package/targets.mak b/package/targets.mak index 9a83f37..f22dcaa 100644 --- a/package/targets.mak +++ b/package/targets.mak @@ -9,7 +9,7 @@ s6-rc-update \ s6-rc-format-upgrade \ s6-rc-repo-init \ s6-rc-repo-sync \ -s6-rc-set-list \ +s6-rc-set-status \ s6-rc-set-new \ s6-rc-set-copy \ s6-rc-set-delete \ diff --git a/src/repo/deps-exe/s6-rc-set-list b/src/repo/deps-exe/s6-rc-set-list deleted file mode 100644 index 9fe69bb..0000000 --- a/src/repo/deps-exe/s6-rc-set-list +++ /dev/null @@ -1,3 +0,0 @@ -${LIBS6RCREPO} --lskarnet -${SPAWN_LIB} diff --git a/src/repo/deps-exe/s6-rc-set-status b/src/repo/deps-exe/s6-rc-set-status new file mode 100644 index 0000000..9fe69bb --- /dev/null +++ b/src/repo/deps-exe/s6-rc-set-status @@ -0,0 +1,3 @@ +${LIBS6RCREPO} +-lskarnet +${SPAWN_LIB} diff --git a/src/repo/s6-rc-set-change.c b/src/repo/s6-rc-set-change.c index 1ab92f6..c678357 100644 --- a/src/repo/s6-rc-set-change.c +++ b/src/repo/s6-rc-set-change.c @@ -129,9 +129,16 @@ int main (int argc, char const *const *argv) if (newsub->sub == 3 && !(wgolb & GOLB_FORCE_ESSENTIAL)) strerr_diefu1x(10, " artificially mark a service as essential without --force-essential") ; + for (unsigned int i = 2 ; i < argc ; i++) + { + if (argv[i][0] == '.') + strerr_dief2x(100, "service names cannot ", "start with a dot") ; + if (strchr(argv[i], '/') || strchr(argv[i], '\n')) + strerr_dief2x(100, "service names cannot ", "contain / or newlines") ; + } + fdlock = s6rc_repo_lock(wgola[GOLA_REPODIR], 1) ; if (fdlock == -1) strerr_diefu2sys(111, "lock ", wgola[GOLA_REPODIR]) ; - if (!s6rc_repo_makesvlist_byname(wgola[GOLA_REPODIR], argv[0], &storage, &svlist)) _exit(111) ; list = genalloc_s(s6rc_repo_sv, &svlist) ; listn = genalloc_len(s6rc_repo_sv, &svlist) ; diff --git a/src/repo/s6-rc-set-list.c b/src/repo/s6-rc-set-list.c deleted file mode 100644 index 84ef3bb..0000000 --- a/src/repo/s6-rc-set-list.c +++ /dev/null @@ -1,86 +0,0 @@ -/* ISC license. */ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#define USAGE "s6-rc-set-list [ -v verbosity ] [ -r repo ] set" -#define dieusage() strerr_dieusage(100, USAGE) - -enum gola_e -{ - GOLA_VERBOSITY, - GOLA_REPODIR, - GOLA_N -} ; - -int main (int argc, char const *const *argv) -{ - static gol_arg const rgola[] = - { - { .so = 'v', .lo = "verbosity", .i = GOLA_VERBOSITY }, - { .so = 'r', .lo = "repodir", .i = GOLA_REPODIR } - } ; - int fdlock ; - unsigned int verbosity = 1 ; - char const *wgola[GOLA_N] = { 0 } ; - unsigned int golc ; - int e ; - uint8_t sub = 4 ; - - PROG = "s6-rc-set-list" ; - wgola[GOLA_REPODIR] = S6RC_REPODIR ; - - golc = gol_main(argc, argv, 0, 0, rgola, GOLA_N, 0, wgola) ; - argc -= golc ; argv += golc ; - if (wgola[GOLA_VERBOSITY] && !uint0_scan(wgola[GOLA_VERBOSITY], &verbosity)) - strerr_dief1x(100, "verbosity needs to be an unsigned integer") ; - if (!argc) dieusage() ; - if (strchr(argv[0], '/') || strchr(argv[0], '\n')) - strerr_dief1x(100, "set names cannot contain / or newlines") ; - - fdlock = s6rc_repo_lock(wgola[GOLA_REPODIR], 1) ; - if (fdlock == -1) strerr_diefu2sys(111, "lock ", wgola[GOLA_REPODIR]) ; - - e = s6rc_repo_checkset(wgola[GOLA_REPODIR], argv[0]) ; - if (e) _exit(e) ; - - size_t repolen = strlen(wgola[GOLA_REPODIR]) ; - size_t setlen = strlen(argv[0]) ; - char fn[repolen + setlen + 17] ; - memcpy(fn, wgola[GOLA_REPODIR], repolen) ; - memcpy(fn + repolen, "/sources/", 9) ; - memcpy(fn + repolen + 9, argv[0], setlen) ; - fn[repolen + 9 + setlen] = '/' ; - while (sub--) - { - memcpy(fn + repolen + 10 + setlen, s6rc_repo_subnames[sub], 7) ; - DIR *dir = opendir(fn) ; - if (!dir) strerr_diefu2sys(111, "opendir ", fn) ; - for (;;) - { - direntry *d ; - errno = 0 ; - d = readdir(dir) ; - if (!d) break ; - if (d->d_name[0] == '.') continue ; - if (buffer_puts(buffer_1, d->d_name) < 0 - || buffer_put(buffer_1, "/", 1) < 0 - || buffer_put(buffer_1, s6rc_repo_subnames[sub], 6) < 0 - || buffer_put(buffer_1, "\n", 1) < 0) - strerr_diefu1sys(111, "write to stdout") ; - } - if (errno) strerr_diefu2sys(111, "readdir ", fn) ; - dir_close(dir) ; - } - if (!buffer_flush(buffer_1)) strerr_diefu1sys(111, "write to stdout") ; - _exit(0) ; -} diff --git a/src/repo/s6-rc-set-status.c b/src/repo/s6-rc-set-status.c new file mode 100644 index 0000000..b58811b --- /dev/null +++ b/src/repo/s6-rc-set-status.c @@ -0,0 +1,118 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#define USAGE "s6-rc-set-status [ -v verbosity ] [ -r repo ] [ -E | -e ] set services..." +#define dieusage() strerr_dieusage(100, USAGE) +#define dieout() strerr_diefu1sys(111, "write to stdout") + +enum golb_e +{ + GOLB_IGNORE_ESSENTIALS = 0x01, + GOLB_NOSUB = 0x02, +} ; + +enum gola_e +{ + GOLA_VERBOSITY, + GOLA_REPODIR, + GOLA_N +} ; + +int main (int argc, char const **argv) +{ + static gol_bool const rgolb[] = + { + { .so = 'E', .lo = "with-essentials", .clear = GOLB_IGNORE_ESSENTIALS, .set = 0 }, + { .so = 'e', .lo = "without-essentials", .clear = 0, .set = GOLB_IGNORE_ESSENTIALS }, + { .so = 'L', .lo = "list", .clear = 0, .set = GOLB_NOSUB }, + } ; + static gol_arg const rgola[] = + { + { .so = 'v', .lo = "verbosity", .i = GOLA_VERBOSITY }, + { .so = 'r', .lo = "repodir", .i = GOLA_REPODIR } + } ; + int fdlock ; + unsigned int verbosity = 1 ; + uint64_t wgolb = 0 ; + char const *setname ; + char const *wgola[GOLA_N] = { 0 } ; + unsigned int golc ; + uint8_t sub ; + + PROG = "s6-rc-set-status" ; + wgola[GOLA_REPODIR] = S6RC_REPODIR ; + + golc = GOL_main(argc, argv, rgolb, rgola, &wgolb, wgola) ; + argc -= golc ; argv += golc ; + if (argc < 2) dieusage() ; + setname = *argv++ ; argc-- ; + if (wgola[GOLA_VERBOSITY] && !uint0_scan(wgola[GOLA_VERBOSITY], &verbosity)) + strerr_dief1x(100, "verbosity needs to be an unsigned integer") ; + if (strchr(setname, '/') || strchr(setname, '\n')) + strerr_dief2x(100, "set", " names cannot contain / or newlines") ; + for (unsigned int i = 0 ; i < argc ; i++) + { + if (argv[i][0] == '.') + strerr_dief2x(100, "service", " names cannot start with a dot") ; + if (strchr(argv[i], '/') || strchr(argv[i], '\n')) + strerr_dief2x(100, "service", " names cannot contain / or newlines") ; + } + + fdlock = s6rc_repo_lock(wgola[GOLA_REPODIR], 1) ; + if (fdlock == -1) strerr_diefu2sys(111, "lock ", wgola[GOLA_REPODIR]) ; + + { + int e = s6rc_repo_checkset(wgola[GOLA_REPODIR], setname) ; + if (e) _exit(e) ; + } + + qsort(argv, argc, sizeof(char const *), &str_cmp) ; + + size_t repolen = strlen(wgola[GOLA_REPODIR]) ; + size_t setlen = strlen(setname) ; + char fn[repolen + setlen + 17] ; + memcpy(fn, wgola[GOLA_REPODIR], repolen) ; + memcpy(fn + repolen, "/sources/", 9) ; + memcpy(fn + repolen + 9, setname, setlen) ; + fn[repolen + 9 + setlen] = '/' ; + + sub = wgolb & GOLB_IGNORE_ESSENTIALS ? 3 : 4 ; + while (sub--) + { + memcpy(fn + repolen + 10 + setlen, s6rc_repo_subnames[sub], 7) ; + DIR *dir = opendir(fn) ; + if (!dir) strerr_diefu2sys(111, "opendir ", fn) ; + for (;;) + { + direntry *d ; + errno = 0 ; + d = readdir(dir) ; + if (!d) break ; + if (d->d_name[0] == '.') continue ; + if (argc && !bsearch(d->d_name, argv, argc, sizeof(char const *), &str_bcmp)) continue ; + if (buffer_puts(buffer_1, d->d_name) < 0) dieout() ; + if (!(wgolb & GOLB_NOSUB)) + if (buffer_put(buffer_1, "/", 1) < 0 + || buffer_put(buffer_1, s6rc_repo_subnames[sub], 6) < 0) dieout() ; + if (buffer_put(buffer_1, "\n", 1) < 0) dieout() ; + } + if (errno) strerr_diefu2sys(111, "readdir ", fn) ; + dir_close(dir) ; + } + if (!buffer_flush(buffer_1)) strerr_diefu1sys(111, "write to stdout") ; + _exit(0) ; +} -- cgit v1.3.1