From 774654ad56fc9304e4a064232760835c7a2a6c13 Mon Sep 17 00:00:00 2001
From: Laurent Bercot
Date: Sat, 11 Feb 2023 03:12:21 +0000
Subject: Add multicall configuration
Signed-off-by: Laurent Bercot
---
.gitignore | 1 +
Makefile | 30 +-
configure | 15 +-
doc/index.html | 11 +
doc/s6-portable-utils.html | 53 ++++
package/deps.mak | 180 +++++------
package/modes | 1 +
package/targets.mak | 68 ++---
src/multicall/deps-exe/s6-portable-utils | 2 +
src/s6-portable-utils/deps-exe/s6-basename | 1 +
src/s6-portable-utils/deps-exe/s6-cat | 1 +
src/s6-portable-utils/deps-exe/s6-chmod | 1 +
src/s6-portable-utils/deps-exe/s6-chown | 1 +
src/s6-portable-utils/deps-exe/s6-clock | 2 +
src/s6-portable-utils/deps-exe/s6-cut | 1 +
src/s6-portable-utils/deps-exe/s6-dirname | 1 +
src/s6-portable-utils/deps-exe/s6-dumpenv | 1 +
src/s6-portable-utils/deps-exe/s6-echo | 1 +
src/s6-portable-utils/deps-exe/s6-env | 1 +
src/s6-portable-utils/deps-exe/s6-expr | 1 +
src/s6-portable-utils/deps-exe/s6-false | 0
src/s6-portable-utils/deps-exe/s6-format-filter | 1 +
src/s6-portable-utils/deps-exe/s6-grep | 1 +
src/s6-portable-utils/deps-exe/s6-head | 1 +
src/s6-portable-utils/deps-exe/s6-hiercopy | 1 +
src/s6-portable-utils/deps-exe/s6-linkname | 1 +
src/s6-portable-utils/deps-exe/s6-ln | 1 +
src/s6-portable-utils/deps-exe/s6-ls | 1 +
src/s6-portable-utils/deps-exe/s6-maximumtime | 3 +
src/s6-portable-utils/deps-exe/s6-mkdir | 1 +
src/s6-portable-utils/deps-exe/s6-mkfifo | 1 +
src/s6-portable-utils/deps-exe/s6-nice | 1 +
src/s6-portable-utils/deps-exe/s6-nuke | 1 +
src/s6-portable-utils/deps-exe/s6-pause | 1 +
src/s6-portable-utils/deps-exe/s6-printenv | 1 +
src/s6-portable-utils/deps-exe/s6-quote | 1 +
src/s6-portable-utils/deps-exe/s6-quote-filter | 1 +
src/s6-portable-utils/deps-exe/s6-rename | 1 +
src/s6-portable-utils/deps-exe/s6-rmrf | 1 +
src/s6-portable-utils/deps-exe/s6-seq | 1 +
src/s6-portable-utils/deps-exe/s6-sleep | 2 +
src/s6-portable-utils/deps-exe/s6-sort | 1 +
src/s6-portable-utils/deps-exe/s6-sync | 0
src/s6-portable-utils/deps-exe/s6-tai64ndiff | 1 +
src/s6-portable-utils/deps-exe/s6-tail | 1 +
src/s6-portable-utils/deps-exe/s6-touch | 1 +
src/s6-portable-utils/deps-exe/s6-true | 0
src/s6-portable-utils/deps-exe/s6-uniquename | 1 +
src/s6-portable-utils/deps-exe/s6-unquote | 1 +
src/s6-portable-utils/deps-exe/s6-unquote-filter | 1 +
src/s6-portable-utils/deps-exe/s6-update-symlinks | 1 +
src/s6-portable-utils/deps-exe/seekablepipe | 1 +
src/s6-portable-utils/s6-basename.c | 46 +++
src/s6-portable-utils/s6-cat.c | 11 +
src/s6-portable-utils/s6-chmod.c | 34 +++
src/s6-portable-utils/s6-chown.c | 55 ++++
src/s6-portable-utils/s6-clock.c | 31 ++
src/s6-portable-utils/s6-cut.c | 212 +++++++++++++
src/s6-portable-utils/s6-dirname.c | 41 +++
src/s6-portable-utils/s6-dumpenv.c | 72 +++++
src/s6-portable-utils/s6-echo.c | 38 +++
src/s6-portable-utils/s6-env.c | 43 +++
src/s6-portable-utils/s6-expr.c | 205 +++++++++++++
src/s6-portable-utils/s6-false.c | 8 +
src/s6-portable-utils/s6-format-filter.c | 62 ++++
src/s6-portable-utils/s6-grep.c | 139 +++++++++
src/s6-portable-utils/s6-head.c | 164 ++++++++++
src/s6-portable-utils/s6-hiercopy.c | 18 ++
src/s6-portable-utils/s6-linkname.c | 43 +++
src/s6-portable-utils/s6-ln.c | 151 ++++++++++
src/s6-portable-utils/s6-ls.c | 57 ++++
src/s6-portable-utils/s6-maximumtime.c | 98 ++++++
src/s6-portable-utils/s6-mkdir.c | 82 +++++
src/s6-portable-utils/s6-mkfifo.c | 36 +++
src/s6-portable-utils/s6-nice.c | 45 +++
src/s6-portable-utils/s6-nuke.c | 50 ++++
src/s6-portable-utils/s6-pause.c | 50 ++++
src/s6-portable-utils/s6-printenv.c | 52 ++++
src/s6-portable-utils/s6-quote-filter.c | 74 +++++
src/s6-portable-utils/s6-quote.c | 60 ++++
src/s6-portable-utils/s6-rename.c | 16 +
src/s6-portable-utils/s6-rmrf.c | 17 ++
src/s6-portable-utils/s6-seq.c | 63 ++++
src/s6-portable-utils/s6-sleep.c | 44 +++
src/s6-portable-utils/s6-sort.c | 130 ++++++++
src/s6-portable-utils/s6-sync.c | 9 +
src/s6-portable-utils/s6-tai64ndiff.c | 74 +++++
src/s6-portable-utils/s6-tail.c | 199 +++++++++++++
src/s6-portable-utils/s6-touch.c | 15 +
src/s6-portable-utils/s6-true.c | 8 +
src/s6-portable-utils/s6-uniquename.c | 40 +++
src/s6-portable-utils/s6-unquote-filter.c | 198 ++++++++++++
src/s6-portable-utils/s6-unquote.c | 71 +++++
src/s6-portable-utils/s6-update-symlinks.c | 345 +++++++++++++++++++++
src/s6-portable-utils/seekablepipe.c | 32 ++
src/skaembutils/deps-exe/s6-basename | 1 -
src/skaembutils/deps-exe/s6-cat | 1 -
src/skaembutils/deps-exe/s6-chmod | 1 -
src/skaembutils/deps-exe/s6-chown | 1 -
src/skaembutils/deps-exe/s6-clock | 2 -
src/skaembutils/deps-exe/s6-cut | 1 -
src/skaembutils/deps-exe/s6-dirname | 1 -
src/skaembutils/deps-exe/s6-dumpenv | 1 -
src/skaembutils/deps-exe/s6-echo | 1 -
src/skaembutils/deps-exe/s6-env | 1 -
src/skaembutils/deps-exe/s6-expr | 1 -
src/skaembutils/deps-exe/s6-false | 0
src/skaembutils/deps-exe/s6-format-filter | 1 -
src/skaembutils/deps-exe/s6-grep | 1 -
src/skaembutils/deps-exe/s6-head | 1 -
src/skaembutils/deps-exe/s6-hiercopy | 1 -
src/skaembutils/deps-exe/s6-linkname | 1 -
src/skaembutils/deps-exe/s6-ln | 3 -
src/skaembutils/deps-exe/s6-ls | 1 -
src/skaembutils/deps-exe/s6-maximumtime | 3 -
src/skaembutils/deps-exe/s6-mkdir | 1 -
src/skaembutils/deps-exe/s6-mkfifo | 1 -
src/skaembutils/deps-exe/s6-nice | 1 -
src/skaembutils/deps-exe/s6-nuke | 1 -
src/skaembutils/deps-exe/s6-pause | 1 -
src/skaembutils/deps-exe/s6-printenv | 1 -
src/skaembutils/deps-exe/s6-quote | 1 -
src/skaembutils/deps-exe/s6-quote-filter | 1 -
src/skaembutils/deps-exe/s6-rename | 1 -
src/skaembutils/deps-exe/s6-rmrf | 1 -
src/skaembutils/deps-exe/s6-seq | 1 -
src/skaembutils/deps-exe/s6-sleep | 2 -
src/skaembutils/deps-exe/s6-sort | 1 -
src/skaembutils/deps-exe/s6-sync | 0
src/skaembutils/deps-exe/s6-tai64ndiff | 1 -
src/skaembutils/deps-exe/s6-tail | 1 -
src/skaembutils/deps-exe/s6-touch | 1 -
src/skaembutils/deps-exe/s6-true | 0
src/skaembutils/deps-exe/s6-uniquename | 3 -
src/skaembutils/deps-exe/s6-unquote | 1 -
src/skaembutils/deps-exe/s6-unquote-filter | 1 -
src/skaembutils/deps-exe/s6-update-symlinks | 3 -
src/skaembutils/deps-exe/seekablepipe | 1 -
src/skaembutils/s6-basename.c | 46 ---
src/skaembutils/s6-cat.c | 11 -
src/skaembutils/s6-chmod.c | 34 ---
src/skaembutils/s6-chown.c | 55 ----
src/skaembutils/s6-clock.c | 31 --
src/skaembutils/s6-cut.c | 212 -------------
src/skaembutils/s6-dirname.c | 41 ---
src/skaembutils/s6-dumpenv.c | 72 -----
src/skaembutils/s6-echo.c | 38 ---
src/skaembutils/s6-env.c | 43 ---
src/skaembutils/s6-expr.c | 205 -------------
src/skaembutils/s6-false.c | 8 -
src/skaembutils/s6-format-filter.c | 62 ----
src/skaembutils/s6-grep.c | 139 ---------
src/skaembutils/s6-head.c | 164 ----------
src/skaembutils/s6-hiercopy.c | 18 --
src/skaembutils/s6-linkname.c | 43 ---
src/skaembutils/s6-ln.c | 151 ----------
src/skaembutils/s6-ls.c | 57 ----
src/skaembutils/s6-maximumtime.c | 98 ------
src/skaembutils/s6-mkdir.c | 82 -----
src/skaembutils/s6-mkfifo.c | 36 ---
src/skaembutils/s6-nice.c | 45 ---
src/skaembutils/s6-nuke.c | 50 ----
src/skaembutils/s6-pause.c | 50 ----
src/skaembutils/s6-printenv.c | 52 ----
src/skaembutils/s6-quote-filter.c | 74 -----
src/skaembutils/s6-quote.c | 60 ----
src/skaembutils/s6-rename.c | 16 -
src/skaembutils/s6-rmrf.c | 17 --
src/skaembutils/s6-seq.c | 63 ----
src/skaembutils/s6-sleep.c | 44 ---
src/skaembutils/s6-sort.c | 130 --------
src/skaembutils/s6-sync.c | 9 -
src/skaembutils/s6-tai64ndiff.c | 74 -----
src/skaembutils/s6-tail.c | 199 -------------
src/skaembutils/s6-touch.c | 15 -
src/skaembutils/s6-true.c | 8 -
src/skaembutils/s6-uniquename.c | 40 ---
src/skaembutils/s6-unquote-filter.c | 198 ------------
src/skaembutils/s6-unquote.c | 71 -----
src/skaembutils/s6-update-symlinks.c | 348 ----------------------
src/skaembutils/seekablepipe.c | 32 --
tools/gen-multicall.sh | 84 ++++++
tools/install.sh | 11 +-
183 files changed, 3588 insertions(+), 3441 deletions(-)
create mode 100644 doc/s6-portable-utils.html
create mode 100644 src/multicall/deps-exe/s6-portable-utils
create mode 100644 src/s6-portable-utils/deps-exe/s6-basename
create mode 100644 src/s6-portable-utils/deps-exe/s6-cat
create mode 100644 src/s6-portable-utils/deps-exe/s6-chmod
create mode 100644 src/s6-portable-utils/deps-exe/s6-chown
create mode 100644 src/s6-portable-utils/deps-exe/s6-clock
create mode 100644 src/s6-portable-utils/deps-exe/s6-cut
create mode 100644 src/s6-portable-utils/deps-exe/s6-dirname
create mode 100644 src/s6-portable-utils/deps-exe/s6-dumpenv
create mode 100644 src/s6-portable-utils/deps-exe/s6-echo
create mode 100644 src/s6-portable-utils/deps-exe/s6-env
create mode 100644 src/s6-portable-utils/deps-exe/s6-expr
create mode 100644 src/s6-portable-utils/deps-exe/s6-false
create mode 100644 src/s6-portable-utils/deps-exe/s6-format-filter
create mode 100644 src/s6-portable-utils/deps-exe/s6-grep
create mode 100644 src/s6-portable-utils/deps-exe/s6-head
create mode 100644 src/s6-portable-utils/deps-exe/s6-hiercopy
create mode 100644 src/s6-portable-utils/deps-exe/s6-linkname
create mode 100644 src/s6-portable-utils/deps-exe/s6-ln
create mode 100644 src/s6-portable-utils/deps-exe/s6-ls
create mode 100644 src/s6-portable-utils/deps-exe/s6-maximumtime
create mode 100644 src/s6-portable-utils/deps-exe/s6-mkdir
create mode 100644 src/s6-portable-utils/deps-exe/s6-mkfifo
create mode 100644 src/s6-portable-utils/deps-exe/s6-nice
create mode 100644 src/s6-portable-utils/deps-exe/s6-nuke
create mode 100644 src/s6-portable-utils/deps-exe/s6-pause
create mode 100644 src/s6-portable-utils/deps-exe/s6-printenv
create mode 100644 src/s6-portable-utils/deps-exe/s6-quote
create mode 100644 src/s6-portable-utils/deps-exe/s6-quote-filter
create mode 100644 src/s6-portable-utils/deps-exe/s6-rename
create mode 100644 src/s6-portable-utils/deps-exe/s6-rmrf
create mode 100644 src/s6-portable-utils/deps-exe/s6-seq
create mode 100644 src/s6-portable-utils/deps-exe/s6-sleep
create mode 100644 src/s6-portable-utils/deps-exe/s6-sort
create mode 100644 src/s6-portable-utils/deps-exe/s6-sync
create mode 100644 src/s6-portable-utils/deps-exe/s6-tai64ndiff
create mode 100644 src/s6-portable-utils/deps-exe/s6-tail
create mode 100644 src/s6-portable-utils/deps-exe/s6-touch
create mode 100644 src/s6-portable-utils/deps-exe/s6-true
create mode 100644 src/s6-portable-utils/deps-exe/s6-uniquename
create mode 100644 src/s6-portable-utils/deps-exe/s6-unquote
create mode 100644 src/s6-portable-utils/deps-exe/s6-unquote-filter
create mode 100644 src/s6-portable-utils/deps-exe/s6-update-symlinks
create mode 100644 src/s6-portable-utils/deps-exe/seekablepipe
create mode 100644 src/s6-portable-utils/s6-basename.c
create mode 100644 src/s6-portable-utils/s6-cat.c
create mode 100644 src/s6-portable-utils/s6-chmod.c
create mode 100644 src/s6-portable-utils/s6-chown.c
create mode 100644 src/s6-portable-utils/s6-clock.c
create mode 100644 src/s6-portable-utils/s6-cut.c
create mode 100644 src/s6-portable-utils/s6-dirname.c
create mode 100644 src/s6-portable-utils/s6-dumpenv.c
create mode 100644 src/s6-portable-utils/s6-echo.c
create mode 100644 src/s6-portable-utils/s6-env.c
create mode 100644 src/s6-portable-utils/s6-expr.c
create mode 100644 src/s6-portable-utils/s6-false.c
create mode 100644 src/s6-portable-utils/s6-format-filter.c
create mode 100644 src/s6-portable-utils/s6-grep.c
create mode 100644 src/s6-portable-utils/s6-head.c
create mode 100644 src/s6-portable-utils/s6-hiercopy.c
create mode 100644 src/s6-portable-utils/s6-linkname.c
create mode 100644 src/s6-portable-utils/s6-ln.c
create mode 100644 src/s6-portable-utils/s6-ls.c
create mode 100644 src/s6-portable-utils/s6-maximumtime.c
create mode 100644 src/s6-portable-utils/s6-mkdir.c
create mode 100644 src/s6-portable-utils/s6-mkfifo.c
create mode 100644 src/s6-portable-utils/s6-nice.c
create mode 100644 src/s6-portable-utils/s6-nuke.c
create mode 100644 src/s6-portable-utils/s6-pause.c
create mode 100644 src/s6-portable-utils/s6-printenv.c
create mode 100644 src/s6-portable-utils/s6-quote-filter.c
create mode 100644 src/s6-portable-utils/s6-quote.c
create mode 100644 src/s6-portable-utils/s6-rename.c
create mode 100644 src/s6-portable-utils/s6-rmrf.c
create mode 100644 src/s6-portable-utils/s6-seq.c
create mode 100644 src/s6-portable-utils/s6-sleep.c
create mode 100644 src/s6-portable-utils/s6-sort.c
create mode 100644 src/s6-portable-utils/s6-sync.c
create mode 100644 src/s6-portable-utils/s6-tai64ndiff.c
create mode 100644 src/s6-portable-utils/s6-tail.c
create mode 100644 src/s6-portable-utils/s6-touch.c
create mode 100644 src/s6-portable-utils/s6-true.c
create mode 100644 src/s6-portable-utils/s6-uniquename.c
create mode 100644 src/s6-portable-utils/s6-unquote-filter.c
create mode 100644 src/s6-portable-utils/s6-unquote.c
create mode 100644 src/s6-portable-utils/s6-update-symlinks.c
create mode 100644 src/s6-portable-utils/seekablepipe.c
delete mode 100644 src/skaembutils/deps-exe/s6-basename
delete mode 100644 src/skaembutils/deps-exe/s6-cat
delete mode 100644 src/skaembutils/deps-exe/s6-chmod
delete mode 100644 src/skaembutils/deps-exe/s6-chown
delete mode 100644 src/skaembutils/deps-exe/s6-clock
delete mode 100644 src/skaembutils/deps-exe/s6-cut
delete mode 100644 src/skaembutils/deps-exe/s6-dirname
delete mode 100644 src/skaembutils/deps-exe/s6-dumpenv
delete mode 100644 src/skaembutils/deps-exe/s6-echo
delete mode 100644 src/skaembutils/deps-exe/s6-env
delete mode 100644 src/skaembutils/deps-exe/s6-expr
delete mode 100644 src/skaembutils/deps-exe/s6-false
delete mode 100644 src/skaembutils/deps-exe/s6-format-filter
delete mode 100644 src/skaembutils/deps-exe/s6-grep
delete mode 100644 src/skaembutils/deps-exe/s6-head
delete mode 100644 src/skaembutils/deps-exe/s6-hiercopy
delete mode 100644 src/skaembutils/deps-exe/s6-linkname
delete mode 100644 src/skaembutils/deps-exe/s6-ln
delete mode 100644 src/skaembutils/deps-exe/s6-ls
delete mode 100644 src/skaembutils/deps-exe/s6-maximumtime
delete mode 100644 src/skaembutils/deps-exe/s6-mkdir
delete mode 100644 src/skaembutils/deps-exe/s6-mkfifo
delete mode 100644 src/skaembutils/deps-exe/s6-nice
delete mode 100644 src/skaembutils/deps-exe/s6-nuke
delete mode 100644 src/skaembutils/deps-exe/s6-pause
delete mode 100644 src/skaembutils/deps-exe/s6-printenv
delete mode 100644 src/skaembutils/deps-exe/s6-quote
delete mode 100644 src/skaembutils/deps-exe/s6-quote-filter
delete mode 100644 src/skaembutils/deps-exe/s6-rename
delete mode 100644 src/skaembutils/deps-exe/s6-rmrf
delete mode 100644 src/skaembutils/deps-exe/s6-seq
delete mode 100644 src/skaembutils/deps-exe/s6-sleep
delete mode 100644 src/skaembutils/deps-exe/s6-sort
delete mode 100644 src/skaembutils/deps-exe/s6-sync
delete mode 100644 src/skaembutils/deps-exe/s6-tai64ndiff
delete mode 100644 src/skaembutils/deps-exe/s6-tail
delete mode 100644 src/skaembutils/deps-exe/s6-touch
delete mode 100644 src/skaembutils/deps-exe/s6-true
delete mode 100644 src/skaembutils/deps-exe/s6-uniquename
delete mode 100644 src/skaembutils/deps-exe/s6-unquote
delete mode 100644 src/skaembutils/deps-exe/s6-unquote-filter
delete mode 100644 src/skaembutils/deps-exe/s6-update-symlinks
delete mode 100644 src/skaembutils/deps-exe/seekablepipe
delete mode 100644 src/skaembutils/s6-basename.c
delete mode 100644 src/skaembutils/s6-cat.c
delete mode 100644 src/skaembutils/s6-chmod.c
delete mode 100644 src/skaembutils/s6-chown.c
delete mode 100644 src/skaembutils/s6-clock.c
delete mode 100644 src/skaembutils/s6-cut.c
delete mode 100644 src/skaembutils/s6-dirname.c
delete mode 100644 src/skaembutils/s6-dumpenv.c
delete mode 100644 src/skaembutils/s6-echo.c
delete mode 100644 src/skaembutils/s6-env.c
delete mode 100644 src/skaembutils/s6-expr.c
delete mode 100644 src/skaembutils/s6-false.c
delete mode 100644 src/skaembutils/s6-format-filter.c
delete mode 100644 src/skaembutils/s6-grep.c
delete mode 100644 src/skaembutils/s6-head.c
delete mode 100644 src/skaembutils/s6-hiercopy.c
delete mode 100644 src/skaembutils/s6-linkname.c
delete mode 100644 src/skaembutils/s6-ln.c
delete mode 100644 src/skaembutils/s6-ls.c
delete mode 100644 src/skaembutils/s6-maximumtime.c
delete mode 100644 src/skaembutils/s6-mkdir.c
delete mode 100644 src/skaembutils/s6-mkfifo.c
delete mode 100644 src/skaembutils/s6-nice.c
delete mode 100644 src/skaembutils/s6-nuke.c
delete mode 100644 src/skaembutils/s6-pause.c
delete mode 100644 src/skaembutils/s6-printenv.c
delete mode 100644 src/skaembutils/s6-quote-filter.c
delete mode 100644 src/skaembutils/s6-quote.c
delete mode 100644 src/skaembutils/s6-rename.c
delete mode 100644 src/skaembutils/s6-rmrf.c
delete mode 100644 src/skaembutils/s6-seq.c
delete mode 100644 src/skaembutils/s6-sleep.c
delete mode 100644 src/skaembutils/s6-sort.c
delete mode 100644 src/skaembutils/s6-sync.c
delete mode 100644 src/skaembutils/s6-tai64ndiff.c
delete mode 100644 src/skaembutils/s6-tail.c
delete mode 100644 src/skaembutils/s6-touch.c
delete mode 100644 src/skaembutils/s6-true.c
delete mode 100644 src/skaembutils/s6-uniquename.c
delete mode 100644 src/skaembutils/s6-unquote-filter.c
delete mode 100644 src/skaembutils/s6-unquote.c
delete mode 100644 src/skaembutils/s6-update-symlinks.c
delete mode 100644 src/skaembutils/seekablepipe.c
create mode 100755 tools/gen-multicall.sh
diff --git a/.gitignore b/.gitignore
index 6e2876c..d77920a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -49,3 +49,4 @@
/s6-unquote-filter
/s6-update-symlinks
/seekablepipe
+/s6-portable-utils
diff --git a/Makefile b/Makefile
index cd6c7f0..0fc3d40 100644
--- a/Makefile
+++ b/Makefile
@@ -17,8 +17,9 @@ CC = $(error Please use ./configure first)
STATIC_LIBS :=
SHARED_LIBS :=
INTERNAL_LIBS :=
-EXTRA_TARGETS :=
LIB_DEFS :=
+BIN_SYMLINKS :=
+EXTRA_TEMP :=
define library_definition
LIB$(firstword $(subst =, ,$(1))) := lib$(lastword $(subst =, ,$(1))).$(if $(DO_ALLSTATIC),a,so).xyzzy
@@ -53,14 +54,14 @@ RANLIB := $(CROSS_COMPILE)ranlib
STRIP := $(CROSS_COMPILE)strip
INSTALL := ./tools/install.sh
-ALL_BINS := $(LIBEXEC_TARGETS) $(BIN_TARGETS)
+ALL_BINS := $(BIN_TARGETS) $(LIBEXEC_TARGETS)
ALL_LIBS := $(SHARED_LIBS) $(STATIC_LIBS) $(INTERNAL_LIBS)
ALL_INCLUDES := $(wildcard src/include/$(package)/*.h)
all: $(ALL_LIBS) $(ALL_BINS) $(ALL_INCLUDES)
clean:
- @exec rm -f $(ALL_LIBS) $(ALL_BINS) $(wildcard src/*/*.o src/*/*.lo) $(EXTRA_TARGETS)
+ @exec rm -f $(ALL_LIBS) $(ALL_BINS) $(EXTRA_TEMP) $(wildcard src/*/*.o src/*/*.lo)
distclean: clean
@exec rm -f config.mak src/include/$(package)/config.h
@@ -84,7 +85,7 @@ endif
install: install-dynlib install-libexec install-bin install-lib install-include
install-dynlib: $(SHARED_LIBS:lib%.so.xyzzy=$(DESTDIR)$(dynlibdir)/lib%.so)
install-libexec: $(LIBEXEC_TARGETS:%=$(DESTDIR)$(libexecdir)/%)
-install-bin: $(BIN_TARGETS:%=$(DESTDIR)$(bindir)/%)
+install-bin: $(BIN_TARGETS:%=$(DESTDIR)$(bindir)/%) $(BIN_SYMLINKS:%=$(DESTDIR)$(bindir)/%)
install-lib: $(STATIC_LIBS:lib%.a.xyzzy=$(DESTDIR)$(libdir)/lib%.a)
install-include: $(ALL_INCLUDES:src/include/$(package)/%.h=$(DESTDIR)$(includedir)/$(package)/%.h)
install-data: $(ALL_DATA:src/etc/%=$(DESTDIR)$(datadir)/%)
@@ -96,7 +97,7 @@ $(DESTDIR)$(exthome): $(DESTDIR)$(home)
update: $(DESTDIR)$(exthome)
-global-links: $(DESTDIR)$(exthome) $(SHARED_LIBS:lib%.so.xyzzy=$(DESTDIR)$(sproot)/library.so/lib%.so.$(version_M)) $(BIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%)
+global-links: $(DESTDIR)$(exthome) $(SHARED_LIBS:lib%.so.xyzzy=$(DESTDIR)$(sproot)/library.so/lib%.so.$(version_M)) $(BIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%) $(BIN_SYMLINKS:%=$(DESTDIR)$(sproot)/command/%)
$(DESTDIR)$(sproot)/command/%: $(DESTDIR)$(home)/command/%
exec $(INSTALL) -D -l ..$(subst $(sproot),,$(exthome))/command/$(
- See the enclosed INSTALL file for installation details.
+ - Starting with version 2.3.0.0, you can use the
+--enable-multicall configure option to save disk space.
Upgrade notes
@@ -126,6 +128,9 @@ the previous versions of s6-portable-utils and the current one.
126 if they fail to execute into a program for another reason.
+
+ (Miscellaneous tools)
+
+
+ (Multicall configuration)
+
+
Related resources
diff --git a/doc/s6-portable-utils.html b/doc/s6-portable-utils.html
new file mode 100644
index 0000000..5700f38
--- /dev/null
+++ b/doc/s6-portable-utils.html
@@ -0,0 +1,53 @@
+
+
+
+
+
+ s6-portable-utils: the s6-portable-utils multicall binary
+
+
+
+
+
+
+
+s6-portable-utils
+Software
+skarnet.org
+
+
+ The s6-portable-utils multicall binary
+
+
+The s6-portable-utils program is only available when the
+--enable-multicall option has been given to the configure
+program at build time. In this configuration, s6-portable-utils is
+a multicall binary implementing the functionality of all
+the programs in the s6-portable-utils package; and the other programs, instead
+of being executables of their own, are symbolic links to the
+s6-portable-utils binary.
+
+
+ Interface
+
+
+ s6-portable-utils subcommand subcommand_arguments...
+
+
+
+ s6-portable-utils will run the subcommand will its arguments. For
+instance, s6-portable-utils s6-seq 1 10 will run the equivalent of the
+program, so this command will list natural numbers
+from 1 to 10.
+
+
+
+ Alternatively, if s6-portable-utils is called with the name of an existing
+command, it will run the equivalent of that command. For instance,
+if the /usr/bin/s6-seq file is a (hard or symbolic) link to
+the s6-portable-utils binary, /usr/bin/s6-seq 1 10 will list
+natural numbers from 1 to 10.
+
+
+
+
diff --git a/package/deps.mak b/package/deps.mak
index 3593d61..d4e6bf6 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -2,133 +2,135 @@
# This file has been generated by tools/gen-deps.sh
#
-src/skaembutils/s6-basename.o src/skaembutils/s6-basename.lo: src/skaembutils/s6-basename.c
-src/skaembutils/s6-cat.o src/skaembutils/s6-cat.lo: src/skaembutils/s6-cat.c
-src/skaembutils/s6-chmod.o src/skaembutils/s6-chmod.lo: src/skaembutils/s6-chmod.c
-src/skaembutils/s6-chown.o src/skaembutils/s6-chown.lo: src/skaembutils/s6-chown.c
-src/skaembutils/s6-clock.o src/skaembutils/s6-clock.lo: src/skaembutils/s6-clock.c
-src/skaembutils/s6-cut.o src/skaembutils/s6-cut.lo: src/skaembutils/s6-cut.c
-src/skaembutils/s6-dirname.o src/skaembutils/s6-dirname.lo: src/skaembutils/s6-dirname.c
-src/skaembutils/s6-dumpenv.o src/skaembutils/s6-dumpenv.lo: src/skaembutils/s6-dumpenv.c
-src/skaembutils/s6-echo.o src/skaembutils/s6-echo.lo: src/skaembutils/s6-echo.c
-src/skaembutils/s6-env.o src/skaembutils/s6-env.lo: src/skaembutils/s6-env.c src/include/s6-portable-utils/config.h
-src/skaembutils/s6-expr.o src/skaembutils/s6-expr.lo: src/skaembutils/s6-expr.c
-src/skaembutils/s6-false.o src/skaembutils/s6-false.lo: src/skaembutils/s6-false.c
-src/skaembutils/s6-format-filter.o src/skaembutils/s6-format-filter.lo: src/skaembutils/s6-format-filter.c
-src/skaembutils/s6-grep.o src/skaembutils/s6-grep.lo: src/skaembutils/s6-grep.c
-src/skaembutils/s6-head.o src/skaembutils/s6-head.lo: src/skaembutils/s6-head.c
-src/skaembutils/s6-hiercopy.o src/skaembutils/s6-hiercopy.lo: src/skaembutils/s6-hiercopy.c
-src/skaembutils/s6-linkname.o src/skaembutils/s6-linkname.lo: src/skaembutils/s6-linkname.c
-src/skaembutils/s6-ln.o src/skaembutils/s6-ln.lo: src/skaembutils/s6-ln.c
-src/skaembutils/s6-ls.o src/skaembutils/s6-ls.lo: src/skaembutils/s6-ls.c
-src/skaembutils/s6-maximumtime.o src/skaembutils/s6-maximumtime.lo: src/skaembutils/s6-maximumtime.c
-src/skaembutils/s6-mkdir.o src/skaembutils/s6-mkdir.lo: src/skaembutils/s6-mkdir.c
-src/skaembutils/s6-mkfifo.o src/skaembutils/s6-mkfifo.lo: src/skaembutils/s6-mkfifo.c
-src/skaembutils/s6-nice.o src/skaembutils/s6-nice.lo: src/skaembutils/s6-nice.c
-src/skaembutils/s6-nuke.o src/skaembutils/s6-nuke.lo: src/skaembutils/s6-nuke.c
-src/skaembutils/s6-pause.o src/skaembutils/s6-pause.lo: src/skaembutils/s6-pause.c
-src/skaembutils/s6-printenv.o src/skaembutils/s6-printenv.lo: src/skaembutils/s6-printenv.c
-src/skaembutils/s6-quote-filter.o src/skaembutils/s6-quote-filter.lo: src/skaembutils/s6-quote-filter.c
-src/skaembutils/s6-quote.o src/skaembutils/s6-quote.lo: src/skaembutils/s6-quote.c
-src/skaembutils/s6-rename.o src/skaembutils/s6-rename.lo: src/skaembutils/s6-rename.c
-src/skaembutils/s6-rmrf.o src/skaembutils/s6-rmrf.lo: src/skaembutils/s6-rmrf.c
-src/skaembutils/s6-seq.o src/skaembutils/s6-seq.lo: src/skaembutils/s6-seq.c
-src/skaembutils/s6-sleep.o src/skaembutils/s6-sleep.lo: src/skaembutils/s6-sleep.c
-src/skaembutils/s6-sort.o src/skaembutils/s6-sort.lo: src/skaembutils/s6-sort.c
-src/skaembutils/s6-sync.o src/skaembutils/s6-sync.lo: src/skaembutils/s6-sync.c
-src/skaembutils/s6-tai64ndiff.o src/skaembutils/s6-tai64ndiff.lo: src/skaembutils/s6-tai64ndiff.c
-src/skaembutils/s6-tail.o src/skaembutils/s6-tail.lo: src/skaembutils/s6-tail.c
-src/skaembutils/s6-touch.o src/skaembutils/s6-touch.lo: src/skaembutils/s6-touch.c
-src/skaembutils/s6-true.o src/skaembutils/s6-true.lo: src/skaembutils/s6-true.c
-src/skaembutils/s6-uniquename.o src/skaembutils/s6-uniquename.lo: src/skaembutils/s6-uniquename.c
-src/skaembutils/s6-unquote-filter.o src/skaembutils/s6-unquote-filter.lo: src/skaembutils/s6-unquote-filter.c
-src/skaembutils/s6-unquote.o src/skaembutils/s6-unquote.lo: src/skaembutils/s6-unquote.c
-src/skaembutils/s6-update-symlinks.o src/skaembutils/s6-update-symlinks.lo: src/skaembutils/s6-update-symlinks.c
-src/skaembutils/seekablepipe.o src/skaembutils/seekablepipe.lo: src/skaembutils/seekablepipe.c
+src/s6-portable-utils/s6-basename.o src/s6-portable-utils/s6-basename.lo: src/s6-portable-utils/s6-basename.c
+src/s6-portable-utils/s6-cat.o src/s6-portable-utils/s6-cat.lo: src/s6-portable-utils/s6-cat.c
+src/s6-portable-utils/s6-chmod.o src/s6-portable-utils/s6-chmod.lo: src/s6-portable-utils/s6-chmod.c
+src/s6-portable-utils/s6-chown.o src/s6-portable-utils/s6-chown.lo: src/s6-portable-utils/s6-chown.c
+src/s6-portable-utils/s6-clock.o src/s6-portable-utils/s6-clock.lo: src/s6-portable-utils/s6-clock.c
+src/s6-portable-utils/s6-cut.o src/s6-portable-utils/s6-cut.lo: src/s6-portable-utils/s6-cut.c
+src/s6-portable-utils/s6-dirname.o src/s6-portable-utils/s6-dirname.lo: src/s6-portable-utils/s6-dirname.c
+src/s6-portable-utils/s6-dumpenv.o src/s6-portable-utils/s6-dumpenv.lo: src/s6-portable-utils/s6-dumpenv.c
+src/s6-portable-utils/s6-echo.o src/s6-portable-utils/s6-echo.lo: src/s6-portable-utils/s6-echo.c
+src/s6-portable-utils/s6-env.o src/s6-portable-utils/s6-env.lo: src/s6-portable-utils/s6-env.c src/include/s6-portable-utils/config.h
+src/s6-portable-utils/s6-expr.o src/s6-portable-utils/s6-expr.lo: src/s6-portable-utils/s6-expr.c
+src/s6-portable-utils/s6-false.o src/s6-portable-utils/s6-false.lo: src/s6-portable-utils/s6-false.c
+src/s6-portable-utils/s6-format-filter.o src/s6-portable-utils/s6-format-filter.lo: src/s6-portable-utils/s6-format-filter.c
+src/s6-portable-utils/s6-grep.o src/s6-portable-utils/s6-grep.lo: src/s6-portable-utils/s6-grep.c
+src/s6-portable-utils/s6-head.o src/s6-portable-utils/s6-head.lo: src/s6-portable-utils/s6-head.c
+src/s6-portable-utils/s6-hiercopy.o src/s6-portable-utils/s6-hiercopy.lo: src/s6-portable-utils/s6-hiercopy.c
+src/s6-portable-utils/s6-linkname.o src/s6-portable-utils/s6-linkname.lo: src/s6-portable-utils/s6-linkname.c
+src/s6-portable-utils/s6-ln.o src/s6-portable-utils/s6-ln.lo: src/s6-portable-utils/s6-ln.c
+src/s6-portable-utils/s6-ls.o src/s6-portable-utils/s6-ls.lo: src/s6-portable-utils/s6-ls.c
+src/s6-portable-utils/s6-maximumtime.o src/s6-portable-utils/s6-maximumtime.lo: src/s6-portable-utils/s6-maximumtime.c
+src/s6-portable-utils/s6-mkdir.o src/s6-portable-utils/s6-mkdir.lo: src/s6-portable-utils/s6-mkdir.c
+src/s6-portable-utils/s6-mkfifo.o src/s6-portable-utils/s6-mkfifo.lo: src/s6-portable-utils/s6-mkfifo.c
+src/s6-portable-utils/s6-nice.o src/s6-portable-utils/s6-nice.lo: src/s6-portable-utils/s6-nice.c
+src/s6-portable-utils/s6-nuke.o src/s6-portable-utils/s6-nuke.lo: src/s6-portable-utils/s6-nuke.c
+src/s6-portable-utils/s6-pause.o src/s6-portable-utils/s6-pause.lo: src/s6-portable-utils/s6-pause.c
+src/s6-portable-utils/s6-printenv.o src/s6-portable-utils/s6-printenv.lo: src/s6-portable-utils/s6-printenv.c
+src/s6-portable-utils/s6-quote-filter.o src/s6-portable-utils/s6-quote-filter.lo: src/s6-portable-utils/s6-quote-filter.c
+src/s6-portable-utils/s6-quote.o src/s6-portable-utils/s6-quote.lo: src/s6-portable-utils/s6-quote.c
+src/s6-portable-utils/s6-rename.o src/s6-portable-utils/s6-rename.lo: src/s6-portable-utils/s6-rename.c
+src/s6-portable-utils/s6-rmrf.o src/s6-portable-utils/s6-rmrf.lo: src/s6-portable-utils/s6-rmrf.c
+src/s6-portable-utils/s6-seq.o src/s6-portable-utils/s6-seq.lo: src/s6-portable-utils/s6-seq.c
+src/s6-portable-utils/s6-sleep.o src/s6-portable-utils/s6-sleep.lo: src/s6-portable-utils/s6-sleep.c
+src/s6-portable-utils/s6-sort.o src/s6-portable-utils/s6-sort.lo: src/s6-portable-utils/s6-sort.c
+src/s6-portable-utils/s6-sync.o src/s6-portable-utils/s6-sync.lo: src/s6-portable-utils/s6-sync.c
+src/s6-portable-utils/s6-tai64ndiff.o src/s6-portable-utils/s6-tai64ndiff.lo: src/s6-portable-utils/s6-tai64ndiff.c
+src/s6-portable-utils/s6-tail.o src/s6-portable-utils/s6-tail.lo: src/s6-portable-utils/s6-tail.c
+src/s6-portable-utils/s6-touch.o src/s6-portable-utils/s6-touch.lo: src/s6-portable-utils/s6-touch.c
+src/s6-portable-utils/s6-true.o src/s6-portable-utils/s6-true.lo: src/s6-portable-utils/s6-true.c
+src/s6-portable-utils/s6-uniquename.o src/s6-portable-utils/s6-uniquename.lo: src/s6-portable-utils/s6-uniquename.c
+src/s6-portable-utils/s6-unquote-filter.o src/s6-portable-utils/s6-unquote-filter.lo: src/s6-portable-utils/s6-unquote-filter.c
+src/s6-portable-utils/s6-unquote.o src/s6-portable-utils/s6-unquote.lo: src/s6-portable-utils/s6-unquote.c
+src/s6-portable-utils/s6-update-symlinks.o src/s6-portable-utils/s6-update-symlinks.lo: src/s6-portable-utils/s6-update-symlinks.c
+src/s6-portable-utils/seekablepipe.o src/s6-portable-utils/seekablepipe.lo: src/s6-portable-utils/seekablepipe.c
+s6-portable-utils: EXTRA_LIBS := -lskarnet ${SPAWN_LIB}
+s6-portable-utils: src/multicall/s6-portable-utils.o
s6-basename: EXTRA_LIBS := -lskarnet
-s6-basename: src/skaembutils/s6-basename.o
+s6-basename: src/s6-portable-utils/s6-basename.o
s6-cat: EXTRA_LIBS := -lskarnet
-s6-cat: src/skaembutils/s6-cat.o
+s6-cat: src/s6-portable-utils/s6-cat.o
s6-chmod: EXTRA_LIBS := -lskarnet
-s6-chmod: src/skaembutils/s6-chmod.o
+s6-chmod: src/s6-portable-utils/s6-chmod.o
s6-chown: EXTRA_LIBS := -lskarnet
-s6-chown: src/skaembutils/s6-chown.o
+s6-chown: src/s6-portable-utils/s6-chown.o
s6-clock: EXTRA_LIBS := -lskarnet ${SYSCLOCK_LIB}
-s6-clock: src/skaembutils/s6-clock.o
+s6-clock: src/s6-portable-utils/s6-clock.o
s6-cut: EXTRA_LIBS := -lskarnet
-s6-cut: src/skaembutils/s6-cut.o
+s6-cut: src/s6-portable-utils/s6-cut.o
s6-dirname: EXTRA_LIBS := -lskarnet
-s6-dirname: src/skaembutils/s6-dirname.o
+s6-dirname: src/s6-portable-utils/s6-dirname.o
s6-dumpenv: EXTRA_LIBS := -lskarnet
-s6-dumpenv: src/skaembutils/s6-dumpenv.o
+s6-dumpenv: src/s6-portable-utils/s6-dumpenv.o
s6-echo: EXTRA_LIBS := -lskarnet
-s6-echo: src/skaembutils/s6-echo.o
+s6-echo: src/s6-portable-utils/s6-echo.o
s6-env: EXTRA_LIBS := -lskarnet
-s6-env: src/skaembutils/s6-env.o
+s6-env: src/s6-portable-utils/s6-env.o
s6-expr: EXTRA_LIBS := -lskarnet
-s6-expr: src/skaembutils/s6-expr.o
+s6-expr: src/s6-portable-utils/s6-expr.o
s6-false: EXTRA_LIBS :=
-s6-false: src/skaembutils/s6-false.o
+s6-false: src/s6-portable-utils/s6-false.o
s6-format-filter: EXTRA_LIBS := -lskarnet
-s6-format-filter: src/skaembutils/s6-format-filter.o
+s6-format-filter: src/s6-portable-utils/s6-format-filter.o
s6-grep: EXTRA_LIBS := -lskarnet
-s6-grep: src/skaembutils/s6-grep.o
+s6-grep: src/s6-portable-utils/s6-grep.o
s6-head: EXTRA_LIBS := -lskarnet
-s6-head: src/skaembutils/s6-head.o
+s6-head: src/s6-portable-utils/s6-head.o
s6-hiercopy: EXTRA_LIBS := -lskarnet
-s6-hiercopy: src/skaembutils/s6-hiercopy.o
+s6-hiercopy: src/s6-portable-utils/s6-hiercopy.o
s6-linkname: EXTRA_LIBS := -lskarnet
-s6-linkname: src/skaembutils/s6-linkname.o
-s6-ln: EXTRA_LIBS := -lskarnet ${SOCKET_LIB} ${SYSCLOCK_LIB}
-s6-ln: src/skaembutils/s6-ln.o
+s6-linkname: src/s6-portable-utils/s6-linkname.o
+s6-ln: EXTRA_LIBS := -lskarnet
+s6-ln: src/s6-portable-utils/s6-ln.o
s6-ls: EXTRA_LIBS := -lskarnet
-s6-ls: src/skaembutils/s6-ls.o
+s6-ls: src/s6-portable-utils/s6-ls.o
s6-maximumtime: EXTRA_LIBS := -lskarnet ${SYSCLOCK_LIB} ${SPAWN_LIB}
-s6-maximumtime: src/skaembutils/s6-maximumtime.o
+s6-maximumtime: src/s6-portable-utils/s6-maximumtime.o
s6-mkdir: EXTRA_LIBS := -lskarnet
-s6-mkdir: src/skaembutils/s6-mkdir.o
+s6-mkdir: src/s6-portable-utils/s6-mkdir.o
s6-mkfifo: EXTRA_LIBS := -lskarnet
-s6-mkfifo: src/skaembutils/s6-mkfifo.o
+s6-mkfifo: src/s6-portable-utils/s6-mkfifo.o
s6-nice: EXTRA_LIBS := -lskarnet
-s6-nice: src/skaembutils/s6-nice.o
+s6-nice: src/s6-portable-utils/s6-nice.o
s6-nuke: EXTRA_LIBS := -lskarnet
-s6-nuke: src/skaembutils/s6-nuke.o
+s6-nuke: src/s6-portable-utils/s6-nuke.o
s6-pause: EXTRA_LIBS := -lskarnet
-s6-pause: src/skaembutils/s6-pause.o
+s6-pause: src/s6-portable-utils/s6-pause.o
s6-printenv: EXTRA_LIBS := -lskarnet
-s6-printenv: src/skaembutils/s6-printenv.o
+s6-printenv: src/s6-portable-utils/s6-printenv.o
s6-quote: EXTRA_LIBS := -lskarnet
-s6-quote: src/skaembutils/s6-quote.o
+s6-quote: src/s6-portable-utils/s6-quote.o
s6-quote-filter: EXTRA_LIBS := -lskarnet
-s6-quote-filter: src/skaembutils/s6-quote-filter.o
+s6-quote-filter: src/s6-portable-utils/s6-quote-filter.o
s6-rename: EXTRA_LIBS := -lskarnet
-s6-rename: src/skaembutils/s6-rename.o
+s6-rename: src/s6-portable-utils/s6-rename.o
s6-rmrf: EXTRA_LIBS := -lskarnet
-s6-rmrf: src/skaembutils/s6-rmrf.o
+s6-rmrf: src/s6-portable-utils/s6-rmrf.o
s6-seq: EXTRA_LIBS := -lskarnet
-s6-seq: src/skaembutils/s6-seq.o
+s6-seq: src/s6-portable-utils/s6-seq.o
s6-sleep: EXTRA_LIBS := -lskarnet ${SYSCLOCK_LIB}
-s6-sleep: src/skaembutils/s6-sleep.o
+s6-sleep: src/s6-portable-utils/s6-sleep.o
s6-sort: EXTRA_LIBS := -lskarnet
-s6-sort: src/skaembutils/s6-sort.o
+s6-sort: src/s6-portable-utils/s6-sort.o
s6-sync: EXTRA_LIBS :=
-s6-sync: src/skaembutils/s6-sync.o
+s6-sync: src/s6-portable-utils/s6-sync.o
s6-tai64ndiff: EXTRA_LIBS := -lskarnet
-s6-tai64ndiff: src/skaembutils/s6-tai64ndiff.o
+s6-tai64ndiff: src/s6-portable-utils/s6-tai64ndiff.o
s6-tail: EXTRA_LIBS := -lskarnet
-s6-tail: src/skaembutils/s6-tail.o
+s6-tail: src/s6-portable-utils/s6-tail.o
s6-touch: EXTRA_LIBS := -lskarnet
-s6-touch: src/skaembutils/s6-touch.o
+s6-touch: src/s6-portable-utils/s6-touch.o
s6-true: EXTRA_LIBS :=
-s6-true: src/skaembutils/s6-true.o
-s6-uniquename: EXTRA_LIBS := -lskarnet ${SOCKET_LIB} ${SYSCLOCK_LIB}
-s6-uniquename: src/skaembutils/s6-uniquename.o
+s6-true: src/s6-portable-utils/s6-true.o
+s6-uniquename: EXTRA_LIBS := -lskarnet
+s6-uniquename: src/s6-portable-utils/s6-uniquename.o
s6-unquote: EXTRA_LIBS := -lskarnet
-s6-unquote: src/skaembutils/s6-unquote.o
+s6-unquote: src/s6-portable-utils/s6-unquote.o
s6-unquote-filter: EXTRA_LIBS := -lskarnet
-s6-unquote-filter: src/skaembutils/s6-unquote-filter.o
-s6-update-symlinks: EXTRA_LIBS := -lskarnet ${SOCKET_LIB} ${SYSCLOCK_LIB}
-s6-update-symlinks: src/skaembutils/s6-update-symlinks.o
+s6-unquote-filter: src/s6-portable-utils/s6-unquote-filter.o
+s6-update-symlinks: EXTRA_LIBS := -lskarnet
+s6-update-symlinks: src/s6-portable-utils/s6-update-symlinks.o
seekablepipe: EXTRA_LIBS := -lskarnet
-seekablepipe: src/skaembutils/seekablepipe.o
+seekablepipe: src/s6-portable-utils/seekablepipe.o
diff --git a/package/modes b/package/modes
index cd33bbd..d45eecf 100644
--- a/package/modes
+++ b/package/modes
@@ -41,3 +41,4 @@ s6-unquote 0755
s6-unquote-filter 0755
s6-update-symlinks 0755
seekablepipe 0755
+s6-portable-utils 0755
diff --git a/package/targets.mak b/package/targets.mak
index b8c613e..6403a9b 100644
--- a/package/targets.mak
+++ b/package/targets.mak
@@ -1,46 +1,24 @@
-BIN_TARGETS := \
-s6-basename \
-s6-cat \
-s6-chmod \
-s6-chown \
-s6-clock \
-s6-cut \
-s6-dirname \
-s6-dumpenv \
-s6-echo \
-s6-env \
-s6-expr \
-s6-false \
-s6-format-filter \
-s6-grep \
-s6-head \
-s6-hiercopy \
-s6-linkname \
-s6-ln \
-s6-ls \
-s6-maximumtime \
-s6-mkdir \
-s6-mkfifo \
-s6-nice \
-s6-nuke \
-s6-pause \
-s6-printenv \
-s6-quote \
-s6-quote-filter \
-s6-rename \
-s6-rmrf \
-s6-seq \
-s6-sleep \
-s6-sort \
-s6-sync \
-s6-tai64ndiff \
-s6-tail \
-s6-touch \
-s6-true \
-s6-uniquename \
-s6-unquote \
-s6-unquote-filter \
-s6-update-symlinks \
-seekablepipe
-
LIBEXEC_TARGETS :=
+
+ifeq ($(MULTICALL),1)
+
+BIN_TARGETS := $(package)
+BIN_SYMLINKS := $(notdir $(wildcard src/$(package)/deps-exe/*))
+EXTRA_TEMP := src/multicall/$(package).c
+
+define symlink_definition
+SYMLINK_TARGET_$(1) := $(package)
+endef
+$(foreach name,$(BIN_SYMLINKS),$(eval $(call symlink_definition,$(name))))
+
+src/multicall/$(package).c: tools/gen-multicall.sh src/$(package)/deps-exe
+ ./tools/gen-multicall.sh $(package) > src/multicall/$(package).c
+
+src/multicall/$(package).o: src/multicall/$(package).c src/include/$(package)/config.h
+
+else
+
+BIN_TARGETS := $(notdir $(wildcard src/$(package)/deps-exe/*))
+BIN_SYMLINKS :=
+
+endif
diff --git a/src/multicall/deps-exe/s6-portable-utils b/src/multicall/deps-exe/s6-portable-utils
new file mode 100644
index 0000000..39597dd
--- /dev/null
+++ b/src/multicall/deps-exe/s6-portable-utils
@@ -0,0 +1,2 @@
+-lskarnet
+${SPAWN_LIB}
diff --git a/src/s6-portable-utils/deps-exe/s6-basename b/src/s6-portable-utils/deps-exe/s6-basename
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-basename
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-cat b/src/s6-portable-utils/deps-exe/s6-cat
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-cat
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-chmod b/src/s6-portable-utils/deps-exe/s6-chmod
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-chmod
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-chown b/src/s6-portable-utils/deps-exe/s6-chown
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-chown
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-clock b/src/s6-portable-utils/deps-exe/s6-clock
new file mode 100644
index 0000000..a11a5f4
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-clock
@@ -0,0 +1,2 @@
+-lskarnet
+${SYSCLOCK_LIB}
diff --git a/src/s6-portable-utils/deps-exe/s6-cut b/src/s6-portable-utils/deps-exe/s6-cut
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-cut
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-dirname b/src/s6-portable-utils/deps-exe/s6-dirname
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-dirname
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-dumpenv b/src/s6-portable-utils/deps-exe/s6-dumpenv
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-dumpenv
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-echo b/src/s6-portable-utils/deps-exe/s6-echo
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-echo
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-env b/src/s6-portable-utils/deps-exe/s6-env
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-env
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-expr b/src/s6-portable-utils/deps-exe/s6-expr
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-expr
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-false b/src/s6-portable-utils/deps-exe/s6-false
new file mode 100644
index 0000000..e69de29
diff --git a/src/s6-portable-utils/deps-exe/s6-format-filter b/src/s6-portable-utils/deps-exe/s6-format-filter
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-format-filter
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-grep b/src/s6-portable-utils/deps-exe/s6-grep
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-grep
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-head b/src/s6-portable-utils/deps-exe/s6-head
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-head
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-hiercopy b/src/s6-portable-utils/deps-exe/s6-hiercopy
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-hiercopy
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-linkname b/src/s6-portable-utils/deps-exe/s6-linkname
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-linkname
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-ln b/src/s6-portable-utils/deps-exe/s6-ln
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-ln
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-ls b/src/s6-portable-utils/deps-exe/s6-ls
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-ls
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-maximumtime b/src/s6-portable-utils/deps-exe/s6-maximumtime
new file mode 100644
index 0000000..756dcc2
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-maximumtime
@@ -0,0 +1,3 @@
+-lskarnet
+${SYSCLOCK_LIB}
+${SPAWN_LIB}
diff --git a/src/s6-portable-utils/deps-exe/s6-mkdir b/src/s6-portable-utils/deps-exe/s6-mkdir
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-mkdir
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-mkfifo b/src/s6-portable-utils/deps-exe/s6-mkfifo
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-mkfifo
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-nice b/src/s6-portable-utils/deps-exe/s6-nice
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-nice
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-nuke b/src/s6-portable-utils/deps-exe/s6-nuke
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-nuke
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-pause b/src/s6-portable-utils/deps-exe/s6-pause
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-pause
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-printenv b/src/s6-portable-utils/deps-exe/s6-printenv
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-printenv
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-quote b/src/s6-portable-utils/deps-exe/s6-quote
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-quote
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-quote-filter b/src/s6-portable-utils/deps-exe/s6-quote-filter
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-quote-filter
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-rename b/src/s6-portable-utils/deps-exe/s6-rename
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-rename
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-rmrf b/src/s6-portable-utils/deps-exe/s6-rmrf
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-rmrf
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-seq b/src/s6-portable-utils/deps-exe/s6-seq
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-seq
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-sleep b/src/s6-portable-utils/deps-exe/s6-sleep
new file mode 100644
index 0000000..a11a5f4
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-sleep
@@ -0,0 +1,2 @@
+-lskarnet
+${SYSCLOCK_LIB}
diff --git a/src/s6-portable-utils/deps-exe/s6-sort b/src/s6-portable-utils/deps-exe/s6-sort
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-sort
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-sync b/src/s6-portable-utils/deps-exe/s6-sync
new file mode 100644
index 0000000..e69de29
diff --git a/src/s6-portable-utils/deps-exe/s6-tai64ndiff b/src/s6-portable-utils/deps-exe/s6-tai64ndiff
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-tai64ndiff
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-tail b/src/s6-portable-utils/deps-exe/s6-tail
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-tail
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-touch b/src/s6-portable-utils/deps-exe/s6-touch
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-touch
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-true b/src/s6-portable-utils/deps-exe/s6-true
new file mode 100644
index 0000000..e69de29
diff --git a/src/s6-portable-utils/deps-exe/s6-uniquename b/src/s6-portable-utils/deps-exe/s6-uniquename
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-uniquename
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-unquote b/src/s6-portable-utils/deps-exe/s6-unquote
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-unquote
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-unquote-filter b/src/s6-portable-utils/deps-exe/s6-unquote-filter
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-unquote-filter
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/s6-update-symlinks b/src/s6-portable-utils/deps-exe/s6-update-symlinks
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/s6-update-symlinks
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/deps-exe/seekablepipe b/src/s6-portable-utils/deps-exe/seekablepipe
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/s6-portable-utils/deps-exe/seekablepipe
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/s6-portable-utils/s6-basename.c b/src/s6-portable-utils/s6-basename.c
new file mode 100644
index 0000000..9e00763
--- /dev/null
+++ b/src/s6-portable-utils/s6-basename.c
@@ -0,0 +1,46 @@
+/* ISC license. */
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-basename [ -n ] file [ suffix ]"
+
+int main (int argc, char const *const *argv)
+{
+ stralloc sa = STRALLOC_ZERO ;
+ int nl = 1 ;
+ PROG = "s6-basename" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "n", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'n' : nl = 0 ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (!argc) strerr_dieusage(100, USAGE) ;
+ if (!sabasename(&sa, argv[0], strlen(argv[0])))
+ strerr_diefu2sys(111, "get basename of ", argv[0]) ;
+ if (argc >= 2)
+ {
+ size_t n = strlen(argv[1]) ;
+ if ((n < sa.len) && !strncmp(argv[1], sa.s + sa.len - n, n))
+ sa.len -= n ;
+ }
+ if (nl && !stralloc_catb(&sa, "\n", 1))
+ strerr_diefu2sys(111, "get basename of ", argv[0]) ;
+ if (allwrite(1, sa.s, sa.len) < sa.len)
+ strerr_diefu1sys(111, "write to stdout") ;
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-cat.c b/src/s6-portable-utils/s6-cat.c
new file mode 100644
index 0000000..8ff5a47
--- /dev/null
+++ b/src/s6-portable-utils/s6-cat.c
@@ -0,0 +1,11 @@
+/* ISC license. */
+
+#include
+#include
+
+int main (void)
+{
+ PROG = "s6-cat" ;
+ if (fd_cat(0, 1) < 0) strerr_diefu1sys(111, "fd_cat") ;
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-chmod.c b/src/s6-portable-utils/s6-chmod.c
new file mode 100644
index 0000000..946a318
--- /dev/null
+++ b/src/s6-portable-utils/s6-chmod.c
@@ -0,0 +1,34 @@
+/* ISC license. */
+
+#include
+
+#include
+#include
+
+#define USAGE "s6-chmod mode file"
+
+int main (int argc, char const *const *argv)
+{
+ mode_t mode = 0 ;
+ unsigned int m ;
+ PROG = "s6-chmod" ;
+ if (argc < 3) strerr_dieusage(100, USAGE) ;
+ if (!uint0_oscan(argv[1], &m)) strerr_dieusage(100, USAGE) ;
+
+ if (m & 0001) mode |= S_IXOTH ;
+ if (m & 0002) mode |= S_IWOTH ;
+ if (m & 0004) mode |= S_IROTH ;
+ if (m & 0010) mode |= S_IXGRP ;
+ if (m & 0020) mode |= S_IWGRP ;
+ if (m & 0040) mode |= S_IRGRP ;
+ if (m & 0100) mode |= S_IXUSR ;
+ if (m & 0200) mode |= S_IWUSR ;
+ if (m & 0400) mode |= S_IRUSR ;
+ if (m & 01000) mode |= S_ISVTX ;
+ if (m & 02000) mode |= S_ISGID ;
+ if (m & 04000) mode |= S_ISUID ;
+
+ if (chmod(argv[2], mode) == -1)
+ strerr_diefu2sys(111, "change mode of ", argv[2]) ;
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-chown.c b/src/s6-portable-utils/s6-chown.c
new file mode 100644
index 0000000..77cd94b
--- /dev/null
+++ b/src/s6-portable-utils/s6-chown.c
@@ -0,0 +1,55 @@
+/* ISC license. */
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-chown [ -U ] [ -u uid ] [ -g gid ] file"
+
+int main (int argc, char const *const *argv)
+{
+ uid_t uid = -1 ;
+ gid_t gid = -1 ;
+ PROG = "s6-chown" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "Uu:g:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'u':
+ {
+ if (!uid0_scan(l.arg, &uid)) strerr_dieusage(100, USAGE) ;
+ break ;
+ }
+ case 'g':
+ {
+ if (!gid0_scan(l.arg, &gid)) strerr_dieusage(100, USAGE) ;
+ break ;
+ }
+ case 'U':
+ {
+ char const *s = getenv("UID") ;
+ if (!s) strerr_dienotset(100, "UID") ;
+ if (!uid0_scan(s, &uid)) strerr_dieinvalid(100, "UID") ;
+ s = getenv("GID") ;
+ if (!s) strerr_dienotset(100, "GID") ;
+ if (!gid0_scan(s, &gid)) strerr_dieinvalid(100, "GID") ;
+ break ;
+ }
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (!argc) strerr_dieusage(100, USAGE) ;
+ if (chown(*argv, uid, gid) == -1)
+ strerr_diefu2sys(111, "chown ", argv[0]) ;
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-clock.c b/src/s6-portable-utils/s6-clock.c
new file mode 100644
index 0000000..5a9e67a
--- /dev/null
+++ b/src/s6-portable-utils/s6-clock.c
@@ -0,0 +1,31 @@
+/* ISC license. */
+
+#include
+#include
+#include
+
+#define USAGE "s6-clock [ tai64nlabel ]"
+
+static int s6clock_getit (void)
+{
+ char fmt[TIMESTAMP+1] ;
+ timestamp(fmt) ;
+ fmt[TIMESTAMP] = '\n' ;
+ if (allwrite(1, fmt, TIMESTAMP+1) < TIMESTAMP+1)
+ strerr_diefu1sys(111, "write to stdout") ;
+ return 0 ;
+}
+
+static int s6clock_setit (char const *h)
+{
+ tain a ;
+ if (!timestamp_scan(h, &a)) strerr_dieusage(100, USAGE) ;
+ if (!tain_setnow(&a)) strerr_diefu1sys(111, "taia_setnow") ;
+ return 0 ;
+}
+
+int main (int argc, char const *const *argv)
+{
+ PROG = "s6-clock" ;
+ return (argc < 2) ? s6clock_getit() : s6clock_setit(argv[1]) ;
+}
diff --git a/src/s6-portable-utils/s6-cut.c b/src/s6-portable-utils/s6-cut.c
new file mode 100644
index 0000000..e55907b
--- /dev/null
+++ b/src/s6-portable-utils/s6-cut.c
@@ -0,0 +1,212 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-cut [ -b list | -c list | -f list ] [ -d delim ] [ -n ] [ -s ] [ file... ]"
+
+static int disize_cmpleft (void const *a, void const *b)
+{
+ return ((disize const *)a)->left - ((disize const *)b)->left ;
+}
+
+static void disizealloc_normalize (genalloc *list)
+{
+ size_t i = 1, cur = 0 ;
+ size_t len = genalloc_len(disize, list) ;
+ disize *const s = genalloc_s(disize, list) ;
+ qsort(s, len, sizeof(disize), &disize_cmpleft) ;
+ for (; i < len ; i++)
+ if (!s[cur].right) break ;
+ else if (s[i].left > s[cur].right) s[++cur] = s[i] ;
+ else if (s[cur].right < s[i].right)
+ s[cur].right = s[i].right ;
+ genalloc_setlen(disize, list, cur+1) ;
+}
+
+static void s6cut_scanlist (genalloc *list, char const *s)
+{
+ size_t i = 0 ;
+ genalloc_setlen(disize, list, 0) ;
+ while (s[i])
+ {
+ char const sep[4] = ", \t" ;
+ disize iv ;
+ if (s[i] == '-') iv.left = 1 ;
+ else
+ {
+ size_t j = size_scan(s+i, &iv.left) ;
+ if (!j || !iv.left) strerr_dief2x(100, "invalid list argument: ", s) ;
+ i += j ;
+ }
+ if (s[i] != '-') iv.right = iv.left ;
+ else
+ {
+ size_t j = size_scan(s + ++i, &iv.right) ;
+ if (!j) iv.right = 0 ;
+ else if (iv.right < iv.left)
+ strerr_dief2x(100, "invalid list argument: ", s) ;
+ else i += j ;
+ }
+ switch (byte_chr(sep, 4, s[i]))
+ {
+ case 0 :
+ case 1 :
+ case 2 : i++ ;
+ case 3 : break ;
+ case 4 :
+ strerr_dief2x(100, "invalid list argument: ", s) ;
+ }
+ if (!genalloc_append(disize, list, &iv))
+ strerr_diefu1sys(111, "build interval list") ;
+ }
+}
+
+static int s6cut_doit (int fd, disize const *s, size_t len, unsigned int flags, char delim)
+{
+ char buf[BUFFER_INSIZE] ;
+ buffer b = BUFFER_INIT(&buffer_flush1read, fd, buf, BUFFER_INSIZE) ;
+ for (;;)
+ {
+ int r ;
+ satmp.len = 0 ;
+ r = skagetln(&b, &satmp, '\n') ;
+ if ((r == -1) && (errno != EPIPE)) return 0 ;
+ if (!r) break ;
+ if (flags & 2)
+ {
+ size_t i = 0 ;
+ for (; i < len ; i++)
+ {
+ size_t j = s[i].right ;
+ if (s[i].left >= satmp.len) break ;
+ if (!j || (j > satmp.len))
+ {
+ j = satmp.len ;
+ r = 0 ;
+ }
+ if (buffer_put(buffer_1, satmp.s + s[i].left - 1, j + 1 - s[i].left) == -1)
+ return 0 ;
+ }
+ }
+ else
+ {
+ size_t i = 0, j = 0, count = 1 ;
+ for (; i < len ; i++)
+ {
+ for (; count < s[i].left ; count++)
+ {
+ j += byte_chr(satmp.s + j, satmp.len - j, delim) ;
+ if (j == satmp.len) break ;
+ j++ ;
+ }
+ if (j == satmp.len)
+ {
+ if (count == 1)
+ {
+ if ((flags & 1) && (buffer_put(buffer_1, satmp.s, satmp.len) < 0))
+ return 0 ;
+ r = 0 ;
+ }
+ break ;
+ }
+ for (; !s[i].right || (count <= s[i].right) ; count++)
+ {
+ size_t k = byte_chr(satmp.s + j, satmp.len - j, delim) ;
+ if ((count > s[0].left) && (buffer_put(buffer_1, &delim, 1) < 0)) return 0 ;
+ if (buffer_put(buffer_1, satmp.s + j, k) < 0) return 0 ;
+ j += k ;
+ if (j == satmp.len)
+ {
+ r = 0 ;
+ break ;
+ }
+ j++ ;
+ }
+ if (j == satmp.len) break ;
+ }
+ }
+ if ((r > 0) && (buffer_put(buffer_1, "\n", 1) < 0)) return 0 ;
+ }
+ return 1 ;
+}
+
+int main (int argc, char const *const *argv)
+{
+ genalloc list = GENALLOC_ZERO ; /* array of disize */
+ char delim = '\t' ;
+ unsigned int what = 0 ;
+ PROG = "s6-cut" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ int flagnodel = 1 ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "nsb:c:f:d:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'n': break ; /* ignored */
+ case 's': flagnodel = 0 ; break ;
+ case 'd': delim = *l.arg ; break ;
+ case 'b':
+ case 'c':
+ {
+ if (what) strerr_dieusage(100, USAGE) ;
+ what = 2 ;
+ s6cut_scanlist(&list, l.arg) ;
+ break ;
+ }
+ case 'f':
+ {
+ if (what) strerr_dieusage(100, USAGE) ;
+ what = 4 ;
+ s6cut_scanlist(&list, l.arg) ;
+ break ;
+ }
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ what += flagnodel ;
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (!genalloc_len(disize, &list)) strerr_dieusage(100, USAGE) ;
+ disizealloc_normalize(&list) ;
+
+ if (!argc)
+ {
+ if (!s6cut_doit(0, genalloc_s(disize, &list), genalloc_len(disize, &list), what, delim))
+ strerr_diefu1sys(111, "cut stdin") ;
+ }
+ else
+ {
+ for (; *argv ; argv++)
+ {
+ if ((argv[0][0] == '-') && !argv[0][1])
+ {
+ if (!s6cut_doit(0, genalloc_s(disize, &list), genalloc_len(disize, &list), what, delim))
+ strerr_diefu1sys(111, "process stdin") ;
+ }
+ else
+ {
+ int fd = open_readb(*argv) ;
+ if (fd == -1)
+ strerr_diefu3sys(111, "open ", *argv, " for reading") ;
+ if (!s6cut_doit(fd, genalloc_s(disize, &list), genalloc_len(disize, &list), what, delim))
+ strerr_diefu2sys(111, "cut ", *argv) ;
+ fd_close(fd) ;
+ }
+ }
+ }
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-dirname.c b/src/s6-portable-utils/s6-dirname.c
new file mode 100644
index 0000000..83782ac
--- /dev/null
+++ b/src/s6-portable-utils/s6-dirname.c
@@ -0,0 +1,41 @@
+/* ISC license. */
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-dirname [ -n ] file"
+
+int main (int argc, char const *const *argv)
+{
+ stralloc sa = STRALLOC_ZERO ;
+ int nl = 1 ;
+ PROG = "s6-dirname" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "n", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'n' : nl = 0 ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+
+ if (!argc) strerr_dieusage(100, USAGE) ;
+ if (!sadirname(&sa, argv[0], strlen(argv[0])))
+ strerr_diefu2sys(111, "get dirname of ", argv[0]) ;
+ if (nl && !stralloc_catb(&sa, "\n", 1))
+ strerr_diefu2sys(111, "get dirname of ", argv[0]) ;
+ if (allwrite(1, sa.s, sa.len) < sa.len)
+ strerr_diefu1sys(111, "write to stdout") ;
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-dumpenv.c b/src/s6-portable-utils/s6-dumpenv.c
new file mode 100644
index 0000000..4b79170
--- /dev/null
+++ b/src/s6-portable-utils/s6-dumpenv.c
@@ -0,0 +1,72 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-dumpenv [ -N | -n ] [ -m mode ] envdir"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv, char const *const *envp)
+{
+ unsigned int mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH ;
+ int chomp = 0 ;
+ size_t dirlen ;
+ PROG = "s6-dumpenv" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "nNm:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'n' : chomp = 0 ; break ;
+ case 'N' : chomp = 1 ; break ;
+ case 'm' : if (!uint0_oscan(l.arg, &mode)) dieusage() ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (!argc) dieusage() ;
+
+ if (mkdir(argv[0], mode) < 0)
+ {
+ struct stat st ;
+ if (errno != EEXIST) strerr_diefu2sys(111, "mkdir ", argv[0]) ;
+ if (stat(argv[0], &st) < 0)
+ strerr_diefu2sys(111, "stat ", argv[0]) ;
+ if (!S_ISDIR(st.st_mode))
+ {
+ errno = ENOTDIR ;
+ strerr_diefu2sys(111, "mkdir ", argv[0]) ;
+ }
+ }
+ dirlen = strlen(argv[0]) ;
+
+ for (; *envp ; envp++)
+ {
+ size_t varlen = str_chr(*envp, '=') ;
+ struct iovec const v[2] =
+ {
+ { .iov_base = (char *)*envp + varlen + 1, .iov_len = strlen(*envp + varlen + 1) },
+ { .iov_base = "\n", .iov_len = 1 }
+ } ;
+ char fn[dirlen + varlen + 2] ;
+ memcpy(fn, argv[0], dirlen) ;
+ fn[dirlen] = '/' ;
+ memcpy(fn + dirlen + 1, *envp, varlen) ;
+ fn[dirlen + 1 + varlen] = 0 ;
+ if (!openwritevnclose_suffix(fn, v, 1 + chomp, "=.tmp"))
+ strerr_diefu2sys(111, "open ", fn) ;
+ }
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-echo.c b/src/s6-portable-utils/s6-echo.c
new file mode 100644
index 0000000..11427d2
--- /dev/null
+++ b/src/s6-portable-utils/s6-echo.c
@@ -0,0 +1,38 @@
+/* ISC license. */
+
+#include
+#include
+#include
+
+#define USAGE "s6-echo [ -n ] [ -s sep ] args..."
+
+int main (int argc, char const *const *argv)
+{
+ char sep = ' ' ;
+ char donl = 1 ;
+ PROG = "s6-echo" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "ns:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'n': donl = 0 ; break ;
+ case 's': sep = *l.arg ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ for ( ; *argv ; argv++)
+ if ((buffer_puts(buffer_1small, *argv) < 0)
+ || (argv[1] && (buffer_put(buffer_1small, &sep, 1) < 0)))
+ goto err ;
+ if (donl && (buffer_put(buffer_1small, "\n", 1) < 0)) goto err ;
+ if (!buffer_flush(buffer_1small)) goto err ;
+ return 0 ;
+err:
+ strerr_diefu1sys(111, "write to stdout") ;
+}
diff --git a/src/s6-portable-utils/s6-env.c b/src/s6-portable-utils/s6-env.c
new file mode 100644
index 0000000..01479ce
--- /dev/null
+++ b/src/s6-portable-utils/s6-env.c
@@ -0,0 +1,43 @@
+/* ISC license. */
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+
+#define USAGE "s6-env [ -i ] [ name=value... ] prog..."
+
+int main (int argc, char const *const *argv, char const *const *envp)
+{
+ stralloc modifs = STRALLOC_ZERO ;
+ char const *arg_zero[2] = { S6_PORTABLE_UTILS_BINPREFIX "s6-printenv", 0 } ;
+ char const *env_zero[1] = { 0 } ;
+ PROG = "s6-env" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "i", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'i': envp = env_zero ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ for (; argc ; argc--, argv++)
+ {
+ if (!strchr(*argv, '=')) break ;
+ if (!stralloc_cats(&modifs, *argv) || !stralloc_0(&modifs))
+ strerr_diefu1sys(111, "stralloc_cats") ;
+ }
+ if (!argc) argv = arg_zero ;
+ xmexec_em(argv, envp, modifs.s, modifs.len) ;
+}
diff --git a/src/s6-portable-utils/s6-expr.c b/src/s6-portable-utils/s6-expr.c
new file mode 100644
index 0000000..91be041
--- /dev/null
+++ b/src/s6-portable-utils/s6-expr.c
@@ -0,0 +1,205 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-expr arithmetic expression"
+#define bail() strerr_dief1x(2, "invalid expression")
+
+enum expr_opnum_e
+{
+ T_DATA,
+ T_AND,
+ T_OR,
+ T_LEFTP,
+ T_RIGHTP,
+ T_EQUAL,
+ T_NEQUAL,
+ T_GREATER,
+ T_GREATERE,
+ T_LESSER,
+ T_LESSERE,
+ T_PLUS,
+ T_MINUS,
+ T_TIMES,
+ T_DIV,
+ T_MOD
+} ;
+
+struct expr_token_s
+{
+ char const *string ;
+ enum expr_opnum_e op ;
+ unsigned int type ;
+} ;
+
+struct expr_node_s
+{
+ enum expr_opnum_e op ;
+ unsigned int type ;
+ unsigned int arg1 ;
+ unsigned int arg2 ;
+ long data ;
+} ;
+
+static unsigned int expr_lex (struct expr_node_s *tree, char const *const *argv)
+{
+ static struct expr_token_s const tokens[16] =
+ {
+ { "+", T_PLUS, 3 },
+ { "-", T_MINUS, 3 },
+ { "*", T_TIMES, 2 },
+ { "/", T_DIV, 2 },
+ { "%", T_MOD, 2 },
+ { "(", T_LEFTP, 7 },
+ { ")", T_RIGHTP, 8 },
+ { "=", T_EQUAL, 4 },
+ { "!=", T_NEQUAL, 4 },
+ { "<", T_LESSER, 4 },
+ { "<=", T_LESSERE, 4 },
+ { ">", T_GREATER, 4 },
+ { ">=", T_GREATERE, 4 },
+ { "|", T_OR, 6 },
+ { "&", T_AND, 5 },
+ { 0, 0, 0 }
+ } ;
+ unsigned int pos = 0 ;
+
+ for (; argv[pos] ; pos++)
+ {
+ unsigned int i = 0 ;
+ for (i = 0 ; tokens[i].string ; i++)
+ if (!strcmp(argv[pos], tokens[i].string))
+ {
+ tree[pos].op = tokens[i].op ;
+ tree[pos].type = tokens[i].type ;
+ break ;
+ }
+ if (!tokens[i].string)
+ {
+ tree[pos].op = T_DATA ;
+ tree[pos].type = 0 ;
+ if (!long_scan(argv[pos], &tree[pos].data)) bail() ;
+ }
+ }
+ return pos ;
+}
+
+static void expr_reduce (struct expr_node_s *tree, unsigned int *stack, unsigned int *sp, unsigned int type)
+{
+ if (tree[stack[*sp-1]].type == type)
+ {
+ tree[stack[*sp-1]].arg1 = stack[*sp-2] ;
+ tree[stack[*sp-1]].arg2 = stack[*sp] ;
+ stack[*sp-2] = stack[*sp-1] ;
+ *sp -= 2 ;
+ }
+ tree[stack[*sp]].type = type + 7 ;
+}
+
+static unsigned int expr_parse (struct expr_node_s *tree, unsigned int n)
+{
+ static char const table[9][15] =
+ {
+ "xsssssssxzzzzzz",
+ "xxxxxxxx!zzzzzz",
+ "mxxxxxxxMszzzzz",
+ "mxxxxxxxMaszzzz",
+ "mxxxxxxxMacszzz",
+ "mxxxxxxxMacAszz",
+ "mxxxxxxxMacAOsz",
+ "xsssssssxzzzzzz",
+ "mxxxxxxxMacAOEs"
+ } ;
+ unsigned int stack[n] ;
+ unsigned int sp = 0, pos = 0 ;
+ char cont = 1 ;
+ stack[0] = n + 1 ;
+ tree[n].type = 8 ; /* add ) for the final reduce */
+ tree[n+1].type = 1 ; /* add EOF */
+ while (cont)
+ {
+ switch (table[tree[pos].type][tree[stack[sp]].type])
+ {
+ case 'x' : bail() ;
+ case '!' : cont = 0 ; break ;
+ case 's' : stack[++sp] = pos++ ; break ;
+ case 'M' :
+ if (tree[stack[sp-2]].type != 7) bail() ;
+ stack[sp-2] = stack[sp-1] ;
+ sp -= 2 ;
+ case 'm' : expr_reduce(tree, stack, &sp, 2) ; break ;
+ case 'a' : expr_reduce(tree, stack, &sp, 3) ; break ;
+ case 'c' : expr_reduce(tree, stack, &sp, 4) ; break ;
+ case 'A' : expr_reduce(tree, stack, &sp, 5) ; break ;
+ case 'O' : expr_reduce(tree, stack, &sp, 6) ; break ;
+ case 'E' : tree[stack[sp]].type = 14 ; break ;
+ case 'z' :
+ default : strerr_dief1x(101, "internal error in parse, please submit a bug-report.") ; /* can't happen */
+ }
+ }
+ if (sp != 2) bail() ;
+ return stack[1] ;
+}
+
+static long expr_run (struct expr_node_s const *tree, unsigned int root)
+{
+ switch (tree[root].op)
+ {
+ case T_DATA :
+ return tree[root].data ;
+ case T_OR :
+ {
+ long r = expr_run(tree, tree[root].arg1) ;
+ return r ? r : expr_run(tree, tree[root].arg2) ;
+ }
+ case T_AND :
+ {
+ long r = expr_run(tree, tree[root].arg1) ;
+ return r ? expr_run(tree, tree[root].arg2) ? r : 0 : 0 ;
+ }
+ case T_EQUAL :
+ return expr_run(tree, tree[root].arg1) == expr_run(tree, tree[root].arg2) ;
+ case T_NEQUAL :
+ return expr_run(tree, tree[root].arg1) != expr_run(tree, tree[root].arg2) ;
+ case T_GREATER :
+ return expr_run(tree, tree[root].arg1) > expr_run(tree, tree[root].arg2) ;
+ case T_GREATERE :
+ return expr_run(tree, tree[root].arg1) >= expr_run(tree, tree[root].arg2) ;
+ case T_LESSER :
+ return expr_run(tree, tree[root].arg1) < expr_run(tree, tree[root].arg2) ;
+ case T_LESSERE :
+ return expr_run(tree, tree[root].arg1) <= expr_run(tree, tree[root].arg2) ;
+ case T_PLUS :
+ return expr_run(tree, tree[root].arg1) + expr_run(tree, tree[root].arg2) ;
+ case T_MINUS :
+ return expr_run(tree, tree[root].arg1) - expr_run(tree, tree[root].arg2) ;
+ case T_TIMES :
+ return expr_run(tree, tree[root].arg1) * expr_run(tree, tree[root].arg2) ;
+ case T_DIV :
+ return expr_run(tree, tree[root].arg1) / expr_run(tree, tree[root].arg2) ;
+ case T_MOD :
+ return expr_run(tree, tree[root].arg1) % expr_run(tree, tree[root].arg2) ;
+ default : strerr_dief1x(101, "internal error in expr_run, please submit a bug-report") ;
+ }
+}
+
+int main (int argc, char const *const *argv)
+{
+ char fmt[LONG_FMT] ;
+ long val ;
+ size_t len ;
+ PROG = "s6-expr" ;
+ if (argc <= 1) return 2 ;
+ {
+ struct expr_node_s tree[argc + 1] ;
+ val = expr_run(tree, expr_parse(tree, expr_lex(tree, argv+1))) ;
+ }
+ len = long_fmt(fmt, val) ;
+ fmt[len++] = '\n' ;
+ if (allwrite(1, fmt, len) < len)
+ strerr_diefu1sys(111, "write to stdout") ;
+ return !val ;
+}
diff --git a/src/s6-portable-utils/s6-false.c b/src/s6-portable-utils/s6-false.c
new file mode 100644
index 0000000..75f483e
--- /dev/null
+++ b/src/s6-portable-utils/s6-false.c
@@ -0,0 +1,8 @@
+/* ISC license. */
+
+#include
+
+int main (void)
+{
+ _exit(1) ;
+}
diff --git a/src/s6-portable-utils/s6-format-filter.c b/src/s6-portable-utils/s6-format-filter.c
new file mode 100644
index 0000000..57b2869
--- /dev/null
+++ b/src/s6-portable-utils/s6-format-filter.c
@@ -0,0 +1,62 @@
+/* ISC license. */
+
+#include
+
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-format-filter format [ args... ]"
+
+int main (int argc, char const *const *argv)
+{
+ stralloc src = STRALLOC_ZERO ;
+ stralloc dst = STRALLOC_ZERO ;
+ char vars[12] = "s0123456789" ;
+ char const *args[12] = { "" } ;
+ char const *format ;
+ PROG = "s6-format-filter" ;
+ argc-- ; args[1] = *argv++ ;
+ if (!argc--) strerr_dieusage(100, USAGE) ;
+ format = *argv++ ;
+ if (argc > 9) argc = 9 ;
+ vars[argc+2] = 0 ;
+ {
+ unsigned int i = 0 ;
+ for (; i < (unsigned int)argc ; i++) args[2+i] = argv[i] ;
+ }
+ if (!string_format(&dst, vars, format, args))
+ strerr_diefu1sys(111, "compile format") ;
+
+ for (;;)
+ {
+ int r ;
+ src.len = 0 ;
+ dst.len = 0 ;
+ r = skagetln(buffer_0f1, &src, '\n') ;
+ if (!r) break ;
+ else if (r < 0)
+ {
+ if ((errno != EPIPE) || !stralloc_0(&src))
+ strerr_diefu1sys(111, "read from stdin") ;
+ }
+ else src.s[src.len-1] = 0 ;
+ args[0] = src.s ;
+ if (!string_format(&dst, vars, format, args))
+ {
+ int e = errno ;
+ buffer_flush(buffer_1) ;
+ errno = e ;
+ strerr_diefu1sys(111, "format") ;
+ }
+ if (r > 0)
+ {
+ if (!stralloc_catb(&dst, "\n", 1))
+ strerr_diefu1sys(111, "format") ;
+ }
+ if (buffer_put(buffer_1, dst.s, dst.len) < 0)
+ strerr_diefu1sys(111, "write to stdout") ;
+ }
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-grep.c b/src/s6-portable-utils/s6-grep.c
new file mode 100644
index 0000000..ebfa064
--- /dev/null
+++ b/src/s6-portable-utils/s6-grep.c
@@ -0,0 +1,139 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-grep [ -E | -F ] [ -i ] [ -c ] [ -n ] [ -q ] [ -v ] pattern"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+typedef struct grep_flags_s grep_flags_t, *grep_flags_t_ref ;
+struct grep_flags_s
+{
+ unsigned int extended : 1 ;
+ unsigned int ignorecase: 1 ;
+ unsigned int fixed : 1 ;
+ unsigned int count : 1 ;
+ unsigned int num : 1 ;
+ unsigned int quiet : 1 ;
+ unsigned int not : 1 ;
+} ;
+#define GREP_FLAGS_ZERO { .extended = 0, .ignorecase = 0, .fixed = 0, .count = 0, .num = 0, .quiet = 0, .not = 0 }
+
+static void grep_xout (char const *s, size_t len)
+{
+ if (buffer_put(buffer_1, s, len) < 0)
+ strerr_diefu1sys(111, "write to stdout") ;
+}
+
+int main (int argc, char const *const *argv)
+{
+ unsigned int count = 0 ;
+ grep_flags_t flags = GREP_FLAGS_ZERO ;
+ PROG = "s6-grep" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "EFicnqv", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'E': flags.extended = 1 ; break ;
+ case 'F': flags.fixed = 1 ; break ;
+ case 'i': flags.ignorecase = 1 ; break ;
+ case 'c': flags.count = 1 ; break ;
+ case 'n': flags.num = 1 ; break ;
+ case 'q': flags.quiet = 1 ; break ;
+ case 'v': flags.not = 1 ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (!argc) dieusage() ;
+ {
+ stralloc line = STRALLOC_ZERO ;
+ regex_t re ;
+ unsigned int num = 0 ;
+ size_t arglen = strlen(argv[0]) ;
+ if (!flags.fixed)
+ {
+ int e = skalibs_regcomp(&re, argv[0], REG_NOSUB | (flags.extended ? REG_EXTENDED : 0) | (flags.ignorecase ? REG_ICASE : 0)) ;
+ if (e)
+ {
+ char buf[256] ;
+ regerror(e, &re, buf, 256) ;
+ strerr_diefu2x(111, "compile regular expression: ", buf) ;
+ }
+ }
+
+ for (;;)
+ {
+ int r ;
+ line.len = 0 ;
+ r = skagetln(buffer_0f1, &line, '\n') ;
+ if (!r) break ;
+ if (r < 0)
+ {
+ if ((errno != EPIPE) || !stralloc_catb(&line, "\n", 1))
+ strerr_diefu1sys(111, "read from stdin") ;
+ }
+ num++ ; line.s[line.len-1] = 0 ;
+ if (flags.fixed)
+ {
+ if (flags.ignorecase)
+ r = case_str(line.s, argv[0]) >= arglen ;
+ else
+ r = !strstr(line.s, argv[0]) ;
+ }
+ else
+ {
+ r = regexec(&re, line.s, 0, 0, 0) ;
+ if (r && r != REG_NOMATCH)
+ {
+ char buf[256] ;
+ regerror(r, &re, buf, 256) ;
+ strerr_diefu2x(111, "match regular expression: ", buf) ;
+ }
+ }
+ line.s[line.len-1] = '\n' ;
+ if (!r ^ flags.not)
+ {
+ count++ ;
+ if (!flags.quiet && !flags.count)
+ {
+ if (flags.num)
+ {
+ char fmt[UINT_FMT] ;
+ size_t n = uint_fmt(fmt, num) ;
+ fmt[n++] = ':' ;
+ grep_xout(fmt, n) ;
+ }
+ grep_xout(line.s, line.len) ;
+ }
+ }
+ }
+ if (flags.quiet) return !count ;
+ stralloc_free(&line) ;
+ if (!flags.fixed) regfree(&re) ;
+ }
+ if (flags.count)
+ {
+ char fmt[UINT_FMT] ;
+ size_t n = uint_fmt(fmt, count) ;
+ fmt[n++] = '\n' ;
+ grep_xout(fmt, n) ;
+ }
+ return !count ;
+}
diff --git a/src/s6-portable-utils/s6-head.c b/src/s6-portable-utils/s6-head.c
new file mode 100644
index 0000000..de7d937
--- /dev/null
+++ b/src/s6-portable-utils/s6-head.c
@@ -0,0 +1,164 @@
+/* ISC license. */
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-head [ -S ] [ -1..9 | -n lines | -c chars ] [ file... ]"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+typedef int head_func (int, size_t) ;
+typedef head_func *head_func_ref ;
+
+static int head_dolines (int fd, size_t lines)
+{
+ char buf[BUFFER_INSIZE] ;
+ buffer in = BUFFER_INIT(&buffer_read, fd, buf, BUFFER_INSIZE) ;
+ buffer out = BUFFER_INIT(&buffer_write, 1, buf, BUFFER_INSIZE) ;
+ struct iovec v[2] ;
+ while (lines)
+ {
+ size_t w = 0 ;
+ ssize_t r = buffer_fill(&in) ;
+ if (r <= 0) return !r ;
+ out.c.n = in.c.n ; out.c.p = in.c.p ;
+ buffer_rpeek(&in, v) ;
+ for (;;)
+ {
+ size_t n = siovec_len(v, 2) ;
+ size_t i ;
+ if (!n) break ;
+ i = siovec_bytechr(v, 2, '\n') ;
+ if (i < n)
+ {
+ w += i+1 ;
+ siovec_seek(v, 2, i+1) ;
+ if (!--lines)
+ {
+ out.c.n = (out.c.p + w) % out.c.a ;
+ break ;
+ }
+ }
+ else siovec_seek(v, 2, i) ;
+ }
+ if (!buffer_flush(&out)) return 0 ;
+ in.c.n = out.c.n ; in.c.p = out.c.p ;
+ }
+ return 1 ;
+}
+
+static int head_safedolines (int fd, size_t lines)
+{
+ char tmp[lines] ;
+ while (lines)
+ {
+ size_t r ;
+ errno = 0 ;
+ r = allread(fd, tmp, lines) ;
+ if (r < lines && errno) return 0 ;
+ lines -= byte_count(tmp, r, '\n') ;
+ if (buffer_put(buffer_1, tmp, r) < (ssize_t)r) return 0 ;
+ }
+ if (!buffer_flush(buffer_1)) return 0 ;
+ return 1 ;
+}
+
+static int head_safedochars (int fd, size_t chars)
+{
+ return (fd_catn(fd, 1, chars) >= chars) ;
+}
+
+int main (int argc, char const *const *argv)
+{
+ head_func_ref f ;
+ unsigned int lines = 10 ;
+ int islines = 1, safe = 0 ;
+ PROG = "s6-head" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ int done = 0 ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "S123456789n:c:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'S' : safe = 1 ; break ;
+ case '1' :
+ case '2' :
+ case '3' :
+ case '4' :
+ case '5' :
+ case '6' :
+ case '7' :
+ case '8' :
+ case '9' :
+ {
+ if (done) dieusage() ;
+ islines = 1 ;
+ lines = opt - '0' ;
+ done = 1 ;
+ break ;
+ }
+ case 'n' :
+ {
+ if (done || !uint0_scan(l.arg, &lines))
+ strerr_dieusage(100, USAGE) ;
+ islines = 1 ;
+ done = 1 ;
+ break ;
+ }
+ case 'c' :
+ {
+ if (done || !uint0_scan(l.arg, &lines))
+ strerr_dieusage(100, USAGE) ;
+ islines = 0 ;
+ done = 1 ;
+ break ;
+ }
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (argc) safe = 0 ;
+ f = islines ? safe ? &head_safedolines : &head_dolines : &head_safedochars ;
+ if (!argc)
+ {
+ if (!(*f)(0, lines))
+ strerr_diefu1sys(111, "head stdin") ;
+ }
+ else
+ {
+ unsigned int i = 0 ;
+ for (; argv[i] ; i++)
+ {
+ int fd ;
+ if (argc >= 2)
+ {
+ if (i) buffer_putnoflush(buffer_1, "\n", 1) ;
+ buffer_putnoflush(buffer_1, "==> ", 4) ;
+ if ((buffer_puts(buffer_1, argv[i]) <= 0)
+ || (buffer_putflush(buffer_1, " <==\n", 5) < 0))
+ strerr_diefu1sys(111, "write to stdout") ;
+ }
+ if ((argv[i][0] == '-') && !argv[i][1]) fd = 0 ;
+ else fd = open_readb(argv[i]) ;
+ if (fd == -1)
+ strerr_diefu3sys(111, "open ", argv[i], " for reading") ;
+ if (!(*f)(fd, lines))
+ strerr_diefu2sys(111, "head ", argv[i]) ;
+ fd_close(fd) ;
+ }
+ }
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-hiercopy.c b/src/s6-portable-utils/s6-hiercopy.c
new file mode 100644
index 0000000..a57dd69
--- /dev/null
+++ b/src/s6-portable-utils/s6-hiercopy.c
@@ -0,0 +1,18 @@
+/* ISC license. */
+
+#include
+
+#include
+#include
+
+#define USAGE "s6-hiercopy src dst"
+
+int main (int argc, char const *const *argv)
+{
+ PROG = "s6-hiercopy" ;
+ if (argc < 3) strerr_dieusage(100, USAGE) ;
+ umask(0) ;
+ if (!hiercopy(argv[1], argv[2]))
+ strerr_diefu4sys(111, "copy hierarchy from ", argv[1], " to ", argv[2]) ;
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-linkname.c b/src/s6-portable-utils/s6-linkname.c
new file mode 100644
index 0000000..8471ac4
--- /dev/null
+++ b/src/s6-portable-utils/s6-linkname.c
@@ -0,0 +1,43 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-linkname [ -n ] [ -f ] link"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv)
+{
+ stralloc sa = STRALLOC_ZERO ;
+ int path = 0, nl = 1 ;
+ PROG = "s6-linkname" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "nf", &l) ;
+ if (opt == -1) break ;
+ switch(opt)
+ {
+ case 'n' : nl = 0 ; break ;
+ case 'f' : path = 1 ; break ;
+ default : dieusage() ;
+ }
+ }
+ argv += l.ind ; argc -= l.ind ;
+ }
+ if (!argc) dieusage() ;
+
+ if ((path ? sarealpath(&sa, *argv) : sareadlink(&sa, *argv)) < 0)
+ strerr_diefu2sys(111, "resolve ", *argv) ;
+
+ if ((buffer_put(buffer_1small, sa.s, sa.len) < 0)
+ || (nl && (buffer_put(buffer_1small, "\n", 1)) < 0)
+ || (!buffer_flush(buffer_1small)))
+ strerr_diefu1sys(111, "write to stdout") ;
+
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-ln.c b/src/s6-portable-utils/s6-ln.c
new file mode 100644
index 0000000..f0b0c5e
--- /dev/null
+++ b/src/s6-portable-utils/s6-ln.c
@@ -0,0 +1,151 @@
+/* ISC license. */
+
+#include
+
+#ifdef SKALIBS_HASLINKAT
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-ln [ -n ] [ -s ] [ -f ] [ -L ] [ -P ] src... dest"
+#define LN_SUFFIX ":s6-ln:XXXXXX"
+
+#ifdef SKALIBS_HASLINKAT
+
+static int linknoderef (char const *old, char const *new)
+{
+ return linkat(AT_FDCWD, old, AT_FDCWD, new, 0) ;
+}
+
+static int linkderef (char const *old, char const *new)
+{
+ return linkat(AT_FDCWD, old, AT_FDCWD, new, AT_SYMLINK_FOLLOW) ;
+}
+
+#else /* can't implement SUSv4, default to link */
+
+# define linknoderef link
+# define linkderef link
+
+#endif
+
+static int ln_doit (char const *old, char const *new, link_func_ref mylink, int force)
+{
+ if ((*mylink)(old, new) == -1)
+ {
+ if (!force || errno != EEXIST)
+ {
+ strerr_warnwu5sys("make a link", " from ", new, " to ", old) ;
+ return 1 ;
+ }
+ {
+ size_t newlen = strlen(new) ;
+ char fn[newlen + sizeof(LN_SUFFIX)] ;
+ memcpy(fn, new, newlen) ;
+ memcpy(fn + newlen, LN_SUFFIX, sizeof(LN_SUFFIX)) ;
+ if (mklinktemp(old, fn, mylink) == -1)
+ {
+ strerr_warnwu3sys("make a link", " to ", old) ;
+ return 1 ;
+ }
+ if (rename(fn, new) == -1)
+ {
+ unlink_void(fn) ;
+ strerr_warnwu2sys("atomically replace ", new) ;
+ return 1 ;
+ }
+ /* if old == new, rename() didn't remove fn */
+ unlink_void(fn) ;
+ }
+ }
+ return 0 ;
+}
+
+int main (int argc, char const *const *argv)
+{
+ link_func_ref mylink = &link ; /* default to system behaviour */
+ int force = 0 ;
+ int nodir = 0 ;
+ PROG = "s6-ln" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "nsfLP", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'n' : nodir = 1 ; break ;
+ case 's': mylink = &symlink ; break ;
+ case 'f': force = 1 ; break ;
+ case 'L': if (mylink != &symlink) mylink = &linkderef ; break ;
+ case 'P': if (mylink != &symlink) mylink = &linknoderef ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (argc < 2) strerr_dieusage(100, USAGE) ;
+ if (argc > 2)
+ {
+ stralloc sa = STRALLOC_ZERO ;
+ unsigned int i = 0 ;
+ int e = 0 ;
+ size_t base ;
+ if (!stralloc_cats(&sa, argv[argc-1]) || !stralloc_catb(&sa, "/", 1))
+ strerr_diefu1sys(111, "stralloc_cats") ;
+ base = sa.len ;
+ for (; i < (unsigned int)(argc-1) ; i++)
+ {
+ sa.len = base ;
+ if (!sabasename(&sa, argv[i], strlen(argv[i])))
+ {
+ strerr_warnwu1sys("sabasename") ;
+ e++ ;
+ continue ;
+ }
+ if (!stralloc_0(&sa))
+ {
+ strerr_warnwu1sys("stralloc_0") ;
+ e++ ;
+ continue ;
+ }
+ e += ln_doit(argv[i], sa.s, mylink, force) ;
+ }
+ return e ;
+ }
+
+ {
+ struct stat st ;
+ if (nodir ? lstat(argv[1], &st) : stat(argv[1], &st) < 0)
+ {
+ if (errno != ENOENT) strerr_diefu2sys(111, "stat ", argv[1]) ;
+ return ln_doit(argv[0], argv[1], mylink, force) ;
+ }
+ if (!S_ISDIR(st.st_mode))
+ return ln_doit(argv[0], argv[1], mylink, force) ;
+ }
+
+ {
+ stralloc sa = STRALLOC_ZERO ;
+ if (!stralloc_cats(&sa, argv[1])
+ || !stralloc_catb(&sa, "/", 1)
+ || !sabasename(&sa, argv[0], strlen(argv[0]))
+ || !stralloc_0(&sa))
+ strerr_diefu1sys(111, "stralloc_catb") ;
+ return ln_doit(argv[0], sa.s, mylink, force) ;
+ }
+}
diff --git a/src/s6-portable-utils/s6-ls.c b/src/s6-portable-utils/s6-ls.c
new file mode 100644
index 0000000..b426da7
--- /dev/null
+++ b/src/s6-portable-utils/s6-ls.c
@@ -0,0 +1,57 @@
+/* ISC license. */
+
+#include
+
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-ls [ -0 ] [ -a | -A ] [ -x exclude ] dir"
+
+int main (int argc, char const *const *argv)
+{
+ unsigned int all = 0 ;
+ char const *exclude = 0 ;
+ char delim = '\n' ;
+ PROG = "s6-ls" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "0aAx:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case '0': delim = '\0' ; break ;
+ case 'a': all = 1 ; break ;
+ case 'A': all = 2 ; break ;
+ case 'x': exclude = l.arg ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (!argc) strerr_dieusage(100, USAGE) ;
+ {
+ direntry *d ;
+ DIR *dir = opendir(*argv) ;
+ if (!dir)
+ strerr_diefu2sys(111, "open directory ", *argv) ;
+ while ((d = readdir(dir)))
+ {
+ if ((d->d_name[0] == '.') && (all < 2))
+ {
+ if (!all || !d->d_name[1] || ((d->d_name[1] == '.') && !d->d_name[2])) continue ;
+ }
+ if (exclude && !strcmp(exclude, d->d_name)) continue ;
+ if ((buffer_puts(buffer_1, d->d_name) < 0)
+ || (buffer_put(buffer_1, &delim, 1) < 0))
+ strerr_diefu1sys(111, "write to stdout") ;
+ }
+ dir_close(dir) ;
+ }
+ if (!buffer_flush(buffer_1))
+ strerr_diefu1sys(111, "write to stdout") ;
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-maximumtime.c b/src/s6-portable-utils/s6-maximumtime.c
new file mode 100644
index 0000000..4da7e89
--- /dev/null
+++ b/src/s6-portable-utils/s6-maximumtime.c
@@ -0,0 +1,98 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-maximumtime [ -0 | -a | -b | -i | -k | -q | -t | -x | -1 | -2 ] milliseconds prog..."
+
+int main (int argc, char const *const *argv, char const *const *envp)
+{
+ tain deadline ;
+ iopause_fd x[1] = { { .fd = -1, .events = IOPAUSE_READ, .revents = 0 } } ;
+ pid_t pid = 0 ;
+ int tosend = SIGTERM ;
+ unsigned int timeout ;
+ PROG = "s6-maximumtime" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "0abikqtx12", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case '0': tosend = 0 ; break ;
+ case 'a': tosend = SIGALRM ; break ;
+ case 'b': tosend = SIGABRT ; break ;
+ case 'i': tosend = SIGINT ; break ;
+ case 'k': tosend = SIGKILL ; break ;
+ case 'q': tosend = SIGQUIT ; break ;
+ case 't': tosend = SIGTERM ; break ;
+ case 'x': tosend = SIGXCPU ; break ;
+ case '1': tosend = SIGUSR1 ; break ;
+ case '2': tosend = SIGUSR2 ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+
+ if ((argc < 2) || !uint0_scan(argv[0], &timeout)) strerr_dieusage(100, USAGE) ;
+ if (timeout) tain_from_millisecs(&deadline, timeout) ;
+ else deadline = tain_infinite_relative ;
+
+ x[0].fd = selfpipe_init() ;
+ if (x[0].fd < 0) strerr_diefu1sys(111, "selfpipe_init") ;
+
+ if (selfpipe_trap(SIGCHLD) < 0) strerr_diefu1sys(111, "selfpipe_trap") ;
+
+ pid = child_spawn0(argv[1], argv+1, envp) ;
+ if (!pid) strerr_diefu2sys(111, "spawn ", argv[1]) ;
+ tain_now_set_stopwatch_g() ;
+ tain_add_g(&deadline, &deadline) ;
+
+ for (;;)
+ {
+ int r = iopause_g(x, 1, &deadline) ;
+ if (r < 0) strerr_diefu1sys(111, "iopause") ;
+ if (!r) break ;
+ if (x[0].revents & IOPAUSE_READ)
+ {
+ int cont = 1 ;
+ while (cont)
+ {
+ switch (selfpipe_read())
+ {
+ case -1 : strerr_diefu1sys(111, "selfpipe_read") ;
+ case 0 : cont = 0 ; break ;
+ case SIGCHLD :
+ {
+ int wstat ;
+ if (wait_pid_nohang(pid, &wstat) == pid)
+ {
+ if (WIFSIGNALED(wstat))
+ strerr_diew1x(111, "child process crashed") ;
+ else return WEXITSTATUS(wstat) ;
+ }
+ }
+ default : strerr_diefu1x(101, "internal error, please submit a bug-report.") ;
+ }
+ }
+ }
+ }
+ kill(pid, tosend) ;
+ errno = ETIMEDOUT ;
+ strerr_diewu1sys(99, "wait for child process") ;
+}
diff --git a/src/s6-portable-utils/s6-mkdir.c b/src/s6-portable-utils/s6-mkdir.c
new file mode 100644
index 0000000..8212813
--- /dev/null
+++ b/src/s6-portable-utils/s6-mkdir.c
@@ -0,0 +1,82 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-mkdir [ -p ] [ -v ] [ -m mode ] dir"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+static int mkdir_doit (char const *s, unsigned int mode, int verbose, int ee)
+{
+ if (mkdir(s, mode) == -1)
+ {
+ if (ee || (errno != EEXIST))
+ {
+ strerr_warnwu2sys("mkdir ", s) ;
+ return 111 ;
+ }
+ }
+ else if (verbose)
+ {
+ buffer_puts(buffer_2, PROG) ;
+ buffer_puts(buffer_2, ": created directory ") ;
+ buffer_puts(buffer_2, s) ;
+ buffer_putflush(buffer_2, "\n", 1) ;
+ }
+ return 0 ;
+}
+
+static int mkdir_doparents (char const *s, unsigned int mode, int verbose)
+{
+ size_t n = strlen(s), i = 0 ;
+ char tmp[n+1] ;
+ for (; i < n ; i++)
+ {
+ if ((s[i] == '/') && i)
+ {
+ int e ;
+ tmp[i] = 0 ;
+ e = mkdir_doit(tmp, mode, verbose, 0) ;
+ if (e) return e ;
+ }
+ tmp[i] = s[i] ;
+ }
+ return mkdir_doit(s, mode, verbose, 0) ;
+}
+
+int main (int argc, char const *const *argv)
+{
+ int parents = 0, verbose = 0 ;
+ unsigned int mode = 0777 ;
+ int e = 0 ;
+ int noumask = 0 ;
+ PROG = "s6-mkdir" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "pvm:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'p': parents = 1 ; break ;
+ case 'v': verbose = 1 ; break ;
+ case 'm': if (!uint_oscan(l.arg, &mode)) dieusage() ; noumask = 1 ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (noumask) umask(0) ;
+ for ( ; *argv ; argv++)
+ e |= parents ? mkdir_doparents(*argv, mode, verbose) :
+ mkdir_doit(*argv, mode, verbose, 1) ;
+ return e ;
+}
diff --git a/src/s6-portable-utils/s6-mkfifo.c b/src/s6-portable-utils/s6-mkfifo.c
new file mode 100644
index 0000000..37e84af
--- /dev/null
+++ b/src/s6-portable-utils/s6-mkfifo.c
@@ -0,0 +1,36 @@
+/* ISC license. */
+
+#include
+
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-mkfifo [ -m mode ] fifo..."
+
+int main (int argc, char const *const *argv)
+{
+ unsigned int mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH ;
+ PROG = "s6-mkfifo" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "m:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'm': if (uint0_oscan(l.arg, &mode)) break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (!argc) strerr_dieusage(100, USAGE) ;
+ umask(S_IXUSR|S_IXGRP|S_IXOTH) ;
+ for (; *argv ; argv++)
+ if (mkfifo(*argv, mode) < 0)
+ strerr_diefu2sys(111, "mkfifo ", *argv) ;
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-nice.c b/src/s6-portable-utils/s6-nice.c
new file mode 100644
index 0000000..38017f6
--- /dev/null
+++ b/src/s6-portable-utils/s6-nice.c
@@ -0,0 +1,45 @@
+/* ISC license. */
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-nice [ -I | -i ] [ -n value ] prog..."
+
+int main (int argc, char const *const *argv)
+{
+ int incr = 10 ;
+ int strict = 0 ;
+ PROG = "s6-nice" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "Iin:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'I' : strict = 0 ; break ;
+ case 'i' : strict = 1 ; break ;
+ case 'n': if (!int_scan(l.arg, &incr)) strerr_dieusage(100, USAGE) ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (!argc) strerr_dieusage(100, USAGE) ;
+
+ errno = 0 ;
+ if ((nice(incr) < 0) && errno)
+ {
+ char fmt[1+UINT_FMT] ;
+ fmt[int_fmt(fmt, incr)] = 0 ;
+ if (strict) strerr_diefu2sys(111, "nice to ", fmt) ;
+ else strerr_warnwu2sys("nice to ", fmt) ;
+ }
+ xexec(argv) ;
+}
diff --git a/src/s6-portable-utils/s6-nuke.c b/src/s6-portable-utils/s6-nuke.c
new file mode 100644
index 0000000..ff80b6c
--- /dev/null
+++ b/src/s6-portable-utils/s6-nuke.c
@@ -0,0 +1,50 @@
+/* ISC license. */
+
+#include
+#include
+
+#include
+#include
+#include
+
+#define USAGE "s6-nuke [ -h | -t | -k ]"
+
+int main (int argc, char const *const *argv)
+{
+ int doterm = 0, dohangup = 0, dokill = 0 ;
+ PROG = "s6-nuke" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "htk", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'h': dohangup = 1 ; break ;
+ case 't': doterm = 1 ; break ;
+ case 'k': dokill = 1 ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+
+ if (dohangup)
+ {
+ sig_ignore(SIGHUP) ;
+ kill(-1, SIGHUP) ;
+ }
+
+ if (doterm)
+ {
+ sig_ignore(SIGTERM) ;
+ kill(-1, SIGTERM) ;
+ kill(-1, SIGCONT) ;
+ }
+
+ if (dokill) kill(-1, SIGKILL) ;
+
+ if (errno) strerr_diefu1sys(111, "kill") ;
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-pause.c b/src/s6-portable-utils/s6-pause.c
new file mode 100644
index 0000000..e0416ba
--- /dev/null
+++ b/src/s6-portable-utils/s6-pause.c
@@ -0,0 +1,50 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-pause [ -t ] [ -h ] [ -a ] [ -q ] [ -b ] [ -i ] [ -p signal,signal... ]"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+#define PAUSE_MAX 64
+
+int main (int argc, char const *const *argv)
+{
+ PROG = "s6-pause" ;
+ unsigned int sigs[PAUSE_MAX] ;
+ size_t nsig = 0 ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "thaqbip:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 't' : if (nsig >= PAUSE_MAX) dieusage() ; sigs[nsig++] = SIGTERM ; break ;
+ case 'h' : if (nsig >= PAUSE_MAX) dieusage() ; sigs[nsig++] = SIGHUP ; break ;
+ case 'a' : if (nsig >= PAUSE_MAX) dieusage() ; sigs[nsig++] = SIGALRM ; break ;
+ case 'q' : if (nsig >= PAUSE_MAX) dieusage() ; sigs[nsig++] = SIGQUIT ; break ;
+ case 'b' : if (nsig >= PAUSE_MAX) dieusage() ; sigs[nsig++] = SIGABRT ; break ;
+ case 'i' : if (nsig >= PAUSE_MAX) dieusage() ; sigs[nsig++] = SIGINT ; break ;
+ case 'p' :
+ {
+ size_t n ;
+ if (!uint_scanlist(sigs + nsig, PAUSE_MAX - nsig, l.arg, &n)) dieusage() ;
+ nsig += n ;
+ break ;
+ }
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+
+ while (nsig--) sig_ignore(sigs[nsig]) ;
+ pause() ;
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-printenv.c b/src/s6-portable-utils/s6-printenv.c
new file mode 100644
index 0000000..d1a48de
--- /dev/null
+++ b/src/s6-portable-utils/s6-printenv.c
@@ -0,0 +1,52 @@
+/* ISC license. */
+
+#include
+
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-printenv [ -n ] [ -0 | -d delimchar ]"
+
+int main (int argc, char const *const *argv, char const *const *envp)
+{
+ char delim = '\n' ;
+ int zero = 0, nl = 1 ;
+ PROG = "s6-printenv" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "nd:0", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'n' : nl = 0 ; break ;
+ case 'd' : delim = *l.arg ; break ;
+ case '0' : zero = 1 ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (zero) delim = 0 ;
+ for (; *envp ; envp++)
+ {
+ if (delim || zero)
+ {
+ if ((buffer_puts(buffer_1, *envp) < 0)
+ || ((nl || envp[1]) && (buffer_put(buffer_1, &delim, 1) < 0)))
+ strerr_diefu1sys(111, "write to stdout") ;
+ }
+ else
+ {
+ size_t written = 0 ;
+ if (!netstring_put(buffer_1, *envp, strlen(*envp), &written))
+ strerr_diefu1sys(111, "write a netstring to stdout") ;
+ }
+ }
+ if (!buffer_flush(buffer_1))
+ strerr_diefu1sys(111, "write to stdout") ;
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-quote-filter.c b/src/s6-portable-utils/s6-quote-filter.c
new file mode 100644
index 0000000..5ed5b60
--- /dev/null
+++ b/src/s6-portable-utils/s6-quote-filter.c
@@ -0,0 +1,74 @@
+/* ISC license. */
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-quote-filter [ -u ] [ -d delim ]"
+
+int main (int argc, char const *const *argv)
+{
+ stralloc src = STRALLOC_ZERO ;
+ stralloc dst = STRALLOC_ZERO ;
+ char const *delim = "\"" ;
+ size_t delimlen ;
+ size_t startquote = 1 ;
+ PROG = "s6-quote-filter" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "ud:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'u' : startquote = 0 ; break ;
+ case 'd': delim = l.arg ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ delimlen = strlen(delim) ;
+ if (startquote)
+ {
+ if(!delimlen) strerr_dief1x(100, "no character to quote with!") ;
+ if (!stralloc_catb(&dst, delim, 1))
+ strerr_diefu1sys(111, "stralloc_catb") ;
+ }
+ for (;;)
+ {
+ int r ;
+ src.len = 0 ;
+ r = skagetln(buffer_0f1, &src, '\n') ;
+ if (!r) break ;
+ if ((r < 0) && (errno != EPIPE))
+ strerr_diefu1sys(111, "read from stdin") ;
+ dst.len = startquote ;
+ if (!string_quote_nodelim_mustquote(&dst, src.s, src.len - (r > 0), delim, delimlen))
+ {
+ int e = errno ;
+ buffer_flush(buffer_1) ;
+ errno = e ;
+ strerr_diefu1sys(111, "quote") ;
+ }
+ if (startquote)
+ {
+ if (!stralloc_catb(&dst, delim, 1))
+ strerr_diefu1sys(111, "stralloc_catb") ;
+ }
+ if (r > 0)
+ {
+ if (!stralloc_catb(&dst, "\n", 1))
+ strerr_diefu1sys(111, "stralloc_catb") ;
+ }
+ if (buffer_put(buffer_1, dst.s, dst.len) < 0)
+ strerr_diefu1sys(111, "write to stdout") ;
+ }
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-quote.c b/src/s6-portable-utils/s6-quote.c
new file mode 100644
index 0000000..74c137c
--- /dev/null
+++ b/src/s6-portable-utils/s6-quote.c
@@ -0,0 +1,60 @@
+/* ISC license. */
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-quote [ -n ] [ -u ] [ -d delim ] string"
+
+int main (int argc, char const *const *argv)
+{
+ stralloc sa = STRALLOC_ZERO ;
+ char const *delim = "\"" ;
+ size_t delimlen ;
+ size_t startquote = 1 ;
+ int nl = 1 ;
+ PROG = "s6-quote" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "nud:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'n' : nl = 0 ; break ;
+ case 'u' : startquote = 0 ; break ;
+ case 'd': delim = l.arg ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (!argc) strerr_dieusage(100, USAGE) ;
+ delimlen = strlen(delim) ;
+ if (startquote)
+ {
+ if (!delimlen) strerr_dief1x(100, "no character to quote with!") ;
+ if (!stralloc_catb(&sa, delim, 1))
+ strerr_diefu1sys(111, "stralloc_catb") ;
+ }
+ if (!string_quote_nodelim_mustquote(&sa, *argv, strlen(*argv), delim, delimlen))
+ strerr_diefu1sys(111, "quote") ;
+ if (startquote)
+ {
+ if (!stralloc_catb(&sa, delim, 1))
+ strerr_diefu1sys(111, "stralloc_catb") ;
+ }
+ if (nl)
+ {
+ if (!stralloc_catb(&sa, "\n", 1))
+ strerr_diefu1sys(111, "stralloc_catb") ;
+ }
+ if (allwrite(1, sa.s, sa.len) < sa.len)
+ strerr_diefu1sys(111, "write to stdout") ;
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-rename.c b/src/s6-portable-utils/s6-rename.c
new file mode 100644
index 0000000..a4fc1ee
--- /dev/null
+++ b/src/s6-portable-utils/s6-rename.c
@@ -0,0 +1,16 @@
+/* ISC license. */
+
+#include
+
+#include
+
+#define USAGE "s6-rename old new"
+
+int main (int argc, char const *const *argv)
+{
+ PROG = "s6-rename" ;
+ if (argc < 3) strerr_dieusage(100, USAGE) ;
+ if (rename(argv[1], argv[2]) == -1)
+ strerr_diefu4sys(111, "rename ", argv[1], " to ", argv[2]) ;
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-rmrf.c b/src/s6-portable-utils/s6-rmrf.c
new file mode 100644
index 0000000..ebbf9a0
--- /dev/null
+++ b/src/s6-portable-utils/s6-rmrf.c
@@ -0,0 +1,17 @@
+/* ISC license. */
+
+#include
+#include
+
+#define USAGE "s6-rmrf file ..."
+
+int main (int argc, char const *const *argv)
+{
+ char const *const *p = argv + 1 ;
+ PROG = "s6-rmrf" ;
+ if (argc < 2) strerr_dieusage(100, USAGE) ;
+ for (; *p ; p++)
+ if (rm_rf(*p) == -1)
+ strerr_diefu2sys(111, "remove ", argv[1]) ;
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-seq.c b/src/s6-portable-utils/s6-seq.c
new file mode 100644
index 0000000..a7b70ba
--- /dev/null
+++ b/src/s6-portable-utils/s6-seq.c
@@ -0,0 +1,63 @@
+/* ISC license. */
+
+#include
+
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-seq [ -w ] [ -s separator ] limits"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv)
+{
+ char const *sep = "\n" ;
+ size_t fixed = 0, seplen = 1 ;
+ unsigned int i = 1, increment = 1, last ;
+ char fmt[UINT_FMT] ;
+ PROG = "s6-seq" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "ws:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'w': fixed = 1 ; break ;
+ case 's': sep = l.arg ; seplen = strlen(sep) ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ switch (argc)
+ {
+ case 1 :
+ if (!uint0_scan(argv[0], &last)) dieusage() ;
+ break ;
+ case 2 :
+ if (!uint0_scan(argv[0], &i)
+ || !uint0_scan(argv[1], &last)) dieusage() ;
+ break ;
+ case 3 :
+ if (!uint0_scan(argv[0], &i)
+ || !uint0_scan(argv[1], &increment)
+ || !uint0_scan(argv[2], &last)) dieusage() ;
+ break ;
+ default : dieusage() ;
+ }
+ if (!seplen) seplen = 1 ;
+ if (fixed) fixed = uint_fmt(0, i + increment * ((last - i) / increment)) ;
+ for (; i <= last ; i += increment)
+ {
+ if (buffer_put(buffer_1, fmt, fixed ? (uint0_fmt(fmt, i, fixed), fixed) : uint_fmt(fmt, i)) < 0) goto err ;
+ if (buffer_put(buffer_1, sep, seplen) < 0) goto err ;
+ }
+ if (!buffer_flush(buffer_1)) goto err ;
+ return 0 ;
+
+err:
+ strerr_diefu1sys(111, "write to stdout") ;
+}
diff --git a/src/s6-portable-utils/s6-sleep.c b/src/s6-portable-utils/s6-sleep.c
new file mode 100644
index 0000000..c5a05b4
--- /dev/null
+++ b/src/s6-portable-utils/s6-sleep.c
@@ -0,0 +1,44 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-sleep [ -m ] duration prog..."
+
+int main (int argc, char const *const *argv)
+{
+ unsigned int n ;
+ int milli = 0 ;
+ PROG = "s6-sleep" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "m", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'm': milli = 1 ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (!argc) strerr_dieusage(100, USAGE) ;
+ if (!uint0_scan(argv[0], &n)) strerr_dieusage(100, USAGE) ;
+
+ {
+ tain deadline ;
+ if (milli) tain_from_millisecs(&deadline, n) ;
+ else tain_uint(&deadline, n) ;
+ tain_now_set_stopwatch_g() ;
+ tain_add_g(&deadline, &deadline) ;
+ deepsleepuntil_g(&deadline) ;
+ }
+
+ xexec0(argv+1) ;
+}
diff --git a/src/s6-portable-utils/s6-sort.c b/src/s6-portable-utils/s6-sort.c
new file mode 100644
index 0000000..66955fe
--- /dev/null
+++ b/src/s6-portable-utils/s6-sort.c
@@ -0,0 +1,130 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-sort [ -bcfru0 ]"
+
+typedef int strncmp_func (char const *, char const *, size_t) ;
+typedef strncmp_func *strncmp_func_ref ;
+typedef int qsortcmp_func (void const *, void const *) ;
+typedef qsortcmp_func *qsortcmp_func_ref ;
+
+typedef struct sort_global_s sort_global, *sort_global_ref ;
+struct sort_global_s
+{
+ strncmp_func_ref comp ;
+ unsigned char flagnoblanks : 1 ;
+ unsigned char flagreverse : 1 ;
+ unsigned char flaguniq : 1 ;
+} ;
+#define SORT_GLOBAL_ZERO { .flagnoblanks = 0, .flagreverse = 0, .flaguniq = 0, .comp = &strncmp }
+
+static sort_global_ref sort_G ;
+
+static int compit (char const *s1, size_t n1, char const *s2, size_t n2)
+{
+ int r ;
+ if (sort_G->flagnoblanks)
+ {
+ while ((*s1 == ' ') || (*s1 == '\t')) (s1++, n1--) ;
+ while ((*s2 == ' ') || (*s2 == '\t')) (s2++, n2--) ;
+ }
+ r = (*sort_G->comp)(s1, s2, n1 < n2 ? n1 : n2) ;
+ if (!r) r = n1 - n2 ;
+ return sort_G->flagreverse ? -r : r ;
+}
+
+static int sacmp (stralloc const *a, stralloc const *b)
+{
+ return compit(a->s, a->len - 1, b->s, b->len - 1) ;
+}
+
+static ssize_t sort_slurplines (genalloc *lines, char sep)
+{
+ ssize_t i = 0 ;
+ for (;; i++)
+ {
+ stralloc sa = STRALLOC_ZERO ;
+ int r = skagetln(buffer_0, &sa, sep) ;
+ if (!r) break ;
+ if ((r < 0) && ((errno != EPIPE) || !stralloc_catb(&sa, &sep, 1)))
+ return -1 ;
+ stralloc_shrink(&sa) ;
+ if (!genalloc_append(stralloc, lines, &sa)) return -1 ;
+ }
+ return i ;
+}
+
+static void sort_uniq (genalloc *lines)
+{
+ size_t len = genalloc_len(stralloc, lines) ;
+ stralloc *s = genalloc_s(stralloc, lines) ;
+ size_t i = 1 ;
+ for (; i < len ; i++)
+ if (!sacmp(s+i-1, s+i)) stralloc_free(s+i-1) ;
+}
+
+static ssize_t sort_outputlines (stralloc const *s, size_t len)
+{
+ size_t i = 0 ;
+ for (; i < len ; i++)
+ if (buffer_put(buffer_1, s[i].s, s[i].len) < 0) return 0 ;
+ return buffer_flush(buffer_1) ;
+}
+
+static int sort_check (stralloc const *s, size_t len)
+{
+ size_t i = 1 ;
+ for (; i < len ; i++)
+ if (sacmp(s+i-1, s+i) >= !sort_G->flaguniq) return 0 ;
+ return 1 ;
+}
+
+int main (int argc, char const *const *argv)
+{
+ genalloc lines = GENALLOC_ZERO ; /* array of stralloc */
+ int flagcheck = 0 ;
+ char sep = '\n' ;
+ sort_global globals = SORT_GLOBAL_ZERO ;
+ sort_G = &globals ;
+ PROG = "s6-sort" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "bcfru0", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'b' : sort_G->flagnoblanks = 1 ; break ;
+ case 'c' : flagcheck = 1 ; break ;
+ case 'f' : sort_G->comp = &strncasecmp ; break ;
+ case 'r' : sort_G->flagreverse = 1 ; break ;
+ case 'u' : sort_G->flaguniq = 1 ; break ;
+ case '0' : sep = '\0' ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+
+ if (sort_slurplines(&lines, sep) < 0) strerr_diefu1sys(111, "read from stdin") ;
+ if (flagcheck) return !sort_check(genalloc_s(stralloc, &lines), genalloc_len(stralloc, &lines)) ;
+ qsort(genalloc_s(stralloc, &lines), genalloc_len(stralloc, &lines), sizeof(stralloc), (qsortcmp_func_ref)&sacmp) ;
+ if (sort_G->flaguniq) sort_uniq(&lines) ;
+ if (!sort_outputlines(genalloc_s(stralloc, &lines), genalloc_len(stralloc, &lines)))
+ strerr_diefu1sys(111, "write to stdout") ;
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-sync.c b/src/s6-portable-utils/s6-sync.c
new file mode 100644
index 0000000..34e3e73
--- /dev/null
+++ b/src/s6-portable-utils/s6-sync.c
@@ -0,0 +1,9 @@
+/* ISC license. */
+
+#include
+
+int main (void)
+{
+ sync() ;
+ _exit(0) ;
+}
diff --git a/src/s6-portable-utils/s6-tai64ndiff.c b/src/s6-portable-utils/s6-tai64ndiff.c
new file mode 100644
index 0000000..cb35b4e
--- /dev/null
+++ b/src/s6-portable-utils/s6-tai64ndiff.c
@@ -0,0 +1,74 @@
+/* ISC license. */
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+int main (int argc, char const *const *argv)
+{
+ stralloc sa = STRALLOC_ZERO ;
+ tain prev ;
+ int defined = 0 ;
+ PROG = "s6-tai64ndiff" ;
+
+ for (;;)
+ {
+ unsigned int p = 0 ;
+ char prefix[23] = "[ . ]" ;
+ int r = skagetln(buffer_0f1, &sa, '\n') ;
+ if (r == -1)
+ if (errno != EPIPE)
+ strerr_diefu1sys(111, "read from stdin") ;
+ else r = 1 ;
+ else if (!r) break ;
+ if (sa.len > TIMESTAMP)
+ {
+ tain cur ;
+ p = timestamp_scan(sa.s, &cur) ;
+ if (p)
+ {
+ if (defined)
+ {
+ tain diff ;
+ int64_t secs ;
+ size_t len ;
+ tain_sub(&diff, &cur, &prev) ;
+ secs = tai_sec(tain_secp(&diff)) ;
+ len = int64_fmt(0, secs) ;
+ if (len > 10)
+ {
+ char fmtn[9] ;
+ size_t m = 1 + (len < 20) ;
+ m += int64_fmt(prefix + m, secs) ;
+ prefix[m++] = '.' ;
+ uint320_fmt(fmtn, tain_nano(&diff), 9) ;
+ memcpy(prefix + m, fmtn, 22 - m) ;
+ }
+ else
+ {
+ int64_fmt(prefix + 11 - len, secs) ;
+ uint320_fmt(prefix + 12, tain_nano(&diff), 9) ;
+ }
+ }
+ prev = cur ;
+ defined = 1 ;
+ if (buffer_put(buffer_1, prefix, 23) < 23)
+ strerr_diefu1sys(111, "write to stdout") ;
+ }
+ else defined = 0 ;
+ }
+ else defined = 0 ;
+ if (buffer_put(buffer_1, sa.s + p, sa.len - p) < (ssize_t)(sa.len - p))
+ strerr_diefu1sys(111, "write to stdout") ;
+ sa.len = 0 ;
+ }
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-tail.c b/src/s6-portable-utils/s6-tail.c
new file mode 100644
index 0000000..a3091cd
--- /dev/null
+++ b/src/s6-portable-utils/s6-tail.c
@@ -0,0 +1,199 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-tail [ -c chars | -n lines | -1..9 ] [ file ]"
+
+typedef int tail_func (int, size_t) ;
+typedef tail_func *tail_func_ref ;
+
+static int tail_pluslines (int fd, size_t n)
+{
+ if (n) n-- ;
+ {
+ char buf[BUFFER_INSIZE] ;
+ buffer b = BUFFER_INIT(&buffer_read, fd, buf, BUFFER_INSIZE) ;
+ size_t count = 0 ;
+ while (count < n)
+ {
+ ssize_t r = buffer_fill(&b) ;
+ if (r <= 0) return !r ;
+ while (!buffer_isempty(&b) && (count < n))
+ {
+ struct iovec v[2] ;
+ size_t i ;
+ buffer_rpeek(&b, v) ;
+ i = siovec_bytechr(v, 2, '\n') ;
+ if (i < buffer_len(&b))
+ {
+ count++ ; i++ ;
+ }
+ buffer_rseek(&b, i) ;
+ }
+ }
+ b.op = &buffer_write ;
+ b.fd = 1 ;
+ if (!buffer_flush(&b)) return 0 ;
+ }
+ return (fd_cat(fd, 1) >= 0) ;
+}
+
+static int tail_pluschars (int fd, size_t n)
+{
+ if (n-- > 1)
+ {
+ int nil = open_write("/dev/null") ;
+ if (nil < 0) return 0 ;
+ if (!fd_catn(fd, nil, n))
+ {
+ fd_close(nil) ;
+ return 0 ;
+ }
+ fd_close(nil) ;
+ }
+ return (fd_cat(fd, 1) >= 0) ;
+}
+
+static int tail_minuslines (int fd, size_t n)
+{
+ char buf[BUFFER_INSIZE] ;
+ buffer b = BUFFER_INIT(&buffer_read, fd, buf, BUFFER_INSIZE) ;
+ size_t head = 0, tail = 0 ;
+ stralloc tab[n+1] ;
+ for (; head <= n ; head++) tab[head] = stralloc_zero ;
+ head = 0 ;
+ for (;;)
+ {
+ int r ;
+ r = skagetln(&b, tab + tail, '\n') ;
+ if (!r) break ;
+ if (r < 0)
+ {
+ if (errno == EPIPE) break ;
+ else goto err ;
+ }
+ tail = (tail + 1) % (n+1) ;
+ if (tail == head)
+ {
+ tab[head].len = 0 ;
+ head = (head + 1) % (n+1) ;
+ }
+ }
+ buffer_init(&b, &buffer_write, 1, buf, BUFFER_INSIZE) ;
+ for (; head != tail ; head = (head + 1) % (n+1))
+ {
+ if (buffer_put(&b, tab[head].s, tab[head].len) < tab[head].len)
+ goto err ;
+ }
+ for (head = 0 ; head <= n ; head++) stralloc_free(tab + head) ;
+ return buffer_flush(&b) ;
+ err:
+ for (head = 0 ; head <= n ; head++) stralloc_free(tab + head) ;
+ return 0 ;
+}
+
+static int tail_minuschars (int fd, size_t n)
+{
+ char buf[BUFFER_INSIZE + n] ;
+ buffer b = BUFFER_INIT(&buffer_read, fd, buf, BUFFER_INSIZE + n) ;
+ for (;;)
+ {
+ ssize_t r = buffer_fill(&b) ;
+ if (!r) break ;
+ if (r < 0) return 0 ;
+ buffer_rseek(&b, buffer_len(&b)) ;
+ buffer_unget(&b, n) ;
+ }
+ b.op = &buffer_write ;
+ b.fd = 1 ;
+ return buffer_flush(&b) ;
+}
+
+int main (int argc, char const *const *argv)
+{
+ tail_func_ref f = &tail_minuslines ;
+ unsigned int n = 10 ;
+ int gotit = 0 ;
+ PROG = "s6-tail" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "123456789n:c:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case '1' :
+ case '2' :
+ case '3' :
+ case '4' :
+ case '5' :
+ case '6' :
+ case '7' :
+ case '8' :
+ case '9' :
+ {
+ if (gotit) strerr_dieusage(100, USAGE) ;
+ gotit = 1 ;
+ f = &tail_minuslines ;
+ n = opt - '0' ;
+ break ;
+ }
+ case 'n':
+ {
+ if (gotit) strerr_dieusage(100, USAGE) ;
+ gotit = 1 ;
+ f = &tail_minuslines ;
+ if (*l.arg == '-') l.arg++ ;
+ else if (*l.arg == '+')
+ {
+ f = &tail_pluslines ;
+ l.arg++ ;
+ }
+ if (!uint0_scan(l.arg, &n)) strerr_dieusage(100, USAGE) ;
+ break ;
+ }
+ case 'c':
+ {
+ if (gotit) strerr_dieusage(100, USAGE) ;
+ gotit = 1 ;
+ f = &tail_minuschars ;
+ if (*l.arg == '-') l.arg++ ;
+ else if (*l.arg == '+')
+ {
+ f = &tail_pluschars ;
+ l.arg++ ;
+ }
+ if (!uint0_scan(l.arg, &n)) strerr_dieusage(100, USAGE) ;
+ break ;
+ }
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (!argc)
+ {
+ if (!(*f)(0, n))
+ strerr_diefu1sys(111, "tail stdin") ;
+ }
+ else
+ {
+ int fd = open_readb(argv[0]) ;
+ if (fd == -1) strerr_diefu3sys(111, "open ", argv[0], " for reading") ;
+ if (!(*f)(fd, n))
+ strerr_diefu2sys(111, "tail ", argv[0]) ;
+ fd_close(fd) ;
+ }
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-touch.c b/src/s6-portable-utils/s6-touch.c
new file mode 100644
index 0000000..7c2c156
--- /dev/null
+++ b/src/s6-portable-utils/s6-touch.c
@@ -0,0 +1,15 @@
+/* ISC license. */
+
+#include
+#include
+
+#define USAGE "s6-touch file ..."
+
+int main (int argc, char const *const *argv)
+{
+ char const *const *p = argv + 1 ;
+ PROG = "s6-touch" ;
+ if (argc < 2) strerr_dieusage(100, USAGE) ;
+ for (; *p ; p++) if (!touch(*p)) strerr_diefu2sys(111, "touch ", *p) ;
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-true.c b/src/s6-portable-utils/s6-true.c
new file mode 100644
index 0000000..f372d43
--- /dev/null
+++ b/src/s6-portable-utils/s6-true.c
@@ -0,0 +1,8 @@
+/* ISC license. */
+
+#include
+
+int main (void)
+{
+ _exit(0) ;
+}
diff --git a/src/s6-portable-utils/s6-uniquename.c b/src/s6-portable-utils/s6-uniquename.c
new file mode 100644
index 0000000..479c50d
--- /dev/null
+++ b/src/s6-portable-utils/s6-uniquename.c
@@ -0,0 +1,40 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-uniquename [ -n randomlen ] prefix"
+#define usage() strerr_dieusage(100, USAGE)
+
+int main (int argc, char const *const *argv)
+{
+ stralloc sa = STRALLOC_ZERO ;
+ unsigned int n = 8 ;
+ PROG = "s6-uniquename" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "n:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'n' : if (!uint0_scan(l.arg, &n)) usage() ; break ;
+ default : usage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (argc < 1) usage() ;
+ if (!stralloc_cats(&sa, argv[0])) strerr_diefu1sys(111, "stralloc_cats") ;
+ if (!(n ? random_sauniquename_early(&sa, n) : sauniquename(&sa)))
+ strerr_diefu1sys(111, "make unique name") ;
+ if (!stralloc_catb(&sa, "\n", 1)) strerr_diefu1sys(111, "stralloc_cats") ;
+ if (allwrite(1, sa.s, sa.len) < sa.len) strerr_diefu1sys(111, "write to stdout") ;
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-unquote-filter.c b/src/s6-portable-utils/s6-unquote-filter.c
new file mode 100644
index 0000000..4b1b4ef
--- /dev/null
+++ b/src/s6-portable-utils/s6-unquote-filter.c
@@ -0,0 +1,198 @@
+/* ISC license. */
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-unquote-filter [ -q | -Q | -v | -w ] [ -d delim ]"
+
+static void unquotefilter_fillfmt (char *fmt, char const *s, size_t len)
+{
+ size_t n = len < 39 ? len+1 : 36 ;
+ memcpy(fmt, s, n) ;
+ if (len >= 39)
+ {
+ memcpy(fmt+n, "...", 3) ;
+ n += 3 ;
+ }
+ fmt[n] = 0 ;
+}
+
+static int unquotefilter_doit (char const *s, size_t len, unsigned int strictness, char const *delim, size_t delimlen)
+{
+ if (delimlen)
+ {
+ if (!len)
+ {
+ switch (strictness)
+ {
+ case 1 :
+ case 2 :
+ strerr_warnw1x("empty line") ;
+ break ;
+ case 3 :
+ buffer_flush(buffer_1) ;
+ strerr_dief1x(100, "empty line") ;
+ default : break ;
+ }
+ return 1 ;
+ }
+ if (!memchr(delim, *s, delimlen))
+ {
+ switch (strictness)
+ {
+ case 0 : return 0 ;
+ case 1 :
+ {
+ strerr_warnw1x("invalid starting quote character") ;
+ return 0 ;
+ }
+ case 2 :
+ {
+ char fmt[40] ;
+ unquotefilter_fillfmt(fmt, s, len) ;
+ strerr_warnw3x("invalid starting quote character", " in line: ", fmt) ;
+ return 0 ;
+ }
+ case 3 :
+ {
+ buffer_flush(buffer_1) ;
+ strerr_dief1x(100, "invalid starting quote character") ;
+ }
+ default : strerr_dief1x(101, "can't happen: unknown strictness") ;
+ }
+ }
+ }
+ {
+ size_t r, w ;
+ char d[len] ;
+ if (!string_unquote_withdelim(d, &w, s + !!delimlen, len - !!delimlen, &r, delim, delimlen))
+ {
+ switch (strictness)
+ {
+ case 0 : return 0 ;
+ case 1 :
+ {
+ strerr_warnwu1sys("unquote") ;
+ return 0 ;
+ }
+ case 2 :
+ {
+ char fmt[40] ;
+ unquotefilter_fillfmt(fmt, s, len) ;
+ strerr_warnwu3sys("unquote", " line: ", fmt) ;
+ return 0 ;
+ }
+ case 3 :
+ {
+ int e = errno ;
+ buffer_flush(buffer_1) ;
+ errno = e ;
+ strerr_diefu1sys(100, "unquote") ;
+ }
+ default : strerr_dief1x(101, "can't happen: unknown strictness") ;
+ }
+ }
+ if (delimlen)
+ {
+ if (r+1 == len)
+ {
+ switch (strictness)
+ {
+ case 0 : return 0 ;
+ case 1 :
+ {
+ strerr_warnwu2x("unquote", ": no ending quote character") ;
+ return 0 ;
+ }
+ case 2 :
+ {
+ char fmt[40] ;
+ unquotefilter_fillfmt(fmt, s, len) ;
+ strerr_warnwu5x("unquote", ": no ending quote character", " in ", "line: ", fmt) ;
+ return 0 ;
+ }
+ case 3 :
+ {
+ int e = errno ;
+ buffer_flush(buffer_1) ;
+ errno = e ;
+ strerr_diefu2x(100, "unquote", ": no ending quote character") ;
+ }
+ default : strerr_dief1x(101, "can't happen: unknown strictness") ;
+ }
+ }
+ else if ((r+2 < len) && (strictness >= 2))
+ {
+ char fmtnum[SIZE_FMT] ;
+ char fmtden[SIZE_FMT] ;
+ char fmt[40] ;
+ unquotefilter_fillfmt(fmt, s, len) ;
+ fmtnum[size_fmt(fmtnum, r+1)] = 0 ;
+ fmtden[size_fmt(fmtden, len-1)] = 0 ;
+ strerr_warnw7x("found ending quote character at position ", fmtnum, "/", fmtden, ", ignoring remainder of ", "line: ", fmt) ;
+ }
+ }
+ if (buffer_put(buffer_1, d, w) < (ssize_t)w)
+ strerr_diefu1sys(111, "write to stdout") ;
+ }
+ return 1 ;
+}
+
+
+int main (int argc, char const *const *argv)
+{
+ stralloc src = STRALLOC_ZERO ;
+ unsigned int strictness = 1 ;
+ char const *delim = "\"" ;
+ size_t delimlen = 1 ;
+ PROG = "s6-unquote-filter" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "qQvwd:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'q': strictness = 0 ; break ;
+ case 'Q': strictness = 1 ; break ;
+ case 'v': strictness = 2 ; break ;
+ case 'w': strictness = 3 ; break ;
+ case 'd': delim = l.arg ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ delimlen = strlen(delim) ;
+ for (;;)
+ {
+ int r ;
+ src.len = 0 ;
+ r = skagetln(buffer_0f1, &src, '\n') ;
+ if (!r) break ;
+ if (r < 0)
+ {
+ if (errno != EPIPE) strerr_diefu1sys(111, "read from stdin") ;
+ }
+ else src.len-- ;
+ if (!unquotefilter_doit(src.s, src.len, strictness, delim, delimlen))
+ {
+ if (buffer_put(buffer_1, src.s, src.len) < (ssize_t)src.len)
+ strerr_diefu1sys(111, "write to stdout") ;
+ }
+ if (r > 0)
+ {
+ if (buffer_put(buffer_1, "\n", 1) < 1)
+ strerr_diefu1sys(111, "write to stdout") ;
+ }
+ }
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-unquote.c b/src/s6-portable-utils/s6-unquote.c
new file mode 100644
index 0000000..34dcea5
--- /dev/null
+++ b/src/s6-portable-utils/s6-unquote.c
@@ -0,0 +1,71 @@
+/* ISC license. */
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-unquote [ -n ] [ -d delim ] string"
+
+int main (int argc, char const *const *argv)
+{
+ char const *delim = "\"" ;
+ char const *string ;
+ size_t len, delimlen ;
+ int nl = 1 ;
+ PROG = "s6-unquote" ;
+ {
+ subgetopt l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "nd:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'n' : nl = 0 ; break ;
+ case 'd': delim = l.arg ; break ;
+ default : strerr_dieusage(100, USAGE) ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (!argc) strerr_dieusage(100, USAGE) ;
+ string = *argv ;
+ len = strlen(string) ;
+ delimlen = strlen(delim) ;
+ if (delimlen)
+ {
+ if (!len--) strerr_dief1x(100, "the empty string isn't a quoted string") ;
+ if (!memchr(delim, *string++, delimlen))
+ strerr_dief1x(100, "invalid starting quote character") ;
+ }
+ {
+ size_t r = 0, w = 0 ;
+ char buf[len+1] ;
+ if (!string_unquote_withdelim(buf, &w, string, len, &r, delim, delimlen))
+ {
+ char fmt[SIZE_FMT] ;
+ fmt[size_fmt(fmt, r + !!delimlen)] = 0 ;
+ strerr_diefu2sys(100, "unquote at character ", fmt) ;
+ }
+ if (delimlen)
+ {
+ if (r == len) strerr_dief1x(100, "no ending quote character") ;
+ else if (r < len - 1)
+ {
+ char fmtnum[SIZE_FMT] ;
+ char fmtden[SIZE_FMT] ;
+ fmtnum[size_fmt(fmtnum, r+1)] = 0 ;
+ fmtden[size_fmt(fmtden, len)] = 0 ;
+ strerr_warnw5x("found ending quote character at position ", fmtnum, "/", fmtden, "; ignoring remainder") ;
+ }
+ }
+ if (nl) buf[w++] = '\n' ;
+ if (allwrite(1, buf, w) < w)
+ strerr_diefu1sys(111, "write to stdout") ;
+ }
+ return 0 ;
+}
diff --git a/src/s6-portable-utils/s6-update-symlinks.c b/src/s6-portable-utils/s6-update-symlinks.c
new file mode 100644
index 0000000..5ba9156
--- /dev/null
+++ b/src/s6-portable-utils/s6-update-symlinks.c
@@ -0,0 +1,345 @@
+/* ISC license. */
+
+#include
+#include
+#include