├── src ├── s6-portable-utils │ ├── deps-exe │ │ ├── s6-sync │ │ ├── s6-true │ │ ├── s6-false │ │ ├── s6-cat │ │ ├── s6-chmod │ │ ├── s6-chown │ │ ├── s6-cut │ │ ├── s6-echo │ │ ├── s6-env │ │ ├── s6-expr │ │ ├── s6-grep │ │ ├── s6-head │ │ ├── s6-ln │ │ ├── s6-ls │ │ ├── s6-mkdir │ │ ├── s6-nice │ │ ├── s6-nuke │ │ ├── s6-pause │ │ ├── s6-quote │ │ ├── s6-rmrf │ │ ├── s6-seq │ │ ├── s6-sort │ │ ├── s6-tail │ │ ├── s6-touch │ │ ├── s6-basename │ │ ├── s6-dirname │ │ ├── s6-dumpenv │ │ ├── s6-hiercopy │ │ ├── s6-linkname │ │ ├── s6-mkfifo │ │ ├── s6-printenv │ │ ├── s6-rename │ │ ├── s6-tai64ndiff │ │ ├── s6-uniquename │ │ ├── s6-unquote │ │ ├── seekablepipe │ │ ├── s6-format-filter │ │ ├── s6-quote-filter │ │ ├── s6-unquote-filter │ │ ├── s6-update-symlinks │ │ ├── s6-clock │ │ ├── s6-sleep │ │ └── s6-maximumtime │ ├── s6-false.c │ ├── s6-true.c │ ├── s6-sync.c │ ├── s6-cat.c │ ├── s6-rename.c │ ├── s6-touch.c │ ├── s6-rmrf.c │ ├── s6-hiercopy.c │ ├── s6-clock.c │ ├── seekablepipe.c │ ├── s6-chmod.c │ ├── s6-mkfifo.c │ ├── s6-echo.c │ ├── s6-nuke.c │ ├── s6-dirname.c │ ├── s6-sleep.c │ ├── s6-nice.c │ ├── s6-linkname.c │ ├── s6-env.c │ ├── s6-uniquename.c │ ├── s6-basename.c │ ├── s6-printenv.c │ ├── s6-chown.c │ ├── s6-pause.c │ ├── s6-ls.c │ ├── s6-format-filter.c │ ├── s6-quote.c │ ├── s6-seq.c │ ├── s6-quote-filter.c │ ├── s6-tai64ndiff.c │ ├── s6-dumpenv.c │ ├── s6-unquote.c │ ├── s6-mkdir.c │ ├── s6-maximumtime.c │ ├── s6-grep.c │ ├── s6-sort.c │ ├── s6-ln.c │ ├── s6-head.c │ ├── s6-tail.c │ ├── s6-unquote-filter.c │ ├── s6-expr.c │ └── s6-cut.c └── multicall │ └── deps-exe │ └── s6-portable-utils ├── package ├── configure-snippets │ ├── configure_expand_dirs │ ├── configure_extra_checks │ ├── configure_generate_configh │ ├── configure_help_install │ ├── configure_help_dependencies │ ├── configure_slashpackage_other │ ├── configure_init_vars │ ├── configure_help_options │ ├── configure_generate_make │ └── configure_case_lines ├── deps-build ├── info ├── targets.mak ├── modes └── deps.mak ├── CONTRIBUTING ├── AUTHORS ├── README.solaris ├── patch-for-solaris ├── tools ├── run-test.sh ├── gen-configure.el ├── install.sh ├── gen-dotpc.sh ├── gen-multicall.sh └── gen-deps.sh ├── COPYING ├── README ├── .gitignore ├── doc ├── s6-sync.html ├── s6-rmrf.html ├── s6-rename.html ├── s6-true.html ├── s6-false.html ├── seekablepipe.html ├── s6-cut.html ├── s6-mkfifo.html ├── s6-touch.html ├── s6-chmod.html ├── s6-env.html ├── s6-cat.html ├── s6-mkdir.html ├── s6-dirname.html ├── s6-linkname.html ├── s6-printenv.html ├── s6-uniquename.html ├── s6-echo.html ├── s6-basename.html ├── s6-tail.html ├── s6-expr.html ├── s6-format-filter.html ├── s6-sleep.html ├── s6-nice.html ├── s6-nuke.html ├── s6-clock.html ├── s6-pause.html ├── s6-ls.html ├── s6-head.html ├── s6-chown.html ├── s6-quote-filter.html ├── s6-sort.html ├── s6-quote.html ├── s6-unquote.html ├── s6-portable-utils.html ├── s6-dumpenv.html ├── s6-seq.html ├── s6-maximumtime.html ├── s6-ln.html ├── s6-tai64ndiff.html ├── s6-grep.html ├── s6-unquote-filter.html ├── s6-hiercopy.html ├── s6-update-symlinks.html └── upgrade.html ├── DCO └── NEWS /src/s6-portable-utils/deps-exe/s6-sync: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-true: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-false: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_expand_dirs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-cat: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-chmod: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-chown: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-cut: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-echo: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-env: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-expr: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-grep: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-head: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-ln: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-ls: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-mkdir: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-nice: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-nuke: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-pause: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-quote: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-rmrf: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-seq: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-sort: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-tail: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-touch: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_extra_checks: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_generate_configh: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_help_install: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-basename: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-dirname: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-dumpenv: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-hiercopy: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-linkname: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-mkfifo: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-printenv: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-rename: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-tai64ndiff: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-uniquename: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-unquote: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/seekablepipe: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_help_dependencies: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_slashpackage_other: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-format-filter: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-quote-filter: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-unquote-filter: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-update-symlinks: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_init_vars: -------------------------------------------------------------------------------- 1 | multicall=false 2 | -------------------------------------------------------------------------------- /src/multicall/deps-exe/s6-portable-utils: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | ${SPAWN_LIB} 3 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-clock: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | ${SYSCLOCK_LIB} 3 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-sleep: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | ${SYSCLOCK_LIB} 3 | -------------------------------------------------------------------------------- /package/deps-build: -------------------------------------------------------------------------------- 1 | true true /package/prog/skalibs 2.14.4.0 libskarnet 2 | -------------------------------------------------------------------------------- /src/s6-portable-utils/deps-exe/s6-maximumtime: -------------------------------------------------------------------------------- 1 | -lskarnet 2 | ${SYSCLOCK_LIB} 3 | ${SPAWN_LIB} 4 | -------------------------------------------------------------------------------- /package/info: -------------------------------------------------------------------------------- 1 | package=s6-portable-utils 2 | version=2.3.1.1 3 | category=admin 4 | package_macro_name=S6_PORTABLE_UTILS 5 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_help_options: -------------------------------------------------------------------------------- 1 | --enable-multicall build a multicall binary [disabled] 2 | 3 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-false.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | int main (void) 6 | { 7 | _exit(1) ; 8 | } 9 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-true.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | int main (void) 6 | { 7 | _exit(0) ; 8 | } 9 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_generate_make: -------------------------------------------------------------------------------- 1 | if $multicall ; then 2 | echo "MULTICALL := 1" 3 | else 4 | echo "MULTICALL :=" 5 | fi 6 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-sync.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | int main (void) 6 | { 7 | sync() ; 8 | _exit(0) ; 9 | } 10 | -------------------------------------------------------------------------------- /package/configure-snippets/configure_case_lines: -------------------------------------------------------------------------------- 1 | --enable-multicall|--enable-multicall=yes) multicall=true ;; 2 | --disable-multicall|--enable-multicall=no) multicall=false ;; 3 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-cat.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | 6 | int main (void) 7 | { 8 | PROG = "s6-cat" ; 9 | if (fd_cat(0, 1) < 0) strerr_diefu1sys(111, "fd_cat") ; 10 | return 0 ; 11 | } 12 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | Please add a Signed-Off-By: line at the end of your commit, 2 | which certifies that you have the right and authority to pass 3 | it on as an open-source patch, as explicited in the Developer's 4 | Certificate of Origin available in this project's DCO file, 5 | or at https://developercertificate.org/ 6 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-rename.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #include 6 | 7 | #define USAGE "s6-rename old new" 8 | 9 | int main (int argc, char const *const *argv) 10 | { 11 | PROG = "s6-rename" ; 12 | if (argc < 3) strerr_dieusage(100, USAGE) ; 13 | if (rename(argv[1], argv[2]) == -1) 14 | strerr_diefu4sys(111, "rename ", argv[1], " to ", argv[2]) ; 15 | return 0 ; 16 | } 17 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-touch.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | 6 | #define USAGE "s6-touch file ..." 7 | 8 | int main (int argc, char const *const *argv) 9 | { 10 | char const *const *p = argv + 1 ; 11 | PROG = "s6-touch" ; 12 | if (argc < 2) strerr_dieusage(100, USAGE) ; 13 | for (; *p ; p++) if (!touch(*p)) strerr_diefu2sys(111, "touch ", *p) ; 14 | return 0 ; 15 | } 16 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Main author: 2 | Laurent Bercot 3 | 4 | Contributors: 5 | Mira Ressel 6 | Wictor Lund 7 | 8 | Thanks to: 9 | Dan J. Bernstein 10 | Jean Marot 11 | Jorge Almeida 12 | Vallo Kallaste 13 | Josuah Demangeon 14 | Eric Vidal 15 | Colin Booth 16 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-rmrf.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | 6 | #define USAGE "s6-rmrf file ..." 7 | 8 | int main (int argc, char const *const *argv) 9 | { 10 | char const *const *p = argv + 1 ; 11 | PROG = "s6-rmrf" ; 12 | if (argc < 2) strerr_dieusage(100, USAGE) ; 13 | for (; *p ; p++) 14 | if (rm_rf(*p) == -1) 15 | strerr_diefu2sys(111, "remove ", argv[1]) ; 16 | return 0 ; 17 | } 18 | -------------------------------------------------------------------------------- /README.solaris: -------------------------------------------------------------------------------- 1 | This package assumes the existence of a POSIX shell in /bin/sh. 2 | On Solaris, /bin/sh is not POSIX. Most versions of Solaris provide 3 | a POSIX shell in /usr/xpg4/bin/sh. 4 | 5 | To compile this package on Solaris, you will need to run 6 | 7 | ./patch-for-solaris 8 | 9 | before you run ./configure. This script will change the #! invocation 10 | of the configure script and various tools so that a POSIX shell is used 11 | for the compilation process. 12 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-hiercopy.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #define USAGE "s6-hiercopy src dst" 9 | 10 | int main (int argc, char const *const *argv) 11 | { 12 | PROG = "s6-hiercopy" ; 13 | if (argc < 3) strerr_dieusage(100, USAGE) ; 14 | umask(0) ; 15 | if (!hiercopy(argv[1], argv[2])) 16 | strerr_diefu4sys(111, "copy hierarchy from ", argv[1], " to ", argv[2]) ; 17 | return 0 ; 18 | } 19 | -------------------------------------------------------------------------------- /patch-for-solaris: -------------------------------------------------------------------------------- 1 | #!/usr/xpg4/bin/sh -e 2 | 3 | patchit () { 4 | echo '#!/usr/xpg4/bin/sh' > $1.tmp 5 | tail -n +2 $1 >> $1.tmp 6 | mv -f $1.tmp $1 7 | chmod 755 $1 8 | } 9 | 10 | # Solaris doesn't understand POSIX.1-2008 either. 11 | sed -e 's/XOPEN_SOURCE=700/XOPEN_SOURCE=600/' < configure > configure.tmp 12 | mv -f configure.tmp configure 13 | 14 | patchit ./configure 15 | patchit ./tools/install.sh 16 | patchit ./tools/gen-deps.sh 17 | 18 | echo 'SHELL := /usr/xpg4/bin/sh' > Makefile.tmp 19 | echo >> Makefile.tmp 20 | cat Makefile >> Makefile.tmp 21 | mv -f Makefile.tmp Makefile 22 | -------------------------------------------------------------------------------- /tools/run-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | prog="$1" 4 | 5 | if test -x "./src/tests/${prog}.wrapper" ; then 6 | cmd="./src/tests/${prog}.wrapper $prog" 7 | else 8 | cmd="./$prog" 9 | fi 10 | 11 | if test -r "./src/tests/${prog}.expected" ; then 12 | cp -f "./src/tests/${prog}.expected" "./${prog}.expected" 13 | elif test -x "./src/tests/${prog}.baseline" ; then 14 | "./src/tests/${prog}.baseline" > "./${prog}.expected" 15 | else 16 | echo "run-test.sh: fatal: missing baseline for $prog" 1>&2 ; exit 100 17 | fi 18 | 19 | $cmd | diff "./${prog}.expected" - 20 | 21 | rm -f "./${prog}.expected" 22 | echo "run-test.sh: info: $prog: pass" 1>&2 23 | -------------------------------------------------------------------------------- /package/targets.mak: -------------------------------------------------------------------------------- 1 | LIBEXEC_TARGETS := 2 | 3 | ifeq ($(MULTICALL),1) 4 | 5 | BIN_TARGETS := $(package) 6 | BIN_SYMLINKS := $(notdir $(wildcard src/$(package)/deps-exe/*)) 7 | EXTRA_TARGETS += src/multicall/$(package).c 8 | 9 | define symlink_definition 10 | SYMLINK_TARGET_$(1) := $(package) 11 | endef 12 | $(foreach name,$(BIN_SYMLINKS),$(eval $(call symlink_definition,$(name)))) 13 | 14 | src/multicall/$(package).c: tools/gen-multicall.sh $(BIN_SYMLINKS:%=src/$(package)/%.c) 15 | ./tools/gen-multicall.sh $(package) > src/multicall/$(package).c 16 | 17 | src/multicall/$(package).o: src/multicall/$(package).c src/include/$(package)/config.h 18 | 19 | else 20 | 21 | BIN_TARGETS := $(notdir $(wildcard src/$(package)/deps-exe/*)) 22 | BIN_SYMLINKS := 23 | 24 | endif 25 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2025 Laurent Bercot 2 | 3 | Permission to use, copy, modify, and distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-clock.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define USAGE "s6-clock [ tai64nlabel ]" 8 | 9 | static int s6clock_getit (void) 10 | { 11 | char fmt[TIMESTAMP+1] ; 12 | timestamp(fmt) ; 13 | fmt[TIMESTAMP] = '\n' ; 14 | if (allwrite(1, fmt, TIMESTAMP+1) < TIMESTAMP+1) 15 | strerr_diefu1sys(111, "write to stdout") ; 16 | return 0 ; 17 | } 18 | 19 | static int s6clock_setit (char const *h) 20 | { 21 | tain a ; 22 | if (!timestamp_scan(h, &a)) strerr_dieusage(100, USAGE) ; 23 | if (!tain_setnow(&a)) strerr_diefu1sys(111, "taia_setnow") ; 24 | return 0 ; 25 | } 26 | 27 | int main (int argc, char const *const *argv) 28 | { 29 | PROG = "s6-clock" ; 30 | return (argc < 2) ? s6clock_getit() : s6clock_setit(argv[1]) ; 31 | } 32 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | s6-portable-utils - tiny general Unix utilities 2 | ----------------------------------------------- 3 | 4 | s6-portable-utils is a set of tiny general Unix utilities, 5 | some performing well-known tasks such as cut and grep, 6 | others being nonstandard but useful in a variety of 7 | scripting situations; they have been optimized for simplicity 8 | and small size. They were designed for embedded systems and 9 | other constrained environments, but they work everywhere. 10 | 11 | See https://skarnet.org/software/s6-portable-utils/ for details. 12 | 13 | 14 | * Installation 15 | ------------ 16 | 17 | See the INSTALL file. 18 | 19 | 20 | * Contact information 21 | ------------------- 22 | 23 | Laurent Bercot 24 | 25 | Please use the mailing-list for 26 | questions about s6-portable-utils. 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /*.pc 2 | *.o 3 | *.a 4 | *.lo 5 | *.so 6 | *.so.* 7 | /config.mak 8 | /src/include/s6-portable-utils/config.h 9 | /src/multicall/s6-portable-utils.c 10 | /s6-portable-utils 11 | /s6-basename 12 | /s6-cat 13 | /s6-chmod 14 | /s6-chown 15 | /s6-clock 16 | /s6-cut 17 | /s6-dirname 18 | /s6-dumpenv 19 | /s6-echo 20 | /s6-env 21 | /s6-expr 22 | /s6-false 23 | /s6-format-filter 24 | /s6-grep 25 | /s6-head 26 | /s6-hiercopy 27 | /s6-linkname 28 | /s6-ln 29 | /s6-ls 30 | /s6-maximumtime 31 | /s6-mkdir 32 | /s6-mkfifo 33 | /s6-nice 34 | /s6-nuke 35 | /s6-pause 36 | /s6-printenv 37 | /s6-quote 38 | /s6-quote-filter 39 | /s6-rename 40 | /s6-rmrf 41 | /s6-seq 42 | /s6-sleep 43 | /s6-sort 44 | /s6-sync 45 | /s6-tai64ndiff 46 | /s6-tail 47 | /s6-test 48 | /s6-touch 49 | /s6-true 50 | /s6-uniquename 51 | /s6-unquote 52 | /s6-unquote-filter 53 | /s6-update-symlinks 54 | /seekablepipe 55 | -------------------------------------------------------------------------------- /package/modes: -------------------------------------------------------------------------------- 1 | s6-basename 0755 2 | s6-cat 0755 3 | s6-chmod 0755 4 | s6-chown 0755 5 | s6-clock 0755 6 | s6-cut 0755 7 | s6-dirname 0755 8 | s6-dumpenv 0755 9 | s6-echo 0755 10 | s6-env 0755 11 | s6-expr 0755 12 | s6-false 0755 13 | s6-format-filter 0755 14 | s6-grep 0755 15 | s6-head 0755 16 | s6-hiercopy 0755 17 | s6-linkname 0755 18 | s6-ln 0755 19 | s6-ls 0755 20 | s6-maximumtime 0755 21 | s6-mkdir 0755 22 | s6-mkfifo 0755 23 | s6-nice 0755 24 | s6-nuke 0755 25 | s6-pause 0755 26 | s6-printenv 0755 27 | s6-quote 0755 28 | s6-quote-filter 0755 29 | s6-rename 0755 30 | s6-rmrf 0755 31 | s6-seq 0755 32 | s6-sleep 0755 33 | s6-sort 0755 34 | s6-sync 0755 35 | s6-tai64ndiff 0755 36 | s6-tail 0755 37 | s6-touch 0755 38 | s6-true 0755 39 | s6-uniquename 0755 40 | s6-unquote 0755 41 | s6-unquote-filter 0755 42 | s6-update-symlinks 0755 43 | seekablepipe 0755 44 | s6-portable-utils 0755 45 | -------------------------------------------------------------------------------- /src/s6-portable-utils/seekablepipe.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define USAGE "seekablepipe tempfile prog..." 11 | 12 | int main (int argc, char const *const *argv) 13 | { 14 | int fdr, fdw ; 15 | PROG = "seekablepipe" ; 16 | if (argc < 3) strerr_dieusage(100, USAGE) ; 17 | fdw = open_trunc(argv[1]) ; 18 | if (fdw < 0) 19 | strerr_diefu2sys(111, "create temporary ", argv[1]) ; 20 | fdr = open_readb(argv[1]) ; 21 | if (fdr < 0) 22 | strerr_diefu3sys(111, "open ", argv[1], " for reading") ; 23 | unlink_void(argv[1]) ; 24 | if (ndelay_off(fdw) < 0) 25 | strerr_diefu1sys(111, "set fdw blocking") ; 26 | if (fd_cat(0, fdw) < 0) 27 | strerr_diefu1sys(111, "read from stdin") ; 28 | close(fdw) ; 29 | if (fd_move(0, fdr) < 0) 30 | strerr_diefu1sys(111, "move temporary file descriptor") ; 31 | xexec(argv+2) ; 32 | } 33 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-chmod.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #define USAGE "s6-chmod mode file" 9 | 10 | int main (int argc, char const *const *argv) 11 | { 12 | mode_t mode = 0 ; 13 | unsigned int m ; 14 | PROG = "s6-chmod" ; 15 | if (argc < 3) strerr_dieusage(100, USAGE) ; 16 | if (!uint0_oscan(argv[1], &m)) strerr_dieusage(100, USAGE) ; 17 | 18 | if (m & 0001) mode |= S_IXOTH ; 19 | if (m & 0002) mode |= S_IWOTH ; 20 | if (m & 0004) mode |= S_IROTH ; 21 | if (m & 0010) mode |= S_IXGRP ; 22 | if (m & 0020) mode |= S_IWGRP ; 23 | if (m & 0040) mode |= S_IRGRP ; 24 | if (m & 0100) mode |= S_IXUSR ; 25 | if (m & 0200) mode |= S_IWUSR ; 26 | if (m & 0400) mode |= S_IRUSR ; 27 | if (m & 01000) mode |= S_ISVTX ; 28 | if (m & 02000) mode |= S_ISGID ; 29 | if (m & 04000) mode |= S_ISUID ; 30 | 31 | if (chmod(argv[2], mode) == -1) 32 | strerr_diefu2sys(111, "change mode of ", argv[2]) ; 33 | return 0 ; 34 | } 35 | -------------------------------------------------------------------------------- /doc/s6-sync.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-sync program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-sync program

20 | 21 |

22 | s6-sync flushes all the dirty system buffers, and blocks until they're 23 | clean. 24 |

25 | 26 |

Interface

27 | 28 |
29 |      s6-sync
30 | 
31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-mkfifo.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define USAGE "s6-mkfifo [ -m mode ] fifo..." 11 | 12 | int main (int argc, char const *const *argv) 13 | { 14 | unsigned int mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH ; 15 | PROG = "s6-mkfifo" ; 16 | { 17 | subgetopt l = SUBGETOPT_ZERO ; 18 | for (;;) 19 | { 20 | int opt = subgetopt_r(argc, argv, "m:", &l) ; 21 | if (opt == -1) break ; 22 | switch (opt) 23 | { 24 | case 'm': if (uint0_oscan(l.arg, &mode)) break ; 25 | default : strerr_dieusage(100, USAGE) ; 26 | } 27 | } 28 | argc -= l.ind ; argv += l.ind ; 29 | } 30 | if (!argc) strerr_dieusage(100, USAGE) ; 31 | umask(S_IXUSR|S_IXGRP|S_IXOTH) ; 32 | for (; *argv ; argv++) 33 | if (mkfifo(*argv, mode) < 0) 34 | strerr_diefu2sys(111, "mkfifo ", *argv) ; 35 | return 0 ; 36 | } 37 | -------------------------------------------------------------------------------- /tools/gen-configure.el: -------------------------------------------------------------------------------- 1 | #!/command/execlineb -S0 2 | 3 | # For dev use only. Don't run this, it overwrites your configure. 4 | 5 | # The quoting interactions in sed and sh make it impossible to get 6 | # such a simple thing done. It's amazing how bad traditional Unix is. 7 | 8 | backtick -E TEMPLATE { redirfd -r 0 tools/configure.template s6-cat } 9 | s6-envdir -Lf package/configure-snippets 10 | multisubstitute 11 | { 12 | importas -uS configure_help_install 13 | importas -uS configure_help_dependencies 14 | importas -uS configure_help_options 15 | importas -uS configure_init_vars 16 | importas -uS configure_case_lines 17 | importas -uS configure_expand_dirs 18 | importas -uS configure_slashpackage_other 19 | importas -uS configure_extra_checks 20 | importas -uS configure_generate_make 21 | importas -uS configure_generate_configh 22 | } 23 | 24 | if 25 | { 26 | redirfd -w 1 configure.new 27 | if { heredoc 0 ${TEMPLATE} s6-cat } 28 | s6-echo 29 | } 30 | 31 | if { s6-chmod 0755 configure.new } 32 | s6-rename configure.new configure 33 | -------------------------------------------------------------------------------- /doc/s6-rmrf.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-rmrf program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-rmrf program

20 | 21 |

22 | s6-rmrf removes a file or directory tree entirely. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-rmrf subtree
29 | 
30 | 31 |

32 | s6-rmrf removes the subtree file hierarchy. 33 |

34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /doc/s6-rename.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-rename program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-rename program

20 | 21 |

22 | s6-rename atomically renames a file. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-rename old new
29 | 
30 | 31 |

32 | s6-rename atomically renames old to new. 33 |

34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-echo.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define USAGE "s6-echo [ -n ] [ -s sep ] args..." 8 | 9 | int main (int argc, char const *const *argv) 10 | { 11 | char sep = ' ' ; 12 | char donl = 1 ; 13 | PROG = "s6-echo" ; 14 | { 15 | subgetopt l = SUBGETOPT_ZERO ; 16 | for (;;) 17 | { 18 | int opt = subgetopt_r(argc, argv, "ns:", &l) ; 19 | if (opt == -1) break ; 20 | switch (opt) 21 | { 22 | case 'n': donl = 0 ; break ; 23 | case 's': sep = *l.arg ; break ; 24 | default : strerr_dieusage(100, USAGE) ; 25 | } 26 | } 27 | argc -= l.ind ; argv += l.ind ; 28 | } 29 | for ( ; *argv ; argv++) 30 | if ((buffer_puts(buffer_1small, *argv) < 0) 31 | || (argv[1] && (buffer_put(buffer_1small, &sep, 1) < 0))) 32 | goto err ; 33 | if (donl && (buffer_put(buffer_1small, "\n", 1) < 0)) goto err ; 34 | if (!buffer_flush(buffer_1small)) goto err ; 35 | return 0 ; 36 | err: 37 | strerr_diefu1sys(111, "write to stdout") ; 38 | } 39 | -------------------------------------------------------------------------------- /doc/s6-true.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-true program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-true program

20 | 21 |

22 | s6-true returns 0. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-true
29 | 
30 | 31 |

Posixness

32 | 33 |

34 | s6-true is suitable as a Single Unix 35 | true 36 | program. 37 |

38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-nuke.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #define USAGE "s6-nuke [ -h | -t | -k ]" 11 | 12 | int main (int argc, char const *const *argv) 13 | { 14 | int doterm = 0, dohangup = 0, dokill = 0 ; 15 | PROG = "s6-nuke" ; 16 | { 17 | subgetopt l = SUBGETOPT_ZERO ; 18 | for (;;) 19 | { 20 | int opt = subgetopt_r(argc, argv, "htk", &l) ; 21 | if (opt == -1) break ; 22 | switch (opt) 23 | { 24 | case 'h': dohangup = 1 ; break ; 25 | case 't': doterm = 1 ; break ; 26 | case 'k': dokill = 1 ; break ; 27 | default : strerr_dieusage(100, USAGE) ; 28 | } 29 | } 30 | argc -= l.ind ; argv += l.ind ; 31 | } 32 | 33 | if (dohangup) 34 | { 35 | sig_ignore(SIGHUP) ; 36 | kill(-1, SIGHUP) ; 37 | } 38 | 39 | if (doterm) 40 | { 41 | sig_ignore(SIGTERM) ; 42 | kill(-1, SIGTERM) ; 43 | kill(-1, SIGCONT) ; 44 | } 45 | 46 | if (dokill) kill(-1, SIGKILL) ; 47 | 48 | if (errno) strerr_diefu1sys(111, "kill") ; 49 | return 0 ; 50 | } 51 | -------------------------------------------------------------------------------- /doc/s6-false.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-false program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-false program

20 | 21 |

22 | s6-false returns 1. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-false
29 | 
30 | 31 |

Posixness

32 | 33 |

34 | s6-false is suitable as a Single Unix 35 | false 36 | program. 37 |

38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-dirname.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define USAGE "s6-dirname [ -n ] file" 12 | 13 | int main (int argc, char const *const *argv) 14 | { 15 | stralloc sa = STRALLOC_ZERO ; 16 | int nl = 1 ; 17 | PROG = "s6-dirname" ; 18 | { 19 | subgetopt l = SUBGETOPT_ZERO ; 20 | for (;;) 21 | { 22 | int opt = subgetopt_r(argc, argv, "n", &l) ; 23 | if (opt == -1) break ; 24 | switch (opt) 25 | { 26 | case 'n' : nl = 0 ; break ; 27 | default : strerr_dieusage(100, USAGE) ; 28 | } 29 | } 30 | argc -= l.ind ; argv += l.ind ; 31 | } 32 | 33 | if (!argc) strerr_dieusage(100, USAGE) ; 34 | if (!sadirname(&sa, argv[0], strlen(argv[0]))) 35 | strerr_diefu2sys(111, "get dirname of ", argv[0]) ; 36 | if (nl && !stralloc_catb(&sa, "\n", 1)) 37 | strerr_diefu2sys(111, "get dirname of ", argv[0]) ; 38 | if (allwrite(1, sa.s, sa.len) < sa.len) 39 | strerr_diefu1sys(111, "write to stdout") ; 40 | return 0 ; 41 | } 42 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-sleep.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define USAGE "s6-sleep [ -m ] duration prog..." 11 | 12 | int main (int argc, char const *const *argv) 13 | { 14 | unsigned int n ; 15 | int milli = 0 ; 16 | PROG = "s6-sleep" ; 17 | { 18 | subgetopt l = SUBGETOPT_ZERO ; 19 | for (;;) 20 | { 21 | int opt = subgetopt_r(argc, argv, "m", &l) ; 22 | if (opt == -1) break ; 23 | switch (opt) 24 | { 25 | case 'm': milli = 1 ; break ; 26 | default : strerr_dieusage(100, USAGE) ; 27 | } 28 | } 29 | argc -= l.ind ; argv += l.ind ; 30 | } 31 | if (!argc) strerr_dieusage(100, USAGE) ; 32 | if (!uint0_scan(argv[0], &n)) strerr_dieusage(100, USAGE) ; 33 | 34 | { 35 | tain deadline ; 36 | if (milli) tain_from_millisecs(&deadline, n) ; 37 | else tain_uint(&deadline, n) ; 38 | tain_now_set_stopwatch_g() ; 39 | tain_add_g(&deadline, &deadline) ; 40 | deepsleepuntil_g(&deadline) ; 41 | } 42 | 43 | xexec0(argv+1) ; 44 | } 45 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-nice.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define USAGE "s6-nice [ -I | -i ] [ -n value ] prog..." 12 | 13 | int main (int argc, char const *const *argv) 14 | { 15 | int incr = 10 ; 16 | int strict = 0 ; 17 | PROG = "s6-nice" ; 18 | { 19 | subgetopt l = SUBGETOPT_ZERO ; 20 | for (;;) 21 | { 22 | int opt = subgetopt_r(argc, argv, "Iin:", &l) ; 23 | if (opt == -1) break ; 24 | switch (opt) 25 | { 26 | case 'I' : strict = 0 ; break ; 27 | case 'i' : strict = 1 ; break ; 28 | case 'n': if (!int_scan(l.arg, &incr)) strerr_dieusage(100, USAGE) ; break ; 29 | default : strerr_dieusage(100, USAGE) ; 30 | } 31 | } 32 | argc -= l.ind ; argv += l.ind ; 33 | } 34 | if (!argc) strerr_dieusage(100, USAGE) ; 35 | 36 | errno = 0 ; 37 | if ((nice(incr) < 0) && errno) 38 | { 39 | char fmt[1+UINT_FMT] ; 40 | fmt[int_fmt(fmt, incr)] = 0 ; 41 | if (strict) strerr_diefu2sys(111, "nice to ", fmt) ; 42 | else strerr_warnwu2sys("nice to ", fmt) ; 43 | } 44 | xexec(argv) ; 45 | } 46 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-linkname.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define USAGE "s6-linkname [ -n ] [ -f ] link" 10 | #define dieusage() strerr_dieusage(100, USAGE) 11 | 12 | int main (int argc, char const *const *argv) 13 | { 14 | stralloc sa = STRALLOC_ZERO ; 15 | int path = 0, nl = 1 ; 16 | PROG = "s6-linkname" ; 17 | { 18 | subgetopt l = SUBGETOPT_ZERO ; 19 | for (;;) 20 | { 21 | int opt = subgetopt_r(argc, argv, "nf", &l) ; 22 | if (opt == -1) break ; 23 | switch(opt) 24 | { 25 | case 'n' : nl = 0 ; break ; 26 | case 'f' : path = 1 ; break ; 27 | default : dieusage() ; 28 | } 29 | } 30 | argv += l.ind ; argc -= l.ind ; 31 | } 32 | if (!argc) dieusage() ; 33 | 34 | if ((path ? sarealpath(&sa, *argv) : sareadlink(&sa, *argv)) < 0) 35 | strerr_diefu2sys(111, "resolve ", *argv) ; 36 | 37 | if ((buffer_put(buffer_1small, sa.s, sa.len) < 0) 38 | || (nl && (buffer_put(buffer_1small, "\n", 1)) < 0) 39 | || (!buffer_flush(buffer_1small))) 40 | strerr_diefu1sys(111, "write to stdout") ; 41 | 42 | return 0 ; 43 | } 44 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-env.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #define USAGE "s6-env [ -i ] [ name=value... ] prog..." 14 | 15 | int main (int argc, char const *const *argv, char const *const *envp) 16 | { 17 | stralloc modifs = STRALLOC_ZERO ; 18 | char const *arg_zero[2] = { S6_PORTABLE_UTILS_BINPREFIX "s6-printenv", 0 } ; 19 | char const *env_zero[1] = { 0 } ; 20 | PROG = "s6-env" ; 21 | { 22 | subgetopt l = SUBGETOPT_ZERO ; 23 | for (;;) 24 | { 25 | int opt = subgetopt_r(argc, argv, "i", &l) ; 26 | if (opt == -1) break ; 27 | switch (opt) 28 | { 29 | case 'i': envp = env_zero ; break ; 30 | default : strerr_dieusage(100, USAGE) ; 31 | } 32 | } 33 | argc -= l.ind ; argv += l.ind ; 34 | } 35 | for (; argc ; argc--, argv++) 36 | { 37 | if (!strchr(*argv, '=')) break ; 38 | if (!stralloc_cats(&modifs, *argv) || !stralloc_0(&modifs)) 39 | strerr_diefu1sys(111, "stralloc_cats") ; 40 | } 41 | if (!argc) argv = arg_zero ; 42 | xmexec_em(argv, envp, modifs.s, modifs.len) ; 43 | } 44 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-uniquename.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define USAGE "s6-uniquename [ -n randomlen ] prefix" 12 | #define usage() strerr_dieusage(100, USAGE) 13 | 14 | int main (int argc, char const *const *argv) 15 | { 16 | stralloc sa = STRALLOC_ZERO ; 17 | unsigned int n = 8 ; 18 | PROG = "s6-uniquename" ; 19 | { 20 | subgetopt l = SUBGETOPT_ZERO ; 21 | for (;;) 22 | { 23 | int opt = subgetopt_r(argc, argv, "n:", &l) ; 24 | if (opt == -1) break ; 25 | switch (opt) 26 | { 27 | case 'n' : if (!uint0_scan(l.arg, &n)) usage() ; break ; 28 | default : usage() ; 29 | } 30 | } 31 | argc -= l.ind ; argv += l.ind ; 32 | } 33 | if (argc < 1) usage() ; 34 | if (!stralloc_cats(&sa, argv[0])) strerr_diefu1sys(111, "stralloc_cats") ; 35 | if (!(n ? random_sauniquename_early(&sa, n) : sauniquename(&sa))) 36 | strerr_diefu1sys(111, "make unique name") ; 37 | if (!stralloc_catb(&sa, "\n", 1)) strerr_diefu1sys(111, "stralloc_cats") ; 38 | if (allwrite(1, sa.s, sa.len) < sa.len) strerr_diefu1sys(111, "write to stdout") ; 39 | return 0 ; 40 | } 41 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-basename.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define USAGE "s6-basename [ -n ] file [ suffix ]" 12 | 13 | int main (int argc, char const *const *argv) 14 | { 15 | stralloc sa = STRALLOC_ZERO ; 16 | int nl = 1 ; 17 | PROG = "s6-basename" ; 18 | { 19 | subgetopt l = SUBGETOPT_ZERO ; 20 | for (;;) 21 | { 22 | int opt = subgetopt_r(argc, argv, "n", &l) ; 23 | if (opt == -1) break ; 24 | switch (opt) 25 | { 26 | case 'n' : nl = 0 ; break ; 27 | default : strerr_dieusage(100, USAGE) ; 28 | } 29 | } 30 | argc -= l.ind ; argv += l.ind ; 31 | } 32 | if (!argc) strerr_dieusage(100, USAGE) ; 33 | if (!sabasename(&sa, argv[0], strlen(argv[0]))) 34 | strerr_diefu2sys(111, "get basename of ", argv[0]) ; 35 | if (argc >= 2) 36 | { 37 | size_t n = strlen(argv[1]) ; 38 | if ((n < sa.len) && !strncmp(argv[1], sa.s + sa.len - n, n)) 39 | sa.len -= n ; 40 | } 41 | if (nl && !stralloc_catb(&sa, "\n", 1)) 42 | strerr_diefu2sys(111, "get basename of ", argv[0]) ; 43 | if (allwrite(1, sa.s, sa.len) < sa.len) 44 | strerr_diefu1sys(111, "write to stdout") ; 45 | return 0 ; 46 | } 47 | -------------------------------------------------------------------------------- /tools/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | usage() { 4 | echo "usage: $0 [ -D ] [ -l ] [ -m mode ] [ -O owner:group ] src dst" 1>&2 5 | exit 1 6 | } 7 | 8 | mkdirp=false 9 | symlink=false 10 | mode=0755 11 | og= 12 | 13 | while getopts Dlm:O: name ; do 14 | case "$name" in 15 | D) mkdirp=true ;; 16 | l) symlink=true ;; 17 | m) mode=$OPTARG ;; 18 | O) og=$OPTARG ;; 19 | ?) usage ;; 20 | esac 21 | done 22 | shift $(($OPTIND - 1)) 23 | 24 | test "$#" -eq 2 || usage 25 | src=$1 26 | dst=$2 27 | tmp="$dst.tmp.$$" 28 | 29 | case "$dst" in 30 | */) echo "$0: $dst ends in /" 1>&2 ; exit 1 ;; 31 | esac 32 | 33 | set -C 34 | set -e 35 | 36 | if $mkdirp ; then 37 | umask 022 38 | case "$2" in 39 | */*) mkdir -p "${dst%/*}" ;; 40 | esac 41 | fi 42 | 43 | trap 'rm -f "$tmp"' EXIT INT QUIT TERM HUP 44 | 45 | umask 077 46 | 47 | if $symlink ; then 48 | ln -s "$src" "$tmp" 49 | else 50 | cat < "$1" > "$tmp" 51 | if test -n "$og" ; then 52 | chown -- "$og" "$tmp" 53 | fi 54 | chmod -- "$mode" "$tmp" 55 | fi 56 | 57 | mv -f "$tmp" "$dst" 58 | if test -d "$dst" ; then 59 | rm -f "$dst/$(basename $tmp)" 60 | if $symlink ; then 61 | mkdir "$tmp" 62 | ln -s "$src" "$tmp/$(basename $dst)" 63 | mv -f "$tmp/$(basename $dst)" "${dst%/*}" 64 | rmdir "$tmp" 65 | else 66 | echo "$0: $dst is a directory" 1>&2 67 | exit 1 68 | fi 69 | fi 70 | -------------------------------------------------------------------------------- /doc/seekablepipe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the seekablepipe program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The seekablepipe program

20 | 21 | seekablepipe turns the reading end of a pipe into a seekable 22 | file descriptor, using a temporary file. 23 | 24 |

Interface

25 | 26 |
27 |      writer | seekablepipe tmpfile reader [ args... ]
28 | 
29 | 30 |

31 | seekablepipe writes writer's output to tmpfile, 32 | which is unlinked as soon as it is created. Then it execs into 33 | reader, reading from a file descriptor on tmpfile. 34 |

35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /doc/s6-cut.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-cut program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-cut program

20 | 21 |

22 | s6-cut prints selected portions of the lines of its input. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-cut [ -b list | -c list | -f list ] [ -n ] [ -s ] [ file ... ]
29 | 
30 | 31 |

32 | s6-cut acts as the generic 33 | cut utility. 34 |

35 | 36 |

Posixness

37 | 38 |

39 | s6-cut is suitable as a Single Unix 40 | cut 41 | program. 42 |

43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /doc/s6-mkfifo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-mkfifo program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-mkfifo program

20 | 21 |

22 | s6-mkfifo creates FIFOs, a.k.a. named pipes. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-mkfifo [ -m mode ] [ fifo... ]
29 | 
30 | 31 |

32 | s6-mkfifo acts as the generic 33 | mkfifo utility. 34 |

35 | 36 |

Posixness

37 | 38 |

39 | s6-mkfifo is suitable as a Single Unix 40 | mkfifo 41 | program. 42 |

43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /doc/s6-touch.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-touch program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-touch program

20 | 21 |

22 | s6-touch changes the modification and access times of a file, creating it if it does 23 | not exist. 24 |

25 | 26 |

Interface

27 | 28 |
29 |      s6-touch file...
30 | 
31 | 32 |

33 | s6-touch touches every file in the list by opening them for appending 34 | then closing them. 35 |

36 | 37 |

Posixness

38 | 39 |

40 | s6-touch is not suitable as a Single Unix 41 | touch 42 | program. 43 |

44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /doc/s6-chmod.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-chmod program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-chmod program

20 | 21 |

22 | s6-chmod changes the permissions of a file. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-chmod perms file
29 | 
30 | 31 |

32 | s6-chmod changes file's permissions to perms, which 33 | must be an absolute octal number such as 0755 for 34 | rwxr-xr-x or 2700 for rwx--S---. 35 |

36 | 37 |

Posixness

38 | 39 |

40 | s6-chmod is not suitable as a Single Unix 41 | chmod 42 | program. 43 |

44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /doc/s6-env.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-env program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-env program

20 | 21 |

22 | s6-env prints the current environment or modifies the environment 23 | before running a program. 24 |

25 | 26 |

Interface

27 | 28 |
29 |      s6-env [ -i ] [ name=value... ] [ prog... ]
30 | 
31 | 32 |

33 | s6-env acts as the generic 34 | env utility. 35 |

36 | 37 |

Posixness

38 | 39 |

40 | s6-env is suitable as a Single Unix 41 | env 42 | program. 43 |

44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /doc/s6-cat.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-cat program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-cat program

20 | 21 |

22 | s6-cat copies stdin to stdout. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-cat
29 | 
30 | 31 |

32 | s6-cat transfers data from stdin to stdout, until it receives EOF or 33 | gets killed. 34 |

35 | 36 |

Notes

37 | 38 |

39 | On systems that support it (as of 2.0.0.0, only Linux 2.6.17 or later), 40 | s6-cat performs zero-copy transfer. 41 |

42 | 43 |

Posixness

44 | 45 |

46 | s6-cat is not suitable as a Single Unix 47 | cat 48 | program. 49 |

50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-printenv.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define USAGE "s6-printenv [ -n ] [ -0 | -d delimchar ]" 11 | 12 | int main (int argc, char const *const *argv, char const *const *envp) 13 | { 14 | char delim = '\n' ; 15 | int zero = 0, nl = 1 ; 16 | PROG = "s6-printenv" ; 17 | { 18 | subgetopt l = SUBGETOPT_ZERO ; 19 | for (;;) 20 | { 21 | int opt = subgetopt_r(argc, argv, "nd:0", &l) ; 22 | if (opt == -1) break ; 23 | switch (opt) 24 | { 25 | case 'n' : nl = 0 ; break ; 26 | case 'd' : delim = *l.arg ; break ; 27 | case '0' : zero = 1 ; break ; 28 | default : strerr_dieusage(100, USAGE) ; 29 | } 30 | } 31 | argc -= l.ind ; argv += l.ind ; 32 | } 33 | if (zero) delim = 0 ; 34 | for (; *envp ; envp++) 35 | { 36 | if (delim || zero) 37 | { 38 | if ((buffer_puts(buffer_1, *envp) < 0) 39 | || ((nl || envp[1]) && (buffer_put(buffer_1, &delim, 1) < 0))) 40 | strerr_diefu1sys(111, "write to stdout") ; 41 | } 42 | else 43 | { 44 | size_t written = 0 ; 45 | if (!netstring_put(buffer_1, *envp, strlen(*envp), &written)) 46 | strerr_diefu1sys(111, "write a netstring to stdout") ; 47 | } 48 | } 49 | if (!buffer_flush(buffer_1)) 50 | strerr_diefu1sys(111, "write to stdout") ; 51 | return 0 ; 52 | } 53 | -------------------------------------------------------------------------------- /doc/s6-mkdir.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-mkdir program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-mkdir program

20 | 21 |

22 | s6-mkdir creates directories. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-mkdir [ -p ] [ -v ] [ -m mode ] [ dir... ]
29 | 
30 | 31 |

32 | s6-mkdir acts as the generic 33 | mkdir utility. 34 |

35 | 36 |

Extra options

37 | 38 |
    39 |
  • -v : write what it does to stderr.
  • 40 |
41 | 42 |

Posixness

43 | 44 |

45 | s6-mkdir is suitable as a Single Unix 46 | mkdir 47 | program. 48 |

49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /DCO: -------------------------------------------------------------------------------- 1 | Developer Certificate of Origin 2 | Version 1.1 3 | 4 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 5 | 1 Letterman Drive 6 | Suite D4700 7 | San Francisco, CA, 94129 8 | 9 | Everyone is permitted to copy and distribute verbatim copies of this 10 | license document, but changing it is not allowed. 11 | 12 | 13 | Developer's Certificate of Origin 1.1 14 | 15 | By making a contribution to this project, I certify that: 16 | 17 | (a) The contribution was created in whole or in part by me and I 18 | have the right to submit it under the open source license 19 | indicated in the file; or 20 | 21 | (b) The contribution is based upon previous work that, to the best 22 | of my knowledge, is covered under an appropriate open source 23 | license and I have the right under that license to submit that 24 | work with modifications, whether created in whole or in part 25 | by me, under the same open source license (unless I am 26 | permitted to submit under a different license), as indicated 27 | in the file; or 28 | 29 | (c) The contribution was provided directly to me by some other 30 | person who certified (a), (b) or (c) and I have not modified 31 | it. 32 | 33 | (d) I understand and agree that this project and the contribution 34 | are public and that a record of the contribution (including all 35 | personal information I submit with it, including my sign-off) is 36 | maintained indefinitely and may be redistributed consistent with 37 | this project or the open source license(s) involved. 38 | -------------------------------------------------------------------------------- /doc/s6-dirname.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-dirname program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-dirname program

20 | 21 |

22 | s6-dirname prints the dirname of a path. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-dirname [ -n ] path
29 | 
30 | 31 |

32 | s6-dirname acts as the generic 33 | dirname utility. 34 |

35 | 36 |

Extra options

37 | 38 |
    39 |
  • -n : do not print a trailing newline after the output.
  • 40 |
41 | 42 |

Posixness

43 | 44 |

45 | s6-dirname is suitable as a Single Unix 46 | dirname 47 | program. 48 |

49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /doc/s6-linkname.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-linkname program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-linkname program

20 | 21 |

22 | s6-linkname gives the content of a symbolic link or resolves a path. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-linkname [ -f ] [ -n ] path
29 | 
30 | 31 |
    32 |
  • If path is a symbolic link, s6-linkname prints its 33 | content then exits 0.
  • 34 |
  • Else it prints an error message and exits 111.
  • 35 |
36 | 37 |

Options

38 | 39 |
    40 |
  • -f : s6-linkname fully resolves path then 41 | prints the result on stdout. path does not have to be a symbolic 42 | link.
  • 43 |
  • -n : do not print a newline after the result.
  • 44 |
45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /doc/s6-printenv.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-printenv program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-printenv program

20 | 21 |

22 | s6-printenv prints its environment variables. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-printenv [ -n ] [ -0 | -d delim ]
29 | 
30 | 31 |

32 | s6-printenv prints its environment on stdout, like 33 | s6-env. 34 |

35 | 36 |

Options

37 | 38 |
    39 |
  • -0 : separate variable definitions with a null character 40 | instead of a newline.
  • 41 |
  • -d delim : separate variable definitions with the 42 | first character of delim instead of a newline
  • 43 |
  • -n : omit the last delimiter character
  • 44 |
45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /doc/s6-uniquename.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-uniquename program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-uniquename program

20 | 21 |

22 | s6-uniquename creates a guaranteed unique file name and prints it to stdout. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-uniquename [ -n randomlen ] prefix
29 | 
30 | 31 |
    32 |
  • s6-uniquename creates a unique filename starting with prefix 33 | involving a TAI64N timestamp, the machine's FQDN and the process' PID.
  • 34 |
  • It prints it to stdout and exits 0.
  • 35 |
36 | 37 |

Options

38 | 39 |
    40 |
  • -n randomlen : for added security, also 41 | add a random readable string of randomlen characters to the 42 | created pathname.
  • 43 |
44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /doc/s6-echo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-echo program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-echo program

20 | 21 |

22 | s6-echo writes its arguments to stdout. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-echo [ -n ] [ -s sep ] args...
29 | 
30 | 31 |

32 | s6-echo writes its arguments args to stdout, separated with spaces. 33 |

34 | 35 |

Options

36 | 37 |
    38 |
  • -n : do not output a trailing newline.
  • 39 |
  • -s sep : separate arguments with the sep 40 | character instead of a space.
  • 41 |
42 | 43 |

Posixness

44 | 45 |

46 | s6-echo is not suitable as a Single Unix 47 | echo 48 | program. 49 |

50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /doc/s6-basename.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-basename program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-basename program

20 | 21 |

22 | s6-basename prints the basename of a pathname. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-basename [ -n ] path [ suffix ]
29 | 
30 | 31 |

32 | s6-basename acts as the generic 33 | basename utility. 34 |

35 | 36 |

Extra options

37 | 38 |
    39 |
  • -n : do not print a trailing newline after the output.
  • 40 |
41 | 42 |

Posixness

43 | 44 |

45 | s6-basename is suitable as a Single Unix 46 | basename 47 | program. 48 |

49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-chown.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define USAGE "s6-chown [ -U ] [ -u uid ] [ -g gid ] file" 12 | 13 | int main (int argc, char const *const *argv) 14 | { 15 | uid_t uid = -1 ; 16 | gid_t gid = -1 ; 17 | PROG = "s6-chown" ; 18 | { 19 | subgetopt l = SUBGETOPT_ZERO ; 20 | for (;;) 21 | { 22 | int opt = subgetopt_r(argc, argv, "Uu:g:", &l) ; 23 | if (opt == -1) break ; 24 | switch (opt) 25 | { 26 | case 'u': 27 | { 28 | if (!uid0_scan(l.arg, &uid)) strerr_dieusage(100, USAGE) ; 29 | break ; 30 | } 31 | case 'g': 32 | { 33 | if (!gid0_scan(l.arg, &gid)) strerr_dieusage(100, USAGE) ; 34 | break ; 35 | } 36 | case 'U': 37 | { 38 | char const *s = getenv("UID") ; 39 | if (!s) strerr_dienotset(100, "UID") ; 40 | if (!uid0_scan(s, &uid)) strerr_dieinvalid(100, "UID") ; 41 | s = getenv("GID") ; 42 | if (!s) strerr_dienotset(100, "GID") ; 43 | if (!gid0_scan(s, &gid)) strerr_dieinvalid(100, "GID") ; 44 | break ; 45 | } 46 | default : strerr_dieusage(100, USAGE) ; 47 | } 48 | } 49 | argc -= l.ind ; argv += l.ind ; 50 | } 51 | if (!argc) strerr_dieusage(100, USAGE) ; 52 | if (chown(*argv, uid, gid) == -1) 53 | strerr_diefu2sys(111, "chown ", argv[0]) ; 54 | return 0 ; 55 | } 56 | -------------------------------------------------------------------------------- /doc/s6-tail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-tail program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-tail program

20 | 21 |

22 | s6-tail prints a file or its stdin after a certain number of bytes or lines. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-tail [ -n lines | -c chars ] [ file ]
29 | 
30 | 31 |

32 | s6-tail acts as the generic 33 | tail utility, 34 | except that the -f option is not supported. 35 |

36 | 37 |

Posixness

38 | 39 |

40 | s6-tail is not suitable as a Single Unix 41 | tail 42 | program; however, if you are never using the -f functionality, s6-tail 43 | scrupulously follows the rest of the specification. 44 |

45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /doc/s6-expr.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-expr program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-expr program

20 | 21 |

22 | s6-expr evaluates an expression and writes the result to stdout. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-expr expression...
29 | 
30 | 31 |

32 | s6-expr acts as the generic 33 | expr utility, 34 | except that the : operator (pattern matching) is not supported. 35 |

36 | 37 |

38 | s6-expr accepts an arbitrary number of arguments. 39 |

40 | 41 |

Posixness

42 | 43 |

44 | s6-expr is not suitable as a Single Unix 45 | expr 46 | program; however, if you are never using the pattern matching functionality, s6-expr 47 | scrupulously follows the rest of the specification. 48 |

49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-pause.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define USAGE "s6-pause [ -t ] [ -h ] [ -a ] [ -q ] [ -b ] [ -i ] [ -p signal,signal... ]" 11 | #define dieusage() strerr_dieusage(100, USAGE) 12 | 13 | #define PAUSE_MAX 64 14 | 15 | int main (int argc, char const *const *argv) 16 | { 17 | PROG = "s6-pause" ; 18 | unsigned int sigs[PAUSE_MAX] ; 19 | size_t nsig = 0 ; 20 | { 21 | subgetopt l = SUBGETOPT_ZERO ; 22 | for (;;) 23 | { 24 | int opt = subgetopt_r(argc, argv, "thaqbip:", &l) ; 25 | if (opt == -1) break ; 26 | switch (opt) 27 | { 28 | case 't' : if (nsig >= PAUSE_MAX) dieusage() ; sigs[nsig++] = SIGTERM ; break ; 29 | case 'h' : if (nsig >= PAUSE_MAX) dieusage() ; sigs[nsig++] = SIGHUP ; break ; 30 | case 'a' : if (nsig >= PAUSE_MAX) dieusage() ; sigs[nsig++] = SIGALRM ; break ; 31 | case 'q' : if (nsig >= PAUSE_MAX) dieusage() ; sigs[nsig++] = SIGQUIT ; break ; 32 | case 'b' : if (nsig >= PAUSE_MAX) dieusage() ; sigs[nsig++] = SIGABRT ; break ; 33 | case 'i' : if (nsig >= PAUSE_MAX) dieusage() ; sigs[nsig++] = SIGINT ; break ; 34 | case 'p' : 35 | { 36 | size_t n ; 37 | if (!uint_scanlist(sigs + nsig, PAUSE_MAX - nsig, l.arg, &n)) dieusage() ; 38 | nsig += n ; 39 | break ; 40 | } 41 | default : dieusage() ; 42 | } 43 | } 44 | argc -= l.ind ; argv += l.ind ; 45 | } 46 | 47 | while (nsig--) sig_ignore(sigs[nsig]) ; 48 | pause() ; 49 | return 0 ; 50 | } 51 | -------------------------------------------------------------------------------- /doc/s6-format-filter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-format-filter program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-format-filter program

20 | 21 |

22 | s6-format-filter processes lines according to its arguments, and 23 | prints the result. 24 |

25 | 26 |

Interface

27 | 28 |
29 |      s6-format-filter format [ args... ]
30 | 
31 | 32 |
    33 |
  • format is a format string that can contain the following special sequences: 34 | %%, %s, and %0 to %9.
  • 35 |
  • For every line it reads on stdin, s6-format-filter prints format on 36 | stdout, replacing %% with %, %0 with the command name 37 | (probably s6-format-filter), %1 to %9 with the first 38 | to the ninth argument in args, and %s with the input line.
  • 39 |
  • s6-format-filter exits 0 when it reads EOF.
  • 40 |
41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-ls.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define USAGE "s6-ls [ -0 ] [ -a | -A ] [ -x exclude ] dir" 11 | 12 | int main (int argc, char const *const *argv) 13 | { 14 | unsigned int all = 0 ; 15 | char const *exclude = 0 ; 16 | char delim = '\n' ; 17 | PROG = "s6-ls" ; 18 | { 19 | subgetopt l = SUBGETOPT_ZERO ; 20 | for (;;) 21 | { 22 | int opt = subgetopt_r(argc, argv, "0aAx:", &l) ; 23 | if (opt == -1) break ; 24 | switch (opt) 25 | { 26 | case '0': delim = '\0' ; break ; 27 | case 'a': all = 1 ; break ; 28 | case 'A': all = 2 ; break ; 29 | case 'x': exclude = l.arg ; break ; 30 | default : strerr_dieusage(100, USAGE) ; 31 | } 32 | } 33 | argc -= l.ind ; argv += l.ind ; 34 | } 35 | if (!argc) strerr_dieusage(100, USAGE) ; 36 | { 37 | direntry *d ; 38 | DIR *dir = opendir(*argv) ; 39 | if (!dir) 40 | strerr_diefu2sys(111, "open directory ", *argv) ; 41 | while ((d = readdir(dir))) 42 | { 43 | if ((d->d_name[0] == '.') && (all < 2)) 44 | { 45 | if (!all || !d->d_name[1] || ((d->d_name[1] == '.') && !d->d_name[2])) continue ; 46 | } 47 | if (exclude && !strcmp(exclude, d->d_name)) continue ; 48 | if ((buffer_puts(buffer_1, d->d_name) < 0) 49 | || (buffer_put(buffer_1, &delim, 1) < 0)) 50 | strerr_diefu1sys(111, "write to stdout") ; 51 | } 52 | dir_close(dir) ; 53 | } 54 | if (!buffer_flush(buffer_1)) 55 | strerr_diefu1sys(111, "write to stdout") ; 56 | return 0 ; 57 | } 58 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-format-filter.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define USAGE "s6-format-filter format [ args... ]" 11 | 12 | int main (int argc, char const *const *argv) 13 | { 14 | stralloc src = STRALLOC_ZERO ; 15 | stralloc dst = STRALLOC_ZERO ; 16 | char vars[12] = "s0123456789" ; 17 | char const *args[12] = { "" } ; 18 | char const *format ; 19 | PROG = "s6-format-filter" ; 20 | argc-- ; args[1] = *argv++ ; 21 | if (!argc--) strerr_dieusage(100, USAGE) ; 22 | format = *argv++ ; 23 | if (argc > 9) argc = 9 ; 24 | vars[argc+2] = 0 ; 25 | { 26 | unsigned int i = 0 ; 27 | for (; i < (unsigned int)argc ; i++) args[2+i] = argv[i] ; 28 | } 29 | if (!string_format(&dst, vars, format, args)) 30 | strerr_diefu1sys(111, "compile format") ; 31 | 32 | for (;;) 33 | { 34 | int r ; 35 | src.len = 0 ; 36 | dst.len = 0 ; 37 | r = skagetln(buffer_0f1, &src, '\n') ; 38 | if (!r) break ; 39 | else if (r < 0) 40 | { 41 | if ((errno != EPIPE) || !stralloc_0(&src)) 42 | strerr_diefu1sys(111, "read from stdin") ; 43 | } 44 | else src.s[src.len-1] = 0 ; 45 | args[0] = src.s ; 46 | if (!string_format(&dst, vars, format, args)) 47 | { 48 | int e = errno ; 49 | buffer_flush(buffer_1) ; 50 | errno = e ; 51 | strerr_diefu1sys(111, "format") ; 52 | } 53 | if (r > 0) 54 | { 55 | if (!stralloc_catb(&dst, "\n", 1)) 56 | strerr_diefu1sys(111, "format") ; 57 | } 58 | if (buffer_put(buffer_1, dst.s, dst.len) < 0) 59 | strerr_diefu1sys(111, "write to stdout") ; 60 | } 61 | return 0 ; 62 | } 63 | -------------------------------------------------------------------------------- /doc/s6-sleep.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-sleep program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-sleep program

20 | 21 |

22 | s6-sleep sleeps for a given time, then optionally executes a program. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-sleep [ -m ] time [ prog... ]
29 | 
30 | 31 |
    32 |
  • s6-sleep acts as the generic 33 | sleep utility. 34 | It ignores non-lethal signals.
  • 35 |
  • If there are prog... arguments, then s6-sleep executes 36 | into prog... after sleeping. Else, it exits 0.
  • 37 |
38 | 39 |

Extra options

40 | 41 |
    42 |
  • -m : Interpret time as milliseconds instead of seconds.
  • 43 |
44 | 45 |

Posixness

46 | 47 |

48 | s6-sleep is suitable as a Single Unix 49 | sleep 50 | program. 51 |

52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-quote.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define USAGE "s6-quote [ -n ] [ -u ] [ -d delim ] string" 12 | 13 | int main (int argc, char const *const *argv) 14 | { 15 | stralloc sa = STRALLOC_ZERO ; 16 | char const *delim = "\"" ; 17 | size_t delimlen ; 18 | size_t startquote = 1 ; 19 | int nl = 1 ; 20 | PROG = "s6-quote" ; 21 | { 22 | subgetopt l = SUBGETOPT_ZERO ; 23 | for (;;) 24 | { 25 | int opt = subgetopt_r(argc, argv, "nud:", &l) ; 26 | if (opt == -1) break ; 27 | switch (opt) 28 | { 29 | case 'n' : nl = 0 ; break ; 30 | case 'u' : startquote = 0 ; break ; 31 | case 'd': delim = l.arg ; break ; 32 | default : strerr_dieusage(100, USAGE) ; 33 | } 34 | } 35 | argc -= l.ind ; argv += l.ind ; 36 | } 37 | if (!argc) strerr_dieusage(100, USAGE) ; 38 | delimlen = strlen(delim) ; 39 | if (startquote) 40 | { 41 | if (!delimlen) strerr_dief1x(100, "no character to quote with!") ; 42 | if (!stralloc_catb(&sa, delim, 1)) 43 | strerr_diefu1sys(111, "stralloc_catb") ; 44 | } 45 | if (!string_quote_nodelim_mustquote(&sa, *argv, strlen(*argv), delim, delimlen)) 46 | strerr_diefu1sys(111, "quote") ; 47 | if (startquote) 48 | { 49 | if (!stralloc_catb(&sa, delim, 1)) 50 | strerr_diefu1sys(111, "stralloc_catb") ; 51 | } 52 | if (nl) 53 | { 54 | if (!stralloc_catb(&sa, "\n", 1)) 55 | strerr_diefu1sys(111, "stralloc_catb") ; 56 | } 57 | if (allwrite(1, sa.s, sa.len) < sa.len) 58 | strerr_diefu1sys(111, "write to stdout") ; 59 | return 0 ; 60 | } 61 | -------------------------------------------------------------------------------- /doc/s6-nice.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-nice program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | www.skarnet.org 17 |

18 | 19 |

The s6-nice program

20 | 21 |

22 | s6-nice executes into a program with an altered nice value. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-nice [ -I | -i ] [ -n value ] [ prog... ]
29 | 
30 | 31 |

32 | s6-nice acts as the generic 33 | nice utility. 34 |

35 | 36 |

Extra options

37 | 38 |
    39 |
  • -I : loose. If the nice value cannot be set to value, 40 | print a warning message and exec into prog... anyway. This is the default.
  • 41 |
  • -i : strict. If the nice value cannot be set to value, 42 | exit 111 with an error message. 43 |
44 | 45 |

Posixness

46 | 47 |

48 | s6-nice is suitable as a Single Unix 49 | nice 50 | program. 51 |

52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /doc/s6-nuke.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-nuke program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-nuke program

20 | 21 |

22 | s6-nuke sends signals to every process it is allowed to send. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-nuke [ -h | -t | -k ]
29 | 
30 | 31 |
    32 |
  • Depending on the options it is given, s6-nuke sends signals to 33 | all processes; depending on s6-nuke's rights, not all processes may 34 | receive them.
  • 35 |
  • s6-nuke protects itself against the signals it sends (which 36 | doesn't do much good against SIGKILL). If it survives the blast, 37 | it exits 0.
  • 38 |
39 | 40 |

Options

41 | 42 |
    43 |
  • -h : send a SIGHUP
  • 44 |
  • -t : send a SIGTERM then a SIGCONT
  • 45 |
  • -k : send a SIGKILL
  • 46 |
47 | 48 |

Usage notes

49 | 50 |

51 | s6-nuke can be used during the shutdown procedure of a system, which is 52 | described 53 | here. 54 |

55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /doc/s6-clock.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-clock program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-clock program

20 | 21 |

22 | s6-clock gets or sets the system clock. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-clock [ label ]
29 | 
30 | 31 |

32 | When called without an argument, s6-clock writes the current system 33 | time, as a 34 | TAI64N 35 | timestamp, to stdout. 36 |

37 | 38 |

39 | When given an argument label, which must be a 40 | TAI64N 41 | timestamp, s6-clock sets the system time to this value. 42 |

43 | 44 |

Notes

45 | 46 |
    47 |
  • s6-clock only prints or accepts TAI time, no matter what the system clock is set 48 | to (TAI-10 or UTC); it will automatically make the right conversions for your 49 | system clock. Make sure your 50 | skalibs has been built with 51 | the right settings.
  • 52 |
53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /doc/s6-pause.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-pause program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-pause program

20 | 21 |

22 | s6-pause blocks until it is killed. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-pause [ -t ] [ -h ] [ -a ] [ -q ] [ -b ] [ -i ] [ -p signals ]
29 | 
30 | 31 |

Options

32 | 33 |
    34 |
  • -t : ignore SIGTERM
  • 35 |
  • -h : ignore SIGHUP
  • 36 |
  • -a : ignore SIGALRM
  • 37 |
  • -q : ignore SIGQUIT
  • 38 |
  • -b : ignore SIGABRT
  • 39 |
  • -i : ignore SIGINT
  • 40 |
  • -p signals : ignore the signals 41 | listed in signals, which must be a comma-separated list of 42 | signal numbers.
  • 43 |
44 | 45 |

Usage notes

46 | 47 |
    48 |
  • s6-pause is one of the smallest possible long-lived programs. It uses 49 | as few resources as the kernel will allow.
  • 50 |
  • The options can be used to wait for a specific signal without being 51 | killed by others.
  • 52 |
53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /doc/s6-ls.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-ls program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-ls program

20 | 21 |

22 | s6-ls lists the contents of a directory. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-ls [ -0 ] [ -a | -A ] [ -x exclude ] dir
29 | 
30 | 31 |

32 | s6-ls lists the contents of dir, one file per line. It 33 | omits files starting with a dot. 34 |

35 | 36 |

Options

37 | 38 |
    39 |
  • -0 : separate file names with a null character 40 | instead of a newline.
  • 41 |
  • -a : do not omit files starting with a dot. Do 42 | not list . or .. though.
  • 43 |
  • -A : do not omit files starting with a dot, even 44 | . and ..
  • 45 |
  • -x exclude : if a file name is 46 | exclude, do not print it.
  • 47 |
48 | 49 |

Posixness

50 | 51 |

52 | s6-ls is not suitable as a Single Unix 53 | ls 54 | program. 55 |

56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-seq.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define USAGE "s6-seq [ -w ] [ -s separator ] limits" 11 | #define dieusage() strerr_dieusage(100, USAGE) 12 | 13 | int main (int argc, char const *const *argv) 14 | { 15 | char const *sep = "\n" ; 16 | size_t fixed = 0, seplen = 1 ; 17 | unsigned int i = 1, increment = 1, last ; 18 | char fmt[UINT_FMT] ; 19 | PROG = "s6-seq" ; 20 | { 21 | subgetopt l = SUBGETOPT_ZERO ; 22 | for (;;) 23 | { 24 | int opt = subgetopt_r(argc, argv, "ws:", &l) ; 25 | if (opt == -1) break ; 26 | switch (opt) 27 | { 28 | case 'w': fixed = 1 ; break ; 29 | case 's': sep = l.arg ; seplen = strlen(sep) ; break ; 30 | default : dieusage() ; 31 | } 32 | } 33 | argc -= l.ind ; argv += l.ind ; 34 | } 35 | switch (argc) 36 | { 37 | case 1 : 38 | if (!uint0_scan(argv[0], &last)) dieusage() ; 39 | break ; 40 | case 2 : 41 | if (!uint0_scan(argv[0], &i) 42 | || !uint0_scan(argv[1], &last)) dieusage() ; 43 | break ; 44 | case 3 : 45 | if (!uint0_scan(argv[0], &i) 46 | || !uint0_scan(argv[1], &increment) 47 | || !uint0_scan(argv[2], &last)) dieusage() ; 48 | break ; 49 | default : dieusage() ; 50 | } 51 | if (!seplen) seplen = 1 ; 52 | if (fixed) fixed = uint_fmt(0, i + increment * ((last - i) / increment)) ; 53 | for (; i <= last ; i += increment) 54 | { 55 | if (buffer_put(buffer_1, fmt, fixed ? (uint0_fmt(fmt, i, fixed), fixed) : uint_fmt(fmt, i)) < 0) goto err ; 56 | if (buffer_put(buffer_1, sep, seplen) < 0) goto err ; 57 | } 58 | if (!buffer_flush(buffer_1)) goto err ; 59 | return 0 ; 60 | 61 | err: 62 | strerr_diefu1sys(111, "write to stdout") ; 63 | } 64 | -------------------------------------------------------------------------------- /doc/s6-head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-head program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-head program

20 | 21 |

22 | s6-head prints the first lines of its input files. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-head [ -S ] [ -1..9 | -n lines | -c chars ] file...
29 | 
30 | 31 |

32 | s6-head acts as the generic 33 | head utility. 34 |

35 | 36 |

Extra options

37 | 38 |
    39 |
  • -S : safe mode. s6-head stops reading its input files right after 40 | getting all the lines it needs. The rest of the stream can then be handled by other 41 | utilities without any data loss.
  • 42 |
  • -1..9 : equivalent to -n 1 .. -n 9.
  • 43 |
  • -c chars : cuts after chars characters instead 44 | of lines lines.
  • 45 |
46 | 47 |

Posixness

48 | 49 |

50 | s6-head is suitable as a Single Unix 51 | head 52 | program. 53 |

54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /doc/s6-chown.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-chown program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-chown program

20 | 21 |

22 | s6-chown changes the owner and/or group of a file. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-chown [ -U ] [ -u uid ] [ -g gid ] file
29 | 
30 | 31 |
    32 |
  • s6-chown changes file's owner to (numeric) uid and group 33 | to (numeric) gid.
  • 34 |
  • If uid isn't provided, the owner remains the same; if gid 35 | isn't provided, the group remains the same.
  • 36 |
  • The -U option sets uid to the value of the UID 37 | environment variable and gid to the value of the GID environment variable. 38 | This makes s6-chown easily usable with 39 | s6-envuidgid: 40 | s6-envuidgid account s6-chown -U file changes file's uid and 41 | gid to account's.
  • 42 |
43 | 44 |

Posixness

45 | 46 |

47 | s6-chown is not suitable as a Single Unix 48 | chown 49 | program. 50 |

51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /doc/s6-quote-filter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-quote-filter program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-quote-filter program

20 | 21 |

22 | s6-quote-filter acts as a filter, quoting lines it reads on stdin 23 | and writing the quoted lines to stdout. 24 |

25 | 26 |

Interface

27 | 28 |
29 |      s6-quote-filter [ -u ] [ -d delim ]
30 | 
31 | 32 |
    33 |
  • s6-quote reads lines on stdin; it quotes every line, putting it inside double quotes 34 | and escaping all dubious characters
  • 35 |
  • It writes the quoted strings to stdout
  • 36 |
  • It exits 0 on EOF
  • 37 |
38 | 39 |

Options

40 | 41 |
    42 |
  • -u : do not put read lines inside double quotes, only escape 43 | characters if needed
  • 44 |
  • -d delim : use the first character of delim 45 | as a quote character, instead of double quotes
  • 46 |
47 | 48 |

Notes

49 | 50 |
    51 |
  • Quoted strings are guaranteed to be pure printable ASCII, without control characters.
  • 52 |
  • Quoted strings can be unquoted via the s6-unquote or 53 | s6-unquote-filter programs.
  • 54 |
55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /doc/s6-sort.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-sort program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-sort program

20 | 21 |

22 | s6-sort sorts its input. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-sort [ -b ] [ -c ] [ -f ] [ -r ] [ -u ] [ -0 ]
29 | 
30 | 31 |
    32 |
  • s6-sort reads its stdin until EOF
  • 33 |
  • It sorts all the lines it read alphanumerically
  • 34 |
  • It prints the sorted lines to stdout and exits 0
  • 35 |
36 | 37 |

Options

38 | 39 |
    40 |
  • -b : ignore leading spaces and tabs at the beginning of each 41 | line when sorting
  • 42 |
  • -c : suppresses normal output, just returns 0 if the output 43 | would have been the same as the input and 1 otherwise
  • 44 |
  • -f : ignore case when sorting
  • 45 |
  • -r : reverse sort
  • 46 |
  • -u : suppresses duplicate lines
  • 47 |
  • -0 : input and output lines are separated by null characters 48 | instead of newlines
  • 49 |
50 | 51 |

Posixness

52 | 53 |

54 | s6-sort is not suitable as a Single Unix 55 | sort 56 | program. 57 |

58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /doc/s6-quote.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-quote program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-quote program

20 | 21 |

22 | s6-quote quotes a string and writes it to stdout. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-quote [ -n ] [ -u ] [ -d delim ] string
29 | 
30 | 31 |
    32 |
  • s6-quote quotes string, putting it inside double quotes 33 | and escaping all dubious characters
  • 34 |
  • It writes the quoted string to stdout and exits 0
  • 35 |
36 | 37 |

Options

38 | 39 |
    40 |
  • -n : do not print a trailing newline
  • 41 |
  • -u : do not put string inside double quotes, only escape 42 | characters if needed
  • 43 |
  • -d delim : use the first character of delim 44 | as a quote character, instead of double quotes
  • 45 |
46 | 47 |

Notes

48 | 49 |
    50 |
  • Quoted strings are guaranteed to be pure printable ASCII, without control characters.
  • 51 |
  • Quoted strings can be unquoted via the s6-unquote or 52 | s6-unquote-filter programs.
  • 53 |
  • Quoted strings are suitable for interpretation by 54 | execlineb.
  • 55 |
56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /doc/s6-unquote.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-unquote program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-unquote program

20 | 21 |

22 | s6-unquote unquotes a quoted string and writes it to stdout. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-unquote [ -n ] [ -d delim ] string
29 | 
30 | 31 |
    32 |
  • s6-unquote unquotes string, which must follow the 33 | syntax of s6-quote's output strings
  • 34 |
  • It prints various warning or error messages to stderr if it 35 | cannot unquote string properly
  • 36 |
  • If successful, it prints the result to stdout and exits 0
  • 37 |
38 | 39 |

Options

40 | 41 |
    42 |
  • -n : do not print a trailing newline.
  • 43 |
  • -d delim : a list of characters that 44 | will be considered as delimiters (to start and end the quoted string). 45 | By default, only the double quote is such a character. If delim 46 | is the empty string, s6-unquote interprets string as 47 | non-delimited, only escaped (i.e. the result of some 48 | s6-quote -u operation).
  • 49 |
50 | 51 |

Notes

52 | 53 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-quote-filter.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define USAGE "s6-quote-filter [ -u ] [ -d delim ]" 13 | 14 | int main (int argc, char const *const *argv) 15 | { 16 | stralloc src = STRALLOC_ZERO ; 17 | stralloc dst = STRALLOC_ZERO ; 18 | char const *delim = "\"" ; 19 | size_t delimlen ; 20 | size_t startquote = 1 ; 21 | PROG = "s6-quote-filter" ; 22 | { 23 | subgetopt l = SUBGETOPT_ZERO ; 24 | for (;;) 25 | { 26 | int opt = subgetopt_r(argc, argv, "ud:", &l) ; 27 | if (opt == -1) break ; 28 | switch (opt) 29 | { 30 | case 'u' : startquote = 0 ; break ; 31 | case 'd': delim = l.arg ; break ; 32 | default : strerr_dieusage(100, USAGE) ; 33 | } 34 | } 35 | argc -= l.ind ; argv += l.ind ; 36 | } 37 | delimlen = strlen(delim) ; 38 | if (startquote) 39 | { 40 | if(!delimlen) strerr_dief1x(100, "no character to quote with!") ; 41 | if (!stralloc_catb(&dst, delim, 1)) 42 | strerr_diefu1sys(111, "stralloc_catb") ; 43 | } 44 | for (;;) 45 | { 46 | int r ; 47 | src.len = 0 ; 48 | r = skagetln(buffer_0f1, &src, '\n') ; 49 | if (!r) break ; 50 | if ((r < 0) && (errno != EPIPE)) 51 | strerr_diefu1sys(111, "read from stdin") ; 52 | dst.len = startquote ; 53 | if (!string_quote_nodelim_mustquote(&dst, src.s, src.len - (r > 0), delim, delimlen)) 54 | { 55 | int e = errno ; 56 | buffer_flush(buffer_1) ; 57 | errno = e ; 58 | strerr_diefu1sys(111, "quote") ; 59 | } 60 | if (startquote) 61 | { 62 | if (!stralloc_catb(&dst, delim, 1)) 63 | strerr_diefu1sys(111, "stralloc_catb") ; 64 | } 65 | if (r > 0) 66 | { 67 | if (!stralloc_catb(&dst, "\n", 1)) 68 | strerr_diefu1sys(111, "stralloc_catb") ; 69 | } 70 | if (buffer_put(buffer_1, dst.s, dst.len) < 0) 71 | strerr_diefu1sys(111, "write to stdout") ; 72 | } 73 | return 0 ; 74 | } 75 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-tai64ndiff.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | int main (int argc, char const *const *argv) 16 | { 17 | stralloc sa = STRALLOC_ZERO ; 18 | tain prev ; 19 | int defined = 0 ; 20 | PROG = "s6-tai64ndiff" ; 21 | 22 | for (;;) 23 | { 24 | unsigned int p = 0 ; 25 | char prefix[23] = "[ . ]" ; 26 | int r = skagetln(buffer_0f1, &sa, '\n') ; 27 | if (r == -1) 28 | if (errno != EPIPE) 29 | strerr_diefu1sys(111, "read from stdin") ; 30 | else r = 1 ; 31 | else if (!r) break ; 32 | if (sa.len > TIMESTAMP) 33 | { 34 | tain cur ; 35 | p = timestamp_scan(sa.s, &cur) ; 36 | if (p) 37 | { 38 | if (defined) 39 | { 40 | tain diff ; 41 | int64_t secs ; 42 | size_t len ; 43 | tain_sub(&diff, &cur, &prev) ; 44 | secs = tai_sec(tain_secp(&diff)) ; 45 | len = int64_fmt(0, secs) ; 46 | if (len > 10) 47 | { 48 | char fmtn[9] ; 49 | size_t m = 1 + (len < 20) ; 50 | m += int64_fmt(prefix + m, secs) ; 51 | prefix[m++] = '.' ; 52 | uint320_fmt(fmtn, tain_nano(&diff), 9) ; 53 | memcpy(prefix + m, fmtn, 22 - m) ; 54 | } 55 | else 56 | { 57 | int64_fmt(prefix + 11 - len, secs) ; 58 | uint320_fmt(prefix + 12, tain_nano(&diff), 9) ; 59 | } 60 | } 61 | prev = cur ; 62 | defined = 1 ; 63 | if (buffer_put(buffer_1, prefix, 23) < 23) 64 | strerr_diefu1sys(111, "write to stdout") ; 65 | } 66 | else defined = 0 ; 67 | } 68 | else defined = 0 ; 69 | if (buffer_put(buffer_1, sa.s + p, sa.len - p) < (ssize_t)(sa.len - p)) 70 | strerr_diefu1sys(111, "write to stdout") ; 71 | sa.len = 0 ; 72 | } 73 | return 0 ; 74 | } 75 | -------------------------------------------------------------------------------- /doc/s6-portable-utils.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-portable-utils multicall binary 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-portable-utils multicall binary

20 | 21 |

22 | The s6-portable-utils program is only available when the 23 | --enable-multicall option has been given to the configure 24 | program at build time. In this configuration, s6-portable-utils is 25 | a multicall binary implementing the functionality of all 26 | the programs in the s6-portable-utils package; and the other programs, instead 27 | of being executables of their own, are symbolic links to the 28 | s6-portable-utils binary. 29 |

30 | 31 |

Interface

32 | 33 |
34 |      s6-portable-utils subcommand subcommand_arguments...
35 | 
36 | 37 |

38 | s6-portable-utils will run the subcommand with its arguments. For 39 | instance, s6-portable-utils s6-seq 1 10 will run the equivalent of the 40 | s6-seq program, so this command will list natural numbers 41 | from 1 to 10. 42 |

43 | 44 |

45 | Alternatively, if s6-portable-utils is called with the name of an existing 46 | command, it will run the equivalent of that command. For instance, 47 | if the /usr/bin/s6-seq file is a (hard or symbolic) link to 48 | the s6-portable-utils binary, /usr/bin/s6-seq 1 10 will list 49 | natural numbers from 1 to 10. 50 |

51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-dumpenv.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define USAGE "s6-dumpenv [ -N | -n ] [ -m mode ] envdir" 15 | #define dieusage() strerr_dieusage(100, USAGE) 16 | 17 | int main (int argc, char const *const *argv, char const *const *envp) 18 | { 19 | unsigned int mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH ; 20 | int chomp = 0 ; 21 | size_t dirlen ; 22 | PROG = "s6-dumpenv" ; 23 | { 24 | subgetopt l = SUBGETOPT_ZERO ; 25 | for (;;) 26 | { 27 | int opt = subgetopt_r(argc, argv, "nNm:", &l) ; 28 | if (opt == -1) break ; 29 | switch (opt) 30 | { 31 | case 'n' : chomp = 0 ; break ; 32 | case 'N' : chomp = 1 ; break ; 33 | case 'm' : if (!uint0_oscan(l.arg, &mode)) dieusage() ; break ; 34 | default : dieusage() ; 35 | } 36 | } 37 | argc -= l.ind ; argv += l.ind ; 38 | } 39 | if (!argc) dieusage() ; 40 | 41 | if (mkdir(argv[0], mode) < 0) 42 | { 43 | struct stat st ; 44 | if (errno != EEXIST) strerr_diefu2sys(111, "mkdir ", argv[0]) ; 45 | if (stat(argv[0], &st) < 0) 46 | strerr_diefu2sys(111, "stat ", argv[0]) ; 47 | if (!S_ISDIR(st.st_mode)) 48 | { 49 | errno = ENOTDIR ; 50 | strerr_diefu2sys(111, "mkdir ", argv[0]) ; 51 | } 52 | } 53 | dirlen = strlen(argv[0]) ; 54 | 55 | for (; *envp ; envp++) 56 | { 57 | size_t varlen = str_chr(*envp, '=') ; 58 | struct iovec const v[2] = 59 | { 60 | { .iov_base = (char *)*envp + varlen + 1, .iov_len = strlen(*envp + varlen + 1) }, 61 | { .iov_base = "\n", .iov_len = 1 } 62 | } ; 63 | char fn[dirlen + varlen + 2] ; 64 | memcpy(fn, argv[0], dirlen) ; 65 | fn[dirlen] = '/' ; 66 | memcpy(fn + dirlen + 1, *envp, varlen) ; 67 | fn[dirlen + 1 + varlen] = 0 ; 68 | if (!openwritevnclose_suffix(fn, v, 1 + chomp, "=.tmp")) 69 | strerr_diefu2sys(111, "open ", fn) ; 70 | } 71 | return 0 ; 72 | } 73 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-unquote.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define USAGE "s6-unquote [ -n ] [ -d delim ] string" 12 | 13 | int main (int argc, char const *const *argv) 14 | { 15 | char const *delim = "\"" ; 16 | char const *string ; 17 | size_t len, delimlen ; 18 | int nl = 1 ; 19 | PROG = "s6-unquote" ; 20 | { 21 | subgetopt l = SUBGETOPT_ZERO ; 22 | for (;;) 23 | { 24 | int opt = subgetopt_r(argc, argv, "nd:", &l) ; 25 | if (opt == -1) break ; 26 | switch (opt) 27 | { 28 | case 'n' : nl = 0 ; break ; 29 | case 'd': delim = l.arg ; break ; 30 | default : strerr_dieusage(100, USAGE) ; 31 | } 32 | } 33 | argc -= l.ind ; argv += l.ind ; 34 | } 35 | if (!argc) strerr_dieusage(100, USAGE) ; 36 | string = *argv ; 37 | len = strlen(string) ; 38 | delimlen = strlen(delim) ; 39 | if (delimlen) 40 | { 41 | if (!len--) strerr_dief1x(100, "the empty string isn't a quoted string") ; 42 | if (!memchr(delim, *string++, delimlen)) 43 | strerr_dief1x(100, "invalid starting quote character") ; 44 | } 45 | { 46 | size_t r = 0, w = 0 ; 47 | char buf[len+1] ; 48 | if (!string_unquote_withdelim(buf, &w, string, len, &r, delim, delimlen)) 49 | { 50 | char fmt[SIZE_FMT] ; 51 | fmt[size_fmt(fmt, r + !!delimlen)] = 0 ; 52 | strerr_diefu2sys(100, "unquote at character ", fmt) ; 53 | } 54 | if (delimlen) 55 | { 56 | if (r == len) strerr_dief1x(100, "no ending quote character") ; 57 | else if (r < len - 1) 58 | { 59 | char fmtnum[SIZE_FMT] ; 60 | char fmtden[SIZE_FMT] ; 61 | fmtnum[size_fmt(fmtnum, r+1)] = 0 ; 62 | fmtden[size_fmt(fmtden, len)] = 0 ; 63 | strerr_warnw5x("found ending quote character at position ", fmtnum, "/", fmtden, "; ignoring remainder") ; 64 | } 65 | } 66 | if (nl) buf[w++] = '\n' ; 67 | if (allwrite(1, buf, w) < w) 68 | strerr_diefu1sys(111, "write to stdout") ; 69 | } 70 | return 0 ; 71 | } 72 | -------------------------------------------------------------------------------- /doc/s6-dumpenv.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-dumpenv program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-dumpenv program

20 | 21 |

22 | s6-dumpenv stores its environment variables into a directory. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-dumpenv [ -N | -n ] [ -m mode ] dir
29 | 
30 | 31 |
    32 |
  • s6-dumpenv creates the directory dir if it does not exist 33 | yet.
  • 34 |
  • For every environment variable x with value y 35 | that it has, it creates a file dir/x containing 36 | y.
  • 37 |
  • It then exits 0.
  • 38 |
39 | 40 |

Options

41 | 42 |
    43 |
  • -N : chomp. Write the environment variables with an 44 | extra newline at the end, so the environment can be retrieved via 45 | s6-envdir -Lf dir.
  • 46 |
  • -n : Write the environment variables as is; the 47 | environment will be retrieved via s6-envdir -Lfn dir. 48 | This is the default.
  • 49 |
  • -m mode : create dir with 50 | mode mode if it doesn't exist yet. Default is 0755.
  • 51 |
52 | 53 |

Notes

54 | 55 |
    56 |
  • A program prog can be run with the environment in dir 57 | by using s6-envdir 58 | -fn -- dir prog.
  • 59 |
60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-mkdir.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define USAGE "s6-mkdir [ -p ] [ -v ] [ -m mode ] dir" 14 | #define dieusage() strerr_dieusage(100, USAGE) 15 | 16 | static int mkdir_doit (char const *s, unsigned int mode, int verbose, int ee) 17 | { 18 | if (mkdir(s, mode) == -1) 19 | { 20 | if (ee || (errno != EEXIST)) 21 | { 22 | strerr_warnwu2sys("mkdir ", s) ; 23 | return 111 ; 24 | } 25 | } 26 | else if (verbose) 27 | { 28 | buffer_puts(buffer_2, PROG) ; 29 | buffer_puts(buffer_2, ": created directory ") ; 30 | buffer_puts(buffer_2, s) ; 31 | buffer_putflush(buffer_2, "\n", 1) ; 32 | } 33 | return 0 ; 34 | } 35 | 36 | static int mkdir_doparents (char const *s, unsigned int mode, int verbose) 37 | { 38 | size_t n = strlen(s), i = 0 ; 39 | char tmp[n+1] ; 40 | for (; i < n ; i++) 41 | { 42 | if ((s[i] == '/') && i) 43 | { 44 | int e ; 45 | tmp[i] = 0 ; 46 | e = mkdir_doit(tmp, mode, verbose, 0) ; 47 | if (e) return e ; 48 | } 49 | tmp[i] = s[i] ; 50 | } 51 | return mkdir_doit(s, mode, verbose, 0) ; 52 | } 53 | 54 | int main (int argc, char const *const *argv) 55 | { 56 | int parents = 0, verbose = 0 ; 57 | unsigned int mode = 0777 ; 58 | int e = 0 ; 59 | int noumask = 0 ; 60 | PROG = "s6-mkdir" ; 61 | { 62 | subgetopt l = SUBGETOPT_ZERO ; 63 | for (;;) 64 | { 65 | int opt = subgetopt_r(argc, argv, "pvm:", &l) ; 66 | if (opt == -1) break ; 67 | switch (opt) 68 | { 69 | case 'p': parents = 1 ; break ; 70 | case 'v': verbose = 1 ; break ; 71 | case 'm': if (!uint_oscan(l.arg, &mode)) dieusage() ; noumask = 1 ; break ; 72 | default : strerr_dieusage(100, USAGE) ; 73 | } 74 | } 75 | argc -= l.ind ; argv += l.ind ; 76 | } 77 | if (noumask) umask(0) ; 78 | for ( ; *argv ; argv++) 79 | e |= parents ? mkdir_doparents(*argv, mode, verbose) : 80 | mkdir_doit(*argv, mode, verbose, 1) ; 81 | return e ; 82 | } 83 | -------------------------------------------------------------------------------- /doc/s6-seq.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-seq program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-seq program

20 | 21 |

22 | s6-seq prints a sequence of numbers. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-seq [ -w ] [ -s separator ] limits
29 | 
30 | 31 |
    32 |
  • limits can be one, two or three arguments. 33 |
      34 |
    • Three arguments are interpreted as first, 35 | increment and last, in this order.
    • 36 |
    • Two arguments are interpreted as first and 37 | last, and increment defaults to 1.
    • 38 |
    • One argument is interpreted as last, and 39 | first and increment both default to 1.
    • 40 |
  • 41 |
  • s6-seq prints all unsigned integers from first 42 | to last inclusive, with a step of increment, 43 | with a newline after each integer. 44 | It then exits 0.
  • 45 |
46 | 47 |

Options

48 | 49 |
    50 |
  • -w : fixed width. The numbers will all be printed 51 | with the same width; smaller numbers will have leading 0 52 | characters.
  • 53 |
  • -s sep : print sep after 54 | each number. Default is a newline. If sep 55 | is the empty string, a null character will be printed.
  • 56 |
57 | 58 |

Notes

59 | 60 |

61 | s6-seq is similar to the GNU seq program. However, it 62 | does not handle negative numbers, floating point numbers or 63 | printf-style formatting. 64 |

65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /doc/s6-maximumtime.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-maximumtime program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-maximumtime program

20 | 21 |

22 | s6-maximumtime executes a program with a time limit. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-maximumtime [ -0 | -a | -b | -i | -k | -q | -t | -x | -1 | -2 ] milli prog...
29 | 
30 | 31 |
    32 |
  • s6-maximumtime forks and execs prog... as a child.
  • 33 |
  • If milli milliseconds elapse before prog exits, 34 | s6-maximumtime sends it a signal and exits 99 with a message.
  • 35 |
  • Else s6-maximumtime exits with the same exit code as prog.
  • 36 |
37 | 38 |

Options

39 | 40 |
    41 |
  • -0 : on timeout, do not send any signal, just exit
  • 42 |
  • -a : on timeout, send a SIGALRM
  • 43 |
  • -b : on timeout, send a SIGABRT
  • 44 |
  • -i : on timeout, send a SIGINT
  • 45 |
  • -k : on timeout, send a SIGKILL
  • 46 |
  • -q : on timeout, send a SIGQUIT
  • 47 |
  • -t : on timeout, send a SIGTERM - this is the default
  • 48 |
  • -x : on timeout, send a SIGXCPU
  • 49 |
  • -1 : on timeout, send a SIGUSR1
  • 50 |
  • -2 : on timeout, send a SIGUSR2
  • 51 |
52 | 53 |

Notes

54 | 55 |
    56 |
  • If milli is 0, then it's interpreted as infinite: no time 57 | limit will be enforced.
  • 58 |
59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /doc/s6-ln.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-ln program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-ln program

20 | 21 |

22 | s6-ln creates a link to a file. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-ln [ -n ] [ -s ] [ -f ] [ -L ] [ -P ] source... target
29 | 
30 | 31 |

32 | s6-ln acts as the generic 33 | ln utility. 34 |

35 | 36 |

Options

37 | 38 |
    39 |
  • -s : create a symbolic link instead of a hard link
  • 40 |
  • -f : force replacement of an existing target
  • 41 |
  • -L : link targets of symlinks in source...
  • 42 |
  • -P : link symlinks in source... themselves
  • 43 |
  • -n : if target is a symlink to a directory, replace 44 | it instead of adding a link in the directory
  • 45 |
46 | 47 |

Posixness

48 | 49 |

50 | s6-ln would be suitable as a Single Unix 51 | ln 52 | program, except that POSIX mandates that a preexisting target must first 53 | be unlink()ed and then (sym)link()ed, which prevents 54 | atomic replacements. 55 | s6-ln aims to be reliable and allow for atomic replacements, so it 56 | deviates from POSIX on that point: when target exists and needs to 57 | be replaced, s6-ln first creates a (sym)link to a unique temporary 58 | name, then rename()s the temporary name to target. This 59 | behaviour makes sure that target is atomically replaced - there's 60 | no point in time where it does not exist. 61 |

62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /doc/s6-tai64ndiff.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-tai64ndiff program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-tai64ndiff program

20 | 21 |

22 | s6-tai64ndiff acts as a filter, reading from stdin and writing to stdout. 23 | It expects every line of its input to begin with a 24 | TAI64N 25 | timestamp. It replaces this timestamp with a prefix showing the time 26 | difference between this line and the previous line. 27 |

28 | 29 |

Interface

30 | 31 |
32 |      s6-tai64ndiff
33 | 
34 | 35 |
    36 |
  • s6-tai64ndiff exits 0 when it sees the end of stdin. If there's an 37 | unfinished line, s6-tai64ndiff processes it and writes it before exiting.
  • 38 |
  • The prefix it prints is of the form [ seconds.microseconds ], 39 | in decimal. It can be interpreted as a fixed-point decimal number of seconds that 40 | elapsed between the timestamp on the previous line and the timestamp on the 41 | current line.
  • 42 |
  • If the difference isn't defined, seconds and microseconds 43 | are just whitespace. The difference is not defined on the first line of stdin or 44 | on non-timestamped lines. Following non-timestamped lines, the difference may not 45 | be accurate.
  • 46 |
47 | 48 |

Notes

49 | 50 |
    51 |
  • The typical use case of s6-tai64ndiff is to read files that have 52 | been filtered through s6-tai64n, or log files 53 | that have been produced by s6-log with the t 54 | directive.
  • 55 |
  • The difference is a signed number. Negative numbers probably indicate 56 | a backwards clock jump, which is a bad thing to have on a system.
  • 57 |
58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /tools/gen-dotpc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | isunique () { 4 | x=$1 5 | set -- $2 6 | while test "$#" -gt 0 ; do 7 | if test "$x" = "$1" ; then 8 | return 1 9 | fi 10 | shift 11 | done 12 | return 0 13 | } 14 | 15 | uniqit () { 16 | res= 17 | while test "$#" -gt 0 ; do 18 | if isunique "$1" "$res" ; then 19 | res="${res}${res:+ }${1}" 20 | fi 21 | shift 22 | done 23 | printf %s\\n "$res" 24 | } 25 | 26 | filterout () { 27 | res= 28 | filter="$1" 29 | shift 30 | while test "$#" -gt 0 ; do 31 | if isunique "$1" "$filter" ; then 32 | res="${res}${res:+ }${1}" 33 | fi 34 | shift 35 | done 36 | printf %s\\n "$res" 37 | } 38 | 39 | print_requires () { 40 | line= 41 | oldifs="$IFS" 42 | while IFS=" " read condvar usedinlibs pkg ver libs ; do 43 | IFS="$oldifs" 44 | for h ; do 45 | i=lib${h##-l} 46 | for j in $libs ; do 47 | if test "$i" = "$j" ; then 48 | line="${line}${line:+, }${i} >= ${ver}" 49 | fi 50 | done 51 | done 52 | done < package/deps-build 53 | IFS="$oldifs" 54 | echo "Requires: $line" 55 | } 56 | 57 | . package/info 58 | 59 | ilist= 60 | dlist= 61 | slist= 62 | 63 | if test "${includedir}" != /usr/include ; then 64 | ilist="-I${includedir}" 65 | fi 66 | if test -n "${extra_includedirs}" ; then 67 | ilist="${ilist}${ilist:+ }${extra_includedirs}" 68 | fi 69 | ilist=`uniqit ${ilist}` 70 | 71 | if test "${dynlibdir}" != /usr/lib && test "${dynlibdir}" != /lib ; then 72 | dlist="-L${dynlibdir}" 73 | fi 74 | 75 | if test "${libdir}" != /usr/lib && test "${libdir}" != /lib ; then 76 | slist="-L${libdir}" 77 | fi 78 | if test -n "${extra_libdirs}" ; then 79 | slist="${slist}${slist:+ }${extra_libdirs}" 80 | fi 81 | slist="$(filterout "${dlist}" $(uniqit ${slist}))" 82 | 83 | echo "prefix=${prefix}" 84 | echo "includedir=${includedir}" 85 | echo "libdir=${libdir}" 86 | echo "dynlibdir=${dynlibdir}" 87 | echo 88 | echo "Name: lib${library}" 89 | echo "Version: ${version}" 90 | echo "Description: ${description:-The ${library} library.}" 91 | echo "URL: ${url:-https://skarnet.org/software/${package}/}" 92 | if test -n "${extra_libs}" ; then 93 | print_requires ${extra_libs} 94 | fi 95 | if test -n "$ilist" ; then 96 | echo "Cflags: ${ilist}" 97 | fi 98 | echo "Libs: ${dlist}${dlist:+ }-l${library}${ldlibs:+ }${ldlibs}" 99 | if test -n "${extra_libs}" ; then 100 | echo "Libs.private: ${slist}${slist:+ }${extra_libs}" 101 | fi 102 | -------------------------------------------------------------------------------- /doc/s6-grep.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-grep program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-grep program

20 | 21 |

22 | s6-grep matches its input against a pattern. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-grep [ -E | -F ] [ -i ] [ -c ] [ -n ] [ -q ] [ -v ] pattern
29 | 
30 | 31 |
    32 |
  • s6-grep compiles pattern as a 33 | Basic 34 | Regular Expression
  • 35 |
  • It reads stdin and matches every line against this regexp
  • 36 |
  • If the line matches, it prints it to stdout
  • 37 |
  • It exits on EOF with code 0 if one or more lines matched and 1 38 | otherwise.
  • 39 |
40 | 41 |

Options

42 | 43 |
    44 |
  • -F : pattern is not compiled as a BRE, but is 45 | interpreted as a literal string.
  • 46 |
  • -E : pattern is not compiled as a BRE, but as an 47 | Extended 48 | Regular Expression (ERE).
  • 49 |
  • -i : ignore case during the match
  • 50 |
  • -c : do not write normal output; only write the number of 51 | lines that have matched pattern after EOF is received
  • 52 |
  • -n : precede every output line by its number and a colon. 53 | The first input line has number 1.
  • 54 |
  • -q : do not write anything to stdout
  • 55 |
  • -v : invert the pattern matching (select lines that do not 56 | match pattern).
  • 57 |
58 | 59 |

Posixness

60 | 61 |

62 | s6-grep is not suitable as a Single Unix 63 | grep 64 | program. 65 |

66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /tools/gen-multicall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | LC_ALL=C ; export LC_ALL 4 | 5 | P="$1" 6 | p=`echo $P | tr - _` 7 | 8 | echo '/* ISC license. */' 9 | echo 10 | echo '#include ' 11 | echo 12 | { echo '#include ' ; echo '#include ' ; cat src/$P/*.c | grep '^#include <' | grep -vF ' 17 | 18 | #include <$P/config.h> 19 | 20 | typedef int emain_func (int, char const *const *, char const *const *) ; 21 | typedef emain_func *emain_func_ref ; 22 | 23 | typedef struct multicall_app_s multicall_app, *multicall_app_ref ; 24 | struct multicall_app_s 25 | { 26 | char const *name ; 27 | emain_func_ref mainf ; 28 | } ; 29 | 30 | static int multicall_app_cmp (void const *a, void const *b) 31 | { 32 | char const *name = a ; 33 | multicall_app const *p = b ; 34 | return strcmp(name, p->name) ; 35 | } 36 | EOF 37 | 38 | for i in `ls -1 src/$P/deps-exe` ; do 39 | j=`echo $i | tr - _` 40 | echo 41 | grep -v '^#include ' < src/$P/${i}.c | grep -vF '/* ISC license. */' | sed -e "s/int main (.*)$/int ${j}_main (int argc, char const *const *argv, char const *const *envp)/" 42 | echo 43 | echo '#undef USAGE' 44 | echo '#undef dieusage' 45 | echo '#undef dienomem' 46 | echo '#undef bail' 47 | done 48 | 49 | cat <mainf))(argc-1, argv+1, envp) ; 76 | } 77 | 78 | int main (int argc, char const *const *argv, char const *const *envp) 79 | { 80 | multicall_app const *p ; 81 | char const *name = strrchr(argv[0], '/') ; 82 | if (name) name++ ; else name = argv[0] ; 83 | p = bsearch(name, multicall_apps, sizeof(multicall_apps) / sizeof(multicall_app), sizeof(multicall_app), &multicall_app_cmp) ; 84 | return p ? (*(p->mainf))(argc, argv, envp) : ${p}_main(argc, argv, envp) ; 85 | } 86 | EOF 87 | -------------------------------------------------------------------------------- /doc/s6-unquote-filter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-unquote-filter program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-unquote-filter program

20 | 21 |

22 | s6-unquote acts as a filter, reading quoted strings on stdin, 23 | unquoting them and writing the results to stdout. 24 |

25 | 26 |

Interface

27 | 28 |
29 |      s6-unquote-filter [ -q | -Q | -v | -w ] [ -d delim ]
30 | 
31 | 32 |
    33 |
  • s6-unquote-filter reads lines on stdin. It exits 0 on EOF.
  • 34 |
  • It expects read lines to follow the 35 | syntax of s6-quote's output strings
  • 36 |
  • Depending on the strictness options, it prints various warning 37 | or error messages to stderr if it cannot properly unquote lines. In 38 | the very strict mode, it exits 100 on the first unquoting error.
  • 39 |
  • If it is successful at unquoting, it prints the resulting 40 | lines to stdout.
  • 41 |
42 | 43 |

Options

44 | 45 |
    46 |
  • -d delim : a list of characters that 47 | will be considered as delimiters (to start and end the quoted string). 48 | By default, only the double quote is such a character. If delim 49 | is the empty string, s6-unquote-filter interprets string as 50 | non-delimited, only escaped (i.e. for instance the result of some 51 | s6-quote-filter -u operation).
  • 52 |
  • -q : loose/quiet mode. s6-unquote-filter will 53 | silently accommodate errors.
  • 54 |
  • -Q : normal mode. This is the default. s6-unquote-filter 55 | will warn on errors.
  • 56 |
  • -v : strict/verbose mode. s6-unquote-filter will 57 | warn loudly on errors, with many details.
  • 58 |
  • -w : very strict mode. s6-unquote-filter will complain 59 | and die on the first unquoting error it encounters.
  • 60 |
61 | 62 |

Notes

63 | 64 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /doc/s6-hiercopy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-hiercopy program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-hiercopy program

20 | 21 |

22 | s6-hiercopy copies a directory structure recursively. 23 |

24 | 25 |

Interface

26 | 27 |
28 |      s6-hiercopy source destination
29 | 
30 | 31 |
    32 |
  • s6-hiercopy recursively copies source to 33 | destination, which is created if it doesn't exist. 34 | The permissions are preserved. The owner and group are preserved 35 | if the user is the superuser.
  • 36 |
  • It exits 0 on success and 111 on temporary failure.
  • 37 |
38 | 39 |

Notes

40 | 41 |
    42 |
  • Copying files and browsing through directories is one of Unix's 43 | weakest points, and s6-hiercopy is not meant to work around 44 | the problem; it's only a quick hack that I needed to boot my embedded 45 | platform. I originally planned to write the ultimate cp utility, 46 | portable and reliable and featureful and everything - while needing 47 | approximately a hundred times less resources than GNU cp does, 48 | of course. But I eventually dropped the idea: it's impossible to 49 | design, much less write, such a utility. Notably, 50 | you cannot make it reliable because Unix's set of filesystem 51 | management primitives is just too weak. It lacks a lot of atomic 52 | operations, and filesystem transactions. As a result, s6-hiercopy 53 | is a walking race condition and should absolutely not 54 | be considered instant when used in a multitasking environment. 55 | But then, cp shouldn't either.
  • 56 |
  • There is no standard way of creating device nodes on a 57 | filesystem, so any cp-like utility is inherently 58 | non-portable. Fortunately, most systems still agree on the non-portable usages of the 59 | mknod 60 | specification, so things should work in practice. Consequently, 61 | the s6-hiercopy utility has been moved from 62 | s6-linux-utils 63 | to s6-portable-utils.
  • 64 |
65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | Changelog for s6-portable-utils. 2 | 3 | In 2.3.1.1 4 | ---------- 5 | 6 | - Support for shared libraries on MacOS. 7 | 8 | 9 | In 2.3.1.0 10 | ---------- 11 | 12 | - Bugfixes. 13 | - pkg-config support. 14 | 15 | 16 | In 2.3.0.4 17 | ---------- 18 | 19 | - Align configure defaults to the rest of skaware. 20 | 21 | 22 | In 2.3.0.3 23 | ---------- 24 | 25 | - Adaptation to skalibs-2.14.0.0. 26 | - Bugfixes. 27 | 28 | 29 | In 2.3.0.2 30 | ---------- 31 | 32 | - Bugfixes. 33 | 34 | 35 | In 2.3.0.1 36 | ---------- 37 | 38 | - Bugfixes. 39 | 40 | 41 | In 2.3.0.0 42 | ---------- 43 | 44 | - s6-test removed. 45 | - New multicall binary: s6-portable-utils. 46 | 47 | 48 | In 2.2.5.1 49 | ---------- 50 | 51 | - Bugfixes. 52 | - Adaptation to skalibs-2.13.0.0. 53 | - s6-test is now deprecated: replaced with execline's eltest. 54 | 55 | 56 | In 2.2.5.0 57 | ---------- 58 | 59 | - Adaptation to skalibs-2.12.0.0. 60 | 61 | 62 | In 2.2.4.0 63 | ---------- 64 | 65 | - New -N option to s6-dumpenv, for chomping retrieval. 66 | 67 | 68 | In 2.2.3.4 69 | ---------- 70 | 71 | - Bugfixes. 72 | 73 | 74 | In 2.2.3.3 75 | ---------- 76 | 77 | - Adaptation to skalibs-2.11.0.0. 78 | 79 | 80 | In 2.2.3.2 81 | ---------- 82 | 83 | - Bugfixes. 84 | 85 | 86 | In 2.2.3.1 87 | ---------- 88 | 89 | - Version that works with skalibs-2.10.0.0. 90 | 91 | 92 | In 2.2.3.0 93 | ---------- 94 | 95 | - Bugfixes that have nothing to do with 2.2.2.4 but that 96 | were reported *right after* 2.2.2.4 was released, because 97 | things do be like that 98 | - New binary: s6-tai64ndiff 99 | 100 | 101 | In 2.2.2.4 102 | ---------- 103 | 104 | - Bugfixes of the bugs introduced in the previous bugfixes 105 | (that's what all software development is about, isn't it?) 106 | 107 | 108 | In 2.2.2.3 109 | ---------- 110 | 111 | - Bugfixes. 112 | 113 | 114 | In 2.2.2.2 115 | ---------- 116 | 117 | - Bugfixes. 118 | 119 | 120 | In 2.2.2.1 121 | ---------- 122 | 123 | - Bugfixes. 124 | 125 | 126 | In 2.2.2.0 127 | ---------- 128 | 129 | - Adaptation to skalibs-2.9.0.0. 130 | 131 | 132 | In 2.2.1.3 133 | ---------- 134 | 135 | - s6-ln doesn't use potentially blocking random anymore, so it's 136 | usable in early boot. This needs skalibs-2.8.0.0, however. 137 | - Everything now builds as PIC by default. 138 | 139 | 140 | In 2.2.1.2 141 | ---------- 142 | 143 | - Adaptation to skalibs-2.7.0.0. 144 | 145 | 146 | In 2.2.1.1 147 | ---------- 148 | 149 | - Bugfix release. 150 | - Adaptation to skalibs-2.6.0.0. 151 | 152 | 153 | In 2.2.1.0 154 | ---------- 155 | 156 | - s6-ln now accepts the non-standard -n option, with a meaning 157 | similar to the one in GNU ln. This is used to atomically update 158 | symbolic links to directories. 159 | 160 | 161 | In 2.2.0.0 162 | ---------- 163 | 164 | - Added this NEWS file. :) 165 | - Major types overhaul to make them more POSIXly correct: 166 | compatibility with skalibs-2.5.0.0. 167 | 168 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-maximumtime.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define USAGE "s6-maximumtime [ -0 | -a | -b | -i | -k | -q | -t | -x | -1 | -2 ] milliseconds prog..." 20 | 21 | int main (int argc, char const *const *argv, char const *const *envp) 22 | { 23 | tain deadline ; 24 | iopause_fd x[1] = { { .fd = -1, .events = IOPAUSE_READ, .revents = 0 } } ; 25 | pid_t pid = 0 ; 26 | int tosend = SIGTERM ; 27 | unsigned int timeout ; 28 | PROG = "s6-maximumtime" ; 29 | { 30 | subgetopt l = SUBGETOPT_ZERO ; 31 | for (;;) 32 | { 33 | int opt = subgetopt_r(argc, argv, "0abikqtx12", &l) ; 34 | if (opt == -1) break ; 35 | switch (opt) 36 | { 37 | case '0': tosend = 0 ; break ; 38 | case 'a': tosend = SIGALRM ; break ; 39 | case 'b': tosend = SIGABRT ; break ; 40 | case 'i': tosend = SIGINT ; break ; 41 | case 'k': tosend = SIGKILL ; break ; 42 | case 'q': tosend = SIGQUIT ; break ; 43 | case 't': tosend = SIGTERM ; break ; 44 | case 'x': tosend = SIGXCPU ; break ; 45 | case '1': tosend = SIGUSR1 ; break ; 46 | case '2': tosend = SIGUSR2 ; break ; 47 | default : strerr_dieusage(100, USAGE) ; 48 | } 49 | } 50 | argc -= l.ind ; argv += l.ind ; 51 | } 52 | 53 | if ((argc < 2) || !uint0_scan(argv[0], &timeout)) strerr_dieusage(100, USAGE) ; 54 | if (timeout) tain_from_millisecs(&deadline, timeout) ; 55 | else deadline = tain_infinite_relative ; 56 | 57 | x[0].fd = selfpipe_init() ; 58 | if (x[0].fd < 0) strerr_diefu1sys(111, "selfpipe_init") ; 59 | 60 | if (!selfpipe_trap(SIGCHLD)) strerr_diefu1sys(111, "selfpipe_trap") ; 61 | 62 | pid = cspawn(argv[1], argv+1, envp, CSPAWN_FLAGS_SELFPIPE_FINISH, 0, 0) ; 63 | if (!pid) strerr_diefu2sys(111, "spawn ", argv[1]) ; 64 | tain_now_set_stopwatch_g() ; 65 | tain_add_g(&deadline, &deadline) ; 66 | 67 | for (;;) 68 | { 69 | int r = iopause_g(x, 1, &deadline) ; 70 | if (r < 0) strerr_diefu1sys(111, "iopause") ; 71 | if (!r) break ; 72 | if (x[0].revents & IOPAUSE_READ) 73 | { 74 | int cont = 1 ; 75 | while (cont) 76 | { 77 | switch (selfpipe_read()) 78 | { 79 | case -1 : strerr_diefu1sys(111, "selfpipe_read") ; 80 | case 0 : cont = 0 ; break ; 81 | case SIGCHLD : 82 | { 83 | int wstat ; 84 | if (wait_pid_nohang(pid, &wstat) == pid) 85 | { 86 | if (WIFSIGNALED(wstat)) 87 | strerr_diew1x(111, "child process crashed") ; 88 | else return WEXITSTATUS(wstat) ; 89 | } 90 | } 91 | default : strerr_diefu1x(101, "internal error, please submit a bug-report.") ; 92 | } 93 | } 94 | } 95 | } 96 | kill(pid, tosend) ; 97 | errno = ETIMEDOUT ; 98 | strerr_diewu1sys(99, "wait for child process") ; 99 | } 100 | -------------------------------------------------------------------------------- /tools/gen-deps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | . package/info 4 | 5 | echo '#' 6 | echo '# This file has been generated by tools/gen-deps.sh' 7 | echo '#' 8 | echo 9 | 10 | internal_libs= 11 | 12 | for dir in src/include/${package} src/* ; do 13 | for file in $(ls -1 $dir | grep -- \\.h$) ; do 14 | { 15 | grep -F -- "#include <${package}/" < ${dir}/$file | cut -d'<' -f2 | cut -d'>' -f1 ; 16 | grep -- '#include ".*\.h"' < ${dir}/$file | cut -d'"' -f2 17 | } | sort -u | { 18 | deps= 19 | while read dep ; do 20 | if echo $dep | grep -q "^${package}/" ; then 21 | deps="$deps src/include/$dep" 22 | elif test -f "${dir}/$dep" ; then 23 | deps="$deps ${dir}/$dep" 24 | else 25 | deps="$deps src/include-local/$dep" 26 | fi 27 | done 28 | if test -n "$deps" ; then 29 | echo "${dir}/${file}:${deps}" 30 | fi 31 | } 32 | done 33 | done 34 | 35 | for dir in src/* ; do 36 | for file in $(ls -1 $dir | grep -- \\.c$) ; do 37 | { 38 | grep -F -- "#include <${package}/" < ${dir}/$file | cut -d'<' -f2 | cut -d'>' -f1 ; 39 | grep -- '#include ".*\.h"' < ${dir}/$file | cut -d'"' -f2 40 | } | sort -u | { 41 | deps=" ${dir}/$file" 42 | while read dep ; do 43 | if echo $dep | grep -q "^${package}/" ; then 44 | deps="$deps src/include/$dep" 45 | elif test -f "${dir}/$dep" ; then 46 | deps="$deps ${dir}/$dep" 47 | else 48 | deps="$deps src/include-local/$dep" 49 | fi 50 | done 51 | o=$(echo $file | sed s/\\.c$/.o/) 52 | lo=$(echo $file | sed s/\\.c$/.lo/) 53 | echo "${dir}/${o} ${dir}/${lo}:${deps}" 54 | } 55 | done 56 | done 57 | echo 58 | 59 | for dir in $(ls -1 src | grep -v ^include) ; do 60 | for file in $(ls -1 src/$dir/deps-lib) ; do 61 | deps= 62 | libs= 63 | while read dep ; do 64 | if echo $dep | grep -q -e '^\${LIB' -e '^-l' -e '^\${.*_LIB}' ; then 65 | libs="$libs $dep" 66 | else 67 | deps="$deps src/$dir/$dep" 68 | fi 69 | done < src/$dir/deps-lib/$file 70 | echo 'ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)' 71 | echo "lib${file}.a.xyzzy:${deps}" 72 | echo else 73 | echo "lib${file}.a.xyzzy:$(echo ${deps} | sed 's/\.o/.lo/g')" 74 | echo endif 75 | if grep -qE "^LIB_DEFS [+:]= .*=$file" package/targets.mak ; then 76 | echo "lib${file}.pc: EXTRA_LIBS :=${libs}" 77 | echo "lib${file}.so.xyzzy: EXTRA_LIBS :=$libs" 78 | echo "lib${file}.so.xyzzy:$(echo ${deps} | sed 's/\.o/.lo/g')" 79 | echo "lib${file}.dylib.xyzzy: EXTRA_LIBS :=$libs" 80 | echo "lib${file}.dylib.xyzzy:$(echo ${deps} | sed 's/\.o/.lo/g')" 81 | else 82 | internal_libs="$internal_libs lib${file}.a.xyzzy" 83 | fi 84 | done 85 | 86 | for file in $(ls -1 src/$dir/deps-exe) ; do 87 | deps= 88 | libs= 89 | while read dep ; do 90 | if echo $dep | grep -q \\.o$ ; then 91 | dep="src/$dir/$dep" 92 | fi 93 | if echo $dep | grep -qx '\${.*_LIB}' ; then 94 | libs="$libs $dep" 95 | else 96 | deps="$deps $dep" 97 | fi 98 | done < src/$dir/deps-exe/$file 99 | echo "$file: EXTRA_LIBS :=$libs" 100 | echo "$file: src/$dir/$file.o$deps" 101 | done 102 | done 103 | echo "INTERNAL_LIBS :=$internal_libs" 104 | -------------------------------------------------------------------------------- /doc/s6-update-symlinks.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: the s6-update-symlinks program 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6
15 | Software
16 | skarnet.org 17 |

18 | 19 |

The s6-update-symlinks program

20 | 21 |

22 | s6-update-symlinks links the content of several similar directory trees 23 | under a single tree. Its main use is to replace search paths like $PATH 24 | or $MANPATH, by creating a unique access tree based on the source trees. 25 | Name conflicts are solved by giving precedence to the last named directory. 26 | Subdirectories are created exactly as needed ; what can be shared is 27 | shared. 28 |

29 | 30 |

31 | s6-update-symlinks is useful when one wants to combine 32 | a logical package system, like Dan Bernstein's 33 | /package and 34 | /command, with 35 | physical filesystem constraints, like /, /usr and 36 | /usr/local on separate filesystems. 37 |

38 | 39 |

Interface

40 | 41 |
42 |      s6-update-symlinks d src1 src2 ...
43 | 
44 | 45 |
    46 |
  • d is the destination directory. It will be created if it doesn't 47 | exist.
  • 48 |
  • src1, src2, ... are the directory containing the files 49 | to be linked.
  • 50 |
  • d and srcn must be 51 | absolute paths, else s6-update-symlinks refuses to run. Using 52 | relative paths doesn't make sense here, anyway.
  • 53 |
  • If src2 is empty, then d becomes a link to src1.
  • 54 |
  • If src1 is empty or entirely overridden by src2, then 55 | d becomes a link to src2.
  • 56 |
  • If src1/file exists but not src2/file, then d 57 | becomes a real directory and d/file a link to src1/file. 58 | Then if src2/file2 exists, d/file2 links to it.
  • 59 |
  • And so on with other src directories, and subdirs.
  • 60 |
  • If s6-update-symlinks manages to performs all the requested 61 | tasks, it exits 0. If it encounters a hard error, it exits 111. If it is 62 | unable to resolve a conflict between given sources, it exits 100.
  • 63 |
64 | 65 |

Examples

66 | 67 |
    68 |
  • 69 | s6-update-symlinks /command /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin 70 |
    makes all files under /bin, ..., /usr/local/sbin 71 | available under /command. The programs linked are the same as the ones 72 | that would be accessed with PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin". 73 |
  • 74 |
  • 75 | s6-update-symlinks /package /initrd/package /slash/package /usr/package /usr/local/package 76 |
    builds a /package hierarchy with what it finds in the listed 77 | directories. This allows oddities like, for instance, having the daemontools 78 | sources in /usr/package/admin/daemontools/src, and the daemontools 79 | binaries in /initrd/package/admin/daemontools/bin, but accessing 80 | both through /package/admin/daemontools/.
  • 81 |
82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-grep.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define USAGE "s6-grep [ -E | -F ] [ -i ] [ -c ] [ -n ] [ -q ] [ -v ] pattern" 19 | #define dieusage() strerr_dieusage(100, USAGE) 20 | 21 | typedef struct grep_flags_s grep_flags_t, *grep_flags_t_ref ; 22 | struct grep_flags_s 23 | { 24 | unsigned int extended : 1 ; 25 | unsigned int ignorecase: 1 ; 26 | unsigned int fixed : 1 ; 27 | unsigned int count : 1 ; 28 | unsigned int num : 1 ; 29 | unsigned int quiet : 1 ; 30 | unsigned int not : 1 ; 31 | } ; 32 | #define GREP_FLAGS_ZERO { .extended = 0, .ignorecase = 0, .fixed = 0, .count = 0, .num = 0, .quiet = 0, .not = 0 } 33 | 34 | static void grep_xout (char const *s, size_t len) 35 | { 36 | if (buffer_put(buffer_1, s, len) < 0) 37 | strerr_diefu1sys(111, "write to stdout") ; 38 | } 39 | 40 | int main (int argc, char const *const *argv) 41 | { 42 | unsigned int count = 0 ; 43 | grep_flags_t flags = GREP_FLAGS_ZERO ; 44 | PROG = "s6-grep" ; 45 | { 46 | subgetopt l = SUBGETOPT_ZERO ; 47 | for (;;) 48 | { 49 | int opt = subgetopt_r(argc, argv, "EFicnqv", &l) ; 50 | if (opt == -1) break ; 51 | switch (opt) 52 | { 53 | case 'E': flags.extended = 1 ; break ; 54 | case 'F': flags.fixed = 1 ; break ; 55 | case 'i': flags.ignorecase = 1 ; break ; 56 | case 'c': flags.count = 1 ; break ; 57 | case 'n': flags.num = 1 ; break ; 58 | case 'q': flags.quiet = 1 ; break ; 59 | case 'v': flags.not = 1 ; break ; 60 | default : dieusage() ; 61 | } 62 | } 63 | argc -= l.ind ; argv += l.ind ; 64 | } 65 | if (!argc) dieusage() ; 66 | { 67 | stralloc line = STRALLOC_ZERO ; 68 | regex_t re ; 69 | unsigned int num = 0 ; 70 | if (!flags.fixed) 71 | { 72 | int e = skalibs_regcomp(&re, argv[0], REG_NOSUB | (flags.extended ? REG_EXTENDED : 0) | (flags.ignorecase ? REG_ICASE : 0)) ; 73 | if (e) 74 | { 75 | char buf[256] ; 76 | regerror(e, &re, buf, 256) ; 77 | strerr_diefu2x(111, "compile regular expression: ", buf) ; 78 | } 79 | } 80 | 81 | for (;;) 82 | { 83 | int r ; 84 | line.len = 0 ; 85 | r = skagetln(buffer_0f1, &line, '\n') ; 86 | if (!r) break ; 87 | if (r < 0) 88 | { 89 | if ((errno != EPIPE) || !stralloc_catb(&line, "\n", 1)) 90 | strerr_diefu1sys(111, "read from stdin") ; 91 | } 92 | num++ ; line.s[line.len-1] = 0 ; 93 | if (flags.fixed) 94 | { 95 | if (flags.ignorecase) 96 | r = !strcasestr(line.s, argv[0]) ; 97 | else 98 | r = !strstr(line.s, argv[0]) ; 99 | } 100 | else 101 | { 102 | r = regexec(&re, line.s, 0, 0, 0) ; 103 | if (r && r != REG_NOMATCH) 104 | { 105 | char buf[256] ; 106 | regerror(r, &re, buf, 256) ; 107 | strerr_diefu2x(111, "match regular expression: ", buf) ; 108 | } 109 | } 110 | line.s[line.len-1] = '\n' ; 111 | if (!r ^ flags.not) 112 | { 113 | count++ ; 114 | if (!flags.quiet && !flags.count) 115 | { 116 | if (flags.num) 117 | { 118 | char fmt[UINT_FMT] ; 119 | size_t n = uint_fmt(fmt, num) ; 120 | fmt[n++] = ':' ; 121 | grep_xout(fmt, n) ; 122 | } 123 | grep_xout(line.s, line.len) ; 124 | } 125 | } 126 | } 127 | if (flags.quiet) return !count ; 128 | stralloc_free(&line) ; 129 | if (!flags.fixed) regfree(&re) ; 130 | } 131 | if (flags.count) 132 | { 133 | char fmt[UINT_FMT] ; 134 | size_t n = uint_fmt(fmt, count) ; 135 | fmt[n++] = '\n' ; 136 | grep_xout(fmt, n) ; 137 | } 138 | return !count ; 139 | } 140 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-sort.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define USAGE "s6-sort [ -bcfru0 ]" 18 | 19 | typedef int strncmp_func (char const *, char const *, size_t) ; 20 | typedef strncmp_func *strncmp_func_ref ; 21 | typedef int qsortcmp_func (void const *, void const *) ; 22 | typedef qsortcmp_func *qsortcmp_func_ref ; 23 | 24 | typedef struct sort_global_s sort_global, *sort_global_ref ; 25 | struct sort_global_s 26 | { 27 | strncmp_func_ref comp ; 28 | unsigned char flagnoblanks : 1 ; 29 | unsigned char flagreverse : 1 ; 30 | unsigned char flaguniq : 1 ; 31 | } ; 32 | #define SORT_GLOBAL_ZERO { .flagnoblanks = 0, .flagreverse = 0, .flaguniq = 0, .comp = &strncmp } 33 | 34 | static sort_global_ref sort_G ; 35 | 36 | static int compit (char const *s1, size_t n1, char const *s2, size_t n2) 37 | { 38 | int r ; 39 | if (sort_G->flagnoblanks) 40 | { 41 | while ((*s1 == ' ') || (*s1 == '\t')) (s1++, n1--) ; 42 | while ((*s2 == ' ') || (*s2 == '\t')) (s2++, n2--) ; 43 | } 44 | r = (*sort_G->comp)(s1, s2, n1 < n2 ? n1 : n2) ; 45 | if (!r) r = n1 - n2 ; 46 | return sort_G->flagreverse ? -r : r ; 47 | } 48 | 49 | static int sacmp (stralloc const *a, stralloc const *b) 50 | { 51 | return compit(a->s, a->len - 1, b->s, b->len - 1) ; 52 | } 53 | 54 | static ssize_t sort_slurplines (genalloc *lines, char sep) 55 | { 56 | ssize_t i = 0 ; 57 | for (;; i++) 58 | { 59 | stralloc sa = STRALLOC_ZERO ; 60 | int r = skagetln(buffer_0, &sa, sep) ; 61 | if (!r) break ; 62 | if ((r < 0) && ((errno != EPIPE) || !stralloc_catb(&sa, &sep, 1))) 63 | return -1 ; 64 | stralloc_shrink(&sa) ; 65 | if (!genalloc_append(stralloc, lines, &sa)) return -1 ; 66 | } 67 | return i ; 68 | } 69 | 70 | static void sort_uniq (genalloc *lines) 71 | { 72 | size_t len = genalloc_len(stralloc, lines) ; 73 | stralloc *s = genalloc_s(stralloc, lines) ; 74 | size_t i = 1 ; 75 | for (; i < len ; i++) 76 | if (!sacmp(s+i-1, s+i)) stralloc_free(s+i-1) ; 77 | } 78 | 79 | static ssize_t sort_outputlines (stralloc const *s, size_t len) 80 | { 81 | size_t i = 0 ; 82 | for (; i < len ; i++) 83 | if (buffer_put(buffer_1, s[i].s, s[i].len) < 0) return 0 ; 84 | return buffer_flush(buffer_1) ; 85 | } 86 | 87 | static int sort_check (stralloc const *s, size_t len) 88 | { 89 | size_t i = 1 ; 90 | for (; i < len ; i++) 91 | if (sacmp(s+i-1, s+i) >= !sort_G->flaguniq) return 0 ; 92 | return 1 ; 93 | } 94 | 95 | int main (int argc, char const *const *argv) 96 | { 97 | genalloc lines = GENALLOC_ZERO ; /* array of stralloc */ 98 | int flagcheck = 0 ; 99 | char sep = '\n' ; 100 | sort_global globals = SORT_GLOBAL_ZERO ; 101 | sort_G = &globals ; 102 | PROG = "s6-sort" ; 103 | { 104 | subgetopt l = SUBGETOPT_ZERO ; 105 | for (;;) 106 | { 107 | int opt = subgetopt_r(argc, argv, "bcfru0", &l) ; 108 | if (opt == -1) break ; 109 | switch (opt) 110 | { 111 | case 'b' : sort_G->flagnoblanks = 1 ; break ; 112 | case 'c' : flagcheck = 1 ; break ; 113 | case 'f' : sort_G->comp = &strncasecmp ; break ; 114 | case 'r' : sort_G->flagreverse = 1 ; break ; 115 | case 'u' : sort_G->flaguniq = 1 ; break ; 116 | case '0' : sep = '\0' ; break ; 117 | default : strerr_dieusage(100, USAGE) ; 118 | } 119 | } 120 | argc -= l.ind ; argv += l.ind ; 121 | } 122 | 123 | if (sort_slurplines(&lines, sep) < 0) strerr_diefu1sys(111, "read from stdin") ; 124 | if (flagcheck) return !sort_check(genalloc_s(stralloc, &lines), genalloc_len(stralloc, &lines)) ; 125 | qsort(genalloc_s(stralloc, &lines), genalloc_len(stralloc, &lines), sizeof(stralloc), (qsortcmp_func_ref)&sacmp) ; 126 | if (sort_G->flaguniq) sort_uniq(&lines) ; 127 | if (!sort_outputlines(genalloc_s(stralloc, &lines), genalloc_len(stralloc, &lines))) 128 | strerr_diefu1sys(111, "write to stdout") ; 129 | return 0 ; 130 | } 131 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-ln.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | 5 | #ifdef SKALIBS_HASLINKAT 6 | #include 7 | #endif 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #define USAGE "s6-ln [ -n ] [ -s ] [ -f ] [ -L ] [ -P ] src... dest" 24 | #define LN_SUFFIX ":s6-ln:XXXXXX" 25 | 26 | #ifdef SKALIBS_HASLINKAT 27 | 28 | static int linknoderef (char const *old, char const *new) 29 | { 30 | return linkat(AT_FDCWD, old, AT_FDCWD, new, 0) ; 31 | } 32 | 33 | static int linkderef (char const *old, char const *new) 34 | { 35 | return linkat(AT_FDCWD, old, AT_FDCWD, new, AT_SYMLINK_FOLLOW) ; 36 | } 37 | 38 | #else /* can't implement SUSv4, default to link */ 39 | 40 | # define linknoderef link 41 | # define linkderef link 42 | 43 | #endif 44 | 45 | static int ln_doit (char const *old, char const *new, link_func_ref mylink, int force) 46 | { 47 | if ((*mylink)(old, new) == -1) 48 | { 49 | if (!force || errno != EEXIST) 50 | { 51 | strerr_warnwu5sys("make a link", " from ", new, " to ", old) ; 52 | return 1 ; 53 | } 54 | { 55 | size_t newlen = strlen(new) ; 56 | char fn[newlen + sizeof(LN_SUFFIX)] ; 57 | memcpy(fn, new, newlen) ; 58 | memcpy(fn + newlen, LN_SUFFIX, sizeof(LN_SUFFIX)) ; 59 | if (mklinktemp(old, fn, mylink) == -1) 60 | { 61 | strerr_warnwu3sys("make a link", " to ", old) ; 62 | return 1 ; 63 | } 64 | if (rename(fn, new) == -1) 65 | { 66 | unlink_void(fn) ; 67 | strerr_warnwu2sys("atomically replace ", new) ; 68 | return 1 ; 69 | } 70 | /* if old == new, rename() didn't remove fn */ 71 | unlink_void(fn) ; 72 | } 73 | } 74 | return 0 ; 75 | } 76 | 77 | int main (int argc, char const *const *argv) 78 | { 79 | link_func_ref mylink = &link ; /* default to system behaviour */ 80 | int force = 0 ; 81 | int nodir = 0 ; 82 | PROG = "s6-ln" ; 83 | { 84 | subgetopt l = SUBGETOPT_ZERO ; 85 | for (;;) 86 | { 87 | int opt = subgetopt_r(argc, argv, "nsfLP", &l) ; 88 | if (opt == -1) break ; 89 | switch (opt) 90 | { 91 | case 'n' : nodir = 1 ; break ; 92 | case 's': mylink = &symlink ; break ; 93 | case 'f': force = 1 ; break ; 94 | case 'L': if (mylink != &symlink) mylink = &linkderef ; break ; 95 | case 'P': if (mylink != &symlink) mylink = &linknoderef ; break ; 96 | default : strerr_dieusage(100, USAGE) ; 97 | } 98 | } 99 | argc -= l.ind ; argv += l.ind ; 100 | } 101 | if (argc < 2) strerr_dieusage(100, USAGE) ; 102 | if (argc > 2) 103 | { 104 | stralloc sa = STRALLOC_ZERO ; 105 | unsigned int i = 0 ; 106 | int e = 0 ; 107 | size_t base ; 108 | if (!stralloc_cats(&sa, argv[argc-1]) || !stralloc_catb(&sa, "/", 1)) 109 | strerr_diefu1sys(111, "stralloc_cats") ; 110 | base = sa.len ; 111 | for (; i < (unsigned int)(argc-1) ; i++) 112 | { 113 | sa.len = base ; 114 | if (!sabasename(&sa, argv[i], strlen(argv[i]))) 115 | { 116 | strerr_warnwu1sys("sabasename") ; 117 | e++ ; 118 | continue ; 119 | } 120 | if (!stralloc_0(&sa)) 121 | { 122 | strerr_warnwu1sys("stralloc_0") ; 123 | e++ ; 124 | continue ; 125 | } 126 | e += ln_doit(argv[i], sa.s, mylink, force) ; 127 | } 128 | return e ; 129 | } 130 | 131 | { 132 | struct stat st ; 133 | if (nodir ? lstat(argv[1], &st) : stat(argv[1], &st) < 0) 134 | { 135 | if (errno != ENOENT) strerr_diefu2sys(111, "stat ", argv[1]) ; 136 | return ln_doit(argv[0], argv[1], mylink, force) ; 137 | } 138 | if (!S_ISDIR(st.st_mode)) 139 | return ln_doit(argv[0], argv[1], mylink, force) ; 140 | } 141 | 142 | { 143 | stralloc sa = STRALLOC_ZERO ; 144 | if (!stralloc_cats(&sa, argv[1]) 145 | || !stralloc_catb(&sa, "/", 1) 146 | || !sabasename(&sa, argv[0], strlen(argv[0])) 147 | || !stralloc_0(&sa)) 148 | strerr_diefu1sys(111, "stralloc_catb") ; 149 | return ln_doit(argv[0], sa.s, mylink, force) ; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-head.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define USAGE "s6-head [ -S ] [ -1..9 | -n lines | -c chars ] [ file... ]" 17 | #define dieusage() strerr_dieusage(100, USAGE) 18 | 19 | typedef int head_func (int, size_t) ; 20 | typedef head_func *head_func_ref ; 21 | 22 | static int head_dolines (int fd, size_t lines) 23 | { 24 | char buf[BUFFER_INSIZE] ; 25 | buffer in = BUFFER_INIT(&buffer_read, fd, buf, BUFFER_INSIZE) ; 26 | buffer out = BUFFER_INIT(&buffer_write, 1, buf, BUFFER_INSIZE) ; 27 | struct iovec v[2] ; 28 | while (lines) 29 | { 30 | size_t w = 0 ; 31 | ssize_t r = buffer_fill(&in) ; 32 | if (r <= 0) return !r ; 33 | out.c.n = in.c.n ; out.c.p = in.c.p ; 34 | buffer_rpeek(&in, v) ; 35 | for (;;) 36 | { 37 | size_t n = siovec_len(v, 2) ; 38 | size_t i ; 39 | if (!n) break ; 40 | i = siovec_bytechr(v, 2, '\n') ; 41 | if (i < n) 42 | { 43 | w += i+1 ; 44 | siovec_seek(v, 2, i+1) ; 45 | if (!--lines) 46 | { 47 | out.c.n = (out.c.p + w) % out.c.a ; 48 | break ; 49 | } 50 | } 51 | else siovec_seek(v, 2, i) ; 52 | } 53 | if (!buffer_flush(&out)) return 0 ; 54 | in.c.n = out.c.n ; in.c.p = out.c.p ; 55 | } 56 | return 1 ; 57 | } 58 | 59 | static int head_safedolines (int fd, size_t lines) 60 | { 61 | char tmp[lines] ; 62 | while (lines) 63 | { 64 | size_t r ; 65 | errno = 0 ; 66 | r = allread(fd, tmp, lines) ; 67 | if (r < lines && errno) return 0 ; 68 | if (!r) break ; 69 | lines -= byte_count(tmp, r, '\n') ; 70 | if (buffer_put(buffer_1, tmp, r) < (ssize_t)r) return 0 ; 71 | } 72 | if (!buffer_flush(buffer_1)) return 0 ; 73 | return 1 ; 74 | } 75 | 76 | static int head_safedochars (int fd, size_t chars) 77 | { 78 | return (fd_catn(fd, 1, chars) >= chars) ; 79 | } 80 | 81 | int main (int argc, char const *const *argv) 82 | { 83 | head_func_ref f ; 84 | unsigned int lines = 10 ; 85 | int islines = 1, safe = 0 ; 86 | PROG = "s6-head" ; 87 | { 88 | subgetopt l = SUBGETOPT_ZERO ; 89 | int done = 0 ; 90 | for (;;) 91 | { 92 | int opt = subgetopt_r(argc, argv, "S123456789n:c:", &l) ; 93 | if (opt == -1) break ; 94 | switch (opt) 95 | { 96 | case 'S' : safe = 1 ; break ; 97 | case '1' : 98 | case '2' : 99 | case '3' : 100 | case '4' : 101 | case '5' : 102 | case '6' : 103 | case '7' : 104 | case '8' : 105 | case '9' : 106 | { 107 | if (done) dieusage() ; 108 | islines = 1 ; 109 | lines = opt - '0' ; 110 | done = 1 ; 111 | break ; 112 | } 113 | case 'n' : 114 | { 115 | if (done || !uint0_scan(l.arg, &lines)) 116 | strerr_dieusage(100, USAGE) ; 117 | islines = 1 ; 118 | done = 1 ; 119 | break ; 120 | } 121 | case 'c' : 122 | { 123 | if (done || !uint0_scan(l.arg, &lines)) 124 | strerr_dieusage(100, USAGE) ; 125 | islines = 0 ; 126 | done = 1 ; 127 | break ; 128 | } 129 | default : strerr_dieusage(100, USAGE) ; 130 | } 131 | } 132 | argc -= l.ind ; argv += l.ind ; 133 | } 134 | if (argc) safe = 0 ; 135 | f = islines ? safe ? &head_safedolines : &head_dolines : &head_safedochars ; 136 | if (!argc) 137 | { 138 | if (!(*f)(0, lines)) 139 | strerr_diefu1sys(111, "head stdin") ; 140 | } 141 | else 142 | { 143 | unsigned int i = 0 ; 144 | for (; argv[i] ; i++) 145 | { 146 | int fd ; 147 | if (argc >= 2) 148 | { 149 | if (i) buffer_putnoflush(buffer_1, "\n", 1) ; 150 | buffer_putnoflush(buffer_1, "==> ", 4) ; 151 | if ((buffer_puts(buffer_1, argv[i]) <= 0) 152 | || (buffer_putflush(buffer_1, " <==\n", 5) < 0)) 153 | strerr_diefu1sys(111, "write to stdout") ; 154 | } 155 | if ((argv[i][0] == '-') && !argv[i][1]) fd = 0 ; 156 | else fd = open_readb(argv[i]) ; 157 | if (fd == -1) 158 | strerr_diefu3sys(111, "open ", argv[i], " for reading") ; 159 | if (!(*f)(fd, lines)) 160 | strerr_diefu2sys(111, "head ", argv[i]) ; 161 | fd_close(fd) ; 162 | } 163 | } 164 | return 0 ; 165 | } 166 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-tail.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define USAGE "s6-tail [ -c chars | -n lines | -1..9 ] [ file ]" 16 | 17 | typedef int tail_func (int, size_t) ; 18 | typedef tail_func *tail_func_ref ; 19 | 20 | static int tail_pluslines (int fd, size_t n) 21 | { 22 | if (n) n-- ; 23 | { 24 | char buf[BUFFER_INSIZE] ; 25 | buffer b = BUFFER_INIT(&buffer_read, fd, buf, BUFFER_INSIZE) ; 26 | size_t count = 0 ; 27 | while (count < n) 28 | { 29 | ssize_t r = buffer_fill(&b) ; 30 | if (r <= 0) return !r ; 31 | while (!buffer_isempty(&b) && (count < n)) 32 | { 33 | struct iovec v[2] ; 34 | size_t i ; 35 | buffer_rpeek(&b, v) ; 36 | i = siovec_bytechr(v, 2, '\n') ; 37 | if (i < buffer_len(&b)) 38 | { 39 | count++ ; i++ ; 40 | } 41 | buffer_rseek(&b, i) ; 42 | } 43 | } 44 | b.op = &buffer_write ; 45 | b.fd = 1 ; 46 | if (!buffer_flush(&b)) return 0 ; 47 | } 48 | return (fd_cat(fd, 1) >= 0) ; 49 | } 50 | 51 | static int tail_pluschars (int fd, size_t n) 52 | { 53 | if (n-- > 1) 54 | { 55 | int nil = open_write("/dev/null") ; 56 | if (nil < 0) return 0 ; 57 | if (!fd_catn(fd, nil, n)) 58 | { 59 | fd_close(nil) ; 60 | return 0 ; 61 | } 62 | fd_close(nil) ; 63 | } 64 | return (fd_cat(fd, 1) >= 0) ; 65 | } 66 | 67 | static int tail_minuslines (int fd, size_t n) 68 | { 69 | char buf[BUFFER_INSIZE] ; 70 | buffer b = BUFFER_INIT(&buffer_read, fd, buf, BUFFER_INSIZE) ; 71 | size_t head = 0, tail = 0 ; 72 | stralloc tab[n+1] ; 73 | for (; head <= n ; head++) tab[head] = stralloc_zero ; 74 | head = 0 ; 75 | for (;;) 76 | { 77 | int r ; 78 | r = skagetln(&b, tab + tail, '\n') ; 79 | if (!r) break ; 80 | if (r < 0) 81 | { 82 | if (errno == EPIPE) break ; 83 | else goto err ; 84 | } 85 | tail = (tail + 1) % (n+1) ; 86 | if (tail == head) 87 | { 88 | tab[head].len = 0 ; 89 | head = (head + 1) % (n+1) ; 90 | } 91 | } 92 | buffer_init(&b, &buffer_write, 1, buf, BUFFER_INSIZE) ; 93 | for (; head != tail ; head = (head + 1) % (n+1)) 94 | { 95 | if (buffer_put(&b, tab[head].s, tab[head].len) < tab[head].len) 96 | goto err ; 97 | } 98 | for (head = 0 ; head <= n ; head++) stralloc_free(tab + head) ; 99 | return buffer_flush(&b) ; 100 | err: 101 | for (head = 0 ; head <= n ; head++) stralloc_free(tab + head) ; 102 | return 0 ; 103 | } 104 | 105 | static int tail_minuschars (int fd, size_t n) 106 | { 107 | char buf[BUFFER_INSIZE + n] ; 108 | buffer b = BUFFER_INIT(&buffer_read, fd, buf, BUFFER_INSIZE + n) ; 109 | for (;;) 110 | { 111 | ssize_t r = buffer_fill(&b) ; 112 | if (!r) break ; 113 | if (r < 0) return 0 ; 114 | buffer_rseek(&b, buffer_len(&b)) ; 115 | buffer_unget(&b, n) ; 116 | } 117 | b.op = &buffer_write ; 118 | b.fd = 1 ; 119 | return buffer_flush(&b) ; 120 | } 121 | 122 | int main (int argc, char const *const *argv) 123 | { 124 | tail_func_ref f = &tail_minuslines ; 125 | unsigned int n = 10 ; 126 | int gotit = 0 ; 127 | PROG = "s6-tail" ; 128 | { 129 | subgetopt l = SUBGETOPT_ZERO ; 130 | for (;;) 131 | { 132 | int opt = subgetopt_r(argc, argv, "123456789n:c:", &l) ; 133 | if (opt == -1) break ; 134 | switch (opt) 135 | { 136 | case '1' : 137 | case '2' : 138 | case '3' : 139 | case '4' : 140 | case '5' : 141 | case '6' : 142 | case '7' : 143 | case '8' : 144 | case '9' : 145 | { 146 | if (gotit) strerr_dieusage(100, USAGE) ; 147 | gotit = 1 ; 148 | f = &tail_minuslines ; 149 | n = opt - '0' ; 150 | break ; 151 | } 152 | case 'n': 153 | { 154 | if (gotit) strerr_dieusage(100, USAGE) ; 155 | gotit = 1 ; 156 | f = &tail_minuslines ; 157 | if (*l.arg == '-') l.arg++ ; 158 | else if (*l.arg == '+') 159 | { 160 | f = &tail_pluslines ; 161 | l.arg++ ; 162 | } 163 | if (!uint0_scan(l.arg, &n)) strerr_dieusage(100, USAGE) ; 164 | break ; 165 | } 166 | case 'c': 167 | { 168 | if (gotit) strerr_dieusage(100, USAGE) ; 169 | gotit = 1 ; 170 | f = &tail_minuschars ; 171 | if (*l.arg == '-') l.arg++ ; 172 | else if (*l.arg == '+') 173 | { 174 | f = &tail_pluschars ; 175 | l.arg++ ; 176 | } 177 | if (!uint0_scan(l.arg, &n)) strerr_dieusage(100, USAGE) ; 178 | break ; 179 | } 180 | default : strerr_dieusage(100, USAGE) ; 181 | } 182 | } 183 | argc -= l.ind ; argv += l.ind ; 184 | } 185 | if (!argc) 186 | { 187 | if (!(*f)(0, n)) 188 | strerr_diefu1sys(111, "tail stdin") ; 189 | } 190 | else 191 | { 192 | int fd = open_readb(argv[0]) ; 193 | if (fd == -1) strerr_diefu3sys(111, "open ", argv[0], " for reading") ; 194 | if (!(*f)(fd, n)) 195 | strerr_diefu2sys(111, "tail ", argv[0]) ; 196 | fd_close(fd) ; 197 | } 198 | return 0 ; 199 | } 200 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-unquote-filter.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define USAGE "s6-unquote-filter [ -q | -Q | -v | -w ] [ -d delim ]" 14 | 15 | static void unquotefilter_fillfmt (char *fmt, char const *s, size_t len) 16 | { 17 | size_t n = len < 39 ? len+1 : 36 ; 18 | memcpy(fmt, s, n) ; 19 | if (len >= 39) 20 | { 21 | memcpy(fmt+n, "...", 3) ; 22 | n += 3 ; 23 | } 24 | fmt[n] = 0 ; 25 | } 26 | 27 | static int unquotefilter_doit (char const *s, size_t len, unsigned int strictness, char const *delim, size_t delimlen) 28 | { 29 | if (delimlen) 30 | { 31 | if (!len) 32 | { 33 | switch (strictness) 34 | { 35 | case 1 : 36 | case 2 : 37 | strerr_warnw1x("empty line") ; 38 | break ; 39 | case 3 : 40 | buffer_flush(buffer_1) ; 41 | strerr_dief1x(100, "empty line") ; 42 | default : break ; 43 | } 44 | return 1 ; 45 | } 46 | if (!memchr(delim, *s, delimlen)) 47 | { 48 | switch (strictness) 49 | { 50 | case 0 : return 0 ; 51 | case 1 : 52 | { 53 | strerr_warnw1x("invalid starting quote character") ; 54 | return 0 ; 55 | } 56 | case 2 : 57 | { 58 | char fmt[40] ; 59 | unquotefilter_fillfmt(fmt, s, len) ; 60 | strerr_warnw3x("invalid starting quote character", " in line: ", fmt) ; 61 | return 0 ; 62 | } 63 | case 3 : 64 | { 65 | buffer_flush(buffer_1) ; 66 | strerr_dief1x(100, "invalid starting quote character") ; 67 | } 68 | default : strerr_dief1x(101, "can't happen: unknown strictness") ; 69 | } 70 | } 71 | } 72 | { 73 | size_t r, w ; 74 | char d[len] ; 75 | if (!string_unquote_withdelim(d, &w, s + !!delimlen, len - !!delimlen, &r, delim, delimlen)) 76 | { 77 | switch (strictness) 78 | { 79 | case 0 : return 0 ; 80 | case 1 : 81 | { 82 | strerr_warnwu1sys("unquote") ; 83 | return 0 ; 84 | } 85 | case 2 : 86 | { 87 | char fmt[40] ; 88 | unquotefilter_fillfmt(fmt, s, len) ; 89 | strerr_warnwu3sys("unquote", " line: ", fmt) ; 90 | return 0 ; 91 | } 92 | case 3 : 93 | { 94 | int e = errno ; 95 | buffer_flush(buffer_1) ; 96 | errno = e ; 97 | strerr_diefu1sys(100, "unquote") ; 98 | } 99 | default : strerr_dief1x(101, "can't happen: unknown strictness") ; 100 | } 101 | } 102 | if (delimlen) 103 | { 104 | if (r+1 == len) 105 | { 106 | switch (strictness) 107 | { 108 | case 0 : return 0 ; 109 | case 1 : 110 | { 111 | strerr_warnwu2x("unquote", ": no ending quote character") ; 112 | return 0 ; 113 | } 114 | case 2 : 115 | { 116 | char fmt[40] ; 117 | unquotefilter_fillfmt(fmt, s, len) ; 118 | strerr_warnwu5x("unquote", ": no ending quote character", " in ", "line: ", fmt) ; 119 | return 0 ; 120 | } 121 | case 3 : 122 | { 123 | int e = errno ; 124 | buffer_flush(buffer_1) ; 125 | errno = e ; 126 | strerr_diefu2x(100, "unquote", ": no ending quote character") ; 127 | } 128 | default : strerr_dief1x(101, "can't happen: unknown strictness") ; 129 | } 130 | } 131 | else if ((r+2 < len) && (strictness >= 2)) 132 | { 133 | char fmtnum[SIZE_FMT] ; 134 | char fmtden[SIZE_FMT] ; 135 | char fmt[40] ; 136 | unquotefilter_fillfmt(fmt, s, len) ; 137 | fmtnum[size_fmt(fmtnum, r+1)] = 0 ; 138 | fmtden[size_fmt(fmtden, len-1)] = 0 ; 139 | strerr_warnw7x("found ending quote character at position ", fmtnum, "/", fmtden, ", ignoring remainder of ", "line: ", fmt) ; 140 | } 141 | } 142 | if (buffer_put(buffer_1, d, w) < (ssize_t)w) 143 | strerr_diefu1sys(111, "write to stdout") ; 144 | } 145 | return 1 ; 146 | } 147 | 148 | 149 | int main (int argc, char const *const *argv) 150 | { 151 | stralloc src = STRALLOC_ZERO ; 152 | unsigned int strictness = 1 ; 153 | char const *delim = "\"" ; 154 | size_t delimlen = 1 ; 155 | PROG = "s6-unquote-filter" ; 156 | { 157 | subgetopt l = SUBGETOPT_ZERO ; 158 | for (;;) 159 | { 160 | int opt = subgetopt_r(argc, argv, "qQvwd:", &l) ; 161 | if (opt == -1) break ; 162 | switch (opt) 163 | { 164 | case 'q': strictness = 0 ; break ; 165 | case 'Q': strictness = 1 ; break ; 166 | case 'v': strictness = 2 ; break ; 167 | case 'w': strictness = 3 ; break ; 168 | case 'd': delim = l.arg ; break ; 169 | default : strerr_dieusage(100, USAGE) ; 170 | } 171 | } 172 | argc -= l.ind ; argv += l.ind ; 173 | } 174 | delimlen = strlen(delim) ; 175 | for (;;) 176 | { 177 | int r ; 178 | src.len = 0 ; 179 | r = skagetln(buffer_0f1, &src, '\n') ; 180 | if (!r) break ; 181 | if (r < 0) 182 | { 183 | if (errno != EPIPE) strerr_diefu1sys(111, "read from stdin") ; 184 | } 185 | else src.len-- ; 186 | if (!unquotefilter_doit(src.s, src.len, strictness, delim, delimlen)) 187 | { 188 | if (buffer_put(buffer_1, src.s, src.len) < (ssize_t)src.len) 189 | strerr_diefu1sys(111, "write to stdout") ; 190 | } 191 | if (r > 0) 192 | { 193 | if (buffer_put(buffer_1, "\n", 1) < 1) 194 | strerr_diefu1sys(111, "write to stdout") ; 195 | } 196 | } 197 | return 0 ; 198 | } 199 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-expr.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define USAGE "s6-expr arithmetic expression" 9 | #define bail() strerr_dief1x(2, "invalid expression") 10 | 11 | enum expr_opnum_e 12 | { 13 | T_DATA, 14 | T_AND, 15 | T_OR, 16 | T_LEFTP, 17 | T_RIGHTP, 18 | T_EQUAL, 19 | T_NEQUAL, 20 | T_GREATER, 21 | T_GREATERE, 22 | T_LESSER, 23 | T_LESSERE, 24 | T_PLUS, 25 | T_MINUS, 26 | T_TIMES, 27 | T_DIV, 28 | T_MOD 29 | } ; 30 | 31 | struct expr_token_s 32 | { 33 | char const *string ; 34 | enum expr_opnum_e op ; 35 | unsigned int type ; 36 | } ; 37 | 38 | struct expr_node_s 39 | { 40 | enum expr_opnum_e op ; 41 | unsigned int type ; 42 | unsigned int arg1 ; 43 | unsigned int arg2 ; 44 | long data ; 45 | } ; 46 | 47 | static unsigned int expr_lex (struct expr_node_s *tree, char const *const *argv) 48 | { 49 | static struct expr_token_s const tokens[16] = 50 | { 51 | { "+", T_PLUS, 3 }, 52 | { "-", T_MINUS, 3 }, 53 | { "*", T_TIMES, 2 }, 54 | { "/", T_DIV, 2 }, 55 | { "%", T_MOD, 2 }, 56 | { "(", T_LEFTP, 7 }, 57 | { ")", T_RIGHTP, 8 }, 58 | { "=", T_EQUAL, 4 }, 59 | { "!=", T_NEQUAL, 4 }, 60 | { "<", T_LESSER, 4 }, 61 | { "<=", T_LESSERE, 4 }, 62 | { ">", T_GREATER, 4 }, 63 | { ">=", T_GREATERE, 4 }, 64 | { "|", T_OR, 6 }, 65 | { "&", T_AND, 5 }, 66 | { 0, 0, 0 } 67 | } ; 68 | unsigned int pos = 0 ; 69 | 70 | for (; argv[pos] ; pos++) 71 | { 72 | unsigned int i = 0 ; 73 | for (i = 0 ; tokens[i].string ; i++) 74 | if (!strcmp(argv[pos], tokens[i].string)) 75 | { 76 | tree[pos].op = tokens[i].op ; 77 | tree[pos].type = tokens[i].type ; 78 | break ; 79 | } 80 | if (!tokens[i].string) 81 | { 82 | tree[pos].op = T_DATA ; 83 | tree[pos].type = 0 ; 84 | if (!long_scan(argv[pos], &tree[pos].data)) bail() ; 85 | } 86 | } 87 | return pos ; 88 | } 89 | 90 | static void expr_reduce (struct expr_node_s *tree, unsigned int *stack, unsigned int *sp, unsigned int type) 91 | { 92 | if (tree[stack[*sp-1]].type == type) 93 | { 94 | tree[stack[*sp-1]].arg1 = stack[*sp-2] ; 95 | tree[stack[*sp-1]].arg2 = stack[*sp] ; 96 | stack[*sp-2] = stack[*sp-1] ; 97 | *sp -= 2 ; 98 | } 99 | tree[stack[*sp]].type = type + 7 ; 100 | } 101 | 102 | static unsigned int expr_parse (struct expr_node_s *tree, unsigned int n) 103 | { 104 | static char const table[9][15] = 105 | { 106 | "xsssssssxzzzzzz", 107 | "xxxxxxxx!zzzzzz", 108 | "mxxxxxxxMszzzzz", 109 | "mxxxxxxxMaszzzz", 110 | "mxxxxxxxMacszzz", 111 | "mxxxxxxxMacAszz", 112 | "mxxxxxxxMacAOsz", 113 | "xsssssssxzzzzzz", 114 | "mxxxxxxxMacAOEs" 115 | } ; 116 | unsigned int stack[n] ; 117 | unsigned int sp = 0, pos = 0 ; 118 | char cont = 1 ; 119 | stack[0] = n + 1 ; 120 | tree[n].type = 8 ; /* add ) for the final reduce */ 121 | tree[n+1].type = 1 ; /* add EOF */ 122 | while (cont) 123 | { 124 | switch (table[tree[pos].type][tree[stack[sp]].type]) 125 | { 126 | case 'x' : bail() ; 127 | case '!' : cont = 0 ; break ; 128 | case 's' : stack[++sp] = pos++ ; break ; 129 | case 'M' : 130 | if (tree[stack[sp-2]].type != 7) bail() ; 131 | stack[sp-2] = stack[sp-1] ; 132 | sp -= 2 ; 133 | case 'm' : expr_reduce(tree, stack, &sp, 2) ; break ; 134 | case 'a' : expr_reduce(tree, stack, &sp, 3) ; break ; 135 | case 'c' : expr_reduce(tree, stack, &sp, 4) ; break ; 136 | case 'A' : expr_reduce(tree, stack, &sp, 5) ; break ; 137 | case 'O' : expr_reduce(tree, stack, &sp, 6) ; break ; 138 | case 'E' : tree[stack[sp]].type = 14 ; break ; 139 | case 'z' : 140 | default : strerr_dief1x(101, "internal error in parse, please submit a bug-report.") ; /* can't happen */ 141 | } 142 | } 143 | if (sp != 2) bail() ; 144 | return stack[1] ; 145 | } 146 | 147 | static long expr_run (struct expr_node_s const *tree, unsigned int root) 148 | { 149 | switch (tree[root].op) 150 | { 151 | case T_DATA : 152 | return tree[root].data ; 153 | case T_OR : 154 | { 155 | long r = expr_run(tree, tree[root].arg1) ; 156 | return r ? r : expr_run(tree, tree[root].arg2) ; 157 | } 158 | case T_AND : 159 | { 160 | long r = expr_run(tree, tree[root].arg1) ; 161 | return r ? expr_run(tree, tree[root].arg2) ? r : 0 : 0 ; 162 | } 163 | case T_EQUAL : 164 | return expr_run(tree, tree[root].arg1) == expr_run(tree, tree[root].arg2) ; 165 | case T_NEQUAL : 166 | return expr_run(tree, tree[root].arg1) != expr_run(tree, tree[root].arg2) ; 167 | case T_GREATER : 168 | return expr_run(tree, tree[root].arg1) > expr_run(tree, tree[root].arg2) ; 169 | case T_GREATERE : 170 | return expr_run(tree, tree[root].arg1) >= expr_run(tree, tree[root].arg2) ; 171 | case T_LESSER : 172 | return expr_run(tree, tree[root].arg1) < expr_run(tree, tree[root].arg2) ; 173 | case T_LESSERE : 174 | return expr_run(tree, tree[root].arg1) <= expr_run(tree, tree[root].arg2) ; 175 | case T_PLUS : 176 | return expr_run(tree, tree[root].arg1) + expr_run(tree, tree[root].arg2) ; 177 | case T_MINUS : 178 | return expr_run(tree, tree[root].arg1) - expr_run(tree, tree[root].arg2) ; 179 | case T_TIMES : 180 | return expr_run(tree, tree[root].arg1) * expr_run(tree, tree[root].arg2) ; 181 | case T_DIV : 182 | return expr_run(tree, tree[root].arg1) / expr_run(tree, tree[root].arg2) ; 183 | case T_MOD : 184 | return expr_run(tree, tree[root].arg1) % expr_run(tree, tree[root].arg2) ; 185 | default : strerr_dief1x(101, "internal error in expr_run, please submit a bug-report") ; 186 | } 187 | } 188 | 189 | int main (int argc, char const *const *argv) 190 | { 191 | char fmt[LONG_FMT] ; 192 | long val ; 193 | size_t len ; 194 | PROG = "s6-expr" ; 195 | if (argc <= 1) return 2 ; 196 | { 197 | struct expr_node_s tree[argc + 1] ; 198 | val = expr_run(tree, expr_parse(tree, expr_lex(tree, argv+1))) ; 199 | } 200 | len = long_fmt(fmt, val) ; 201 | fmt[len++] = '\n' ; 202 | if (allwrite(1, fmt, len) < len) 203 | strerr_diefu1sys(111, "write to stdout") ; 204 | return !val ; 205 | } 206 | -------------------------------------------------------------------------------- /src/s6-portable-utils/s6-cut.c: -------------------------------------------------------------------------------- 1 | /* ISC license. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define USAGE "s6-cut [ -b list | -c list | -f list ] [ -d delim ] [ -n ] [ -s ] [ file... ]" 17 | 18 | static int disize_cmpleft (void const *a, void const *b) 19 | { 20 | return ((disize const *)a)->left - ((disize const *)b)->left ; 21 | } 22 | 23 | static void disizealloc_normalize (genalloc *list) 24 | { 25 | size_t i = 1, cur = 0 ; 26 | size_t len = genalloc_len(disize, list) ; 27 | disize *const s = genalloc_s(disize, list) ; 28 | qsort(s, len, sizeof(disize), &disize_cmpleft) ; 29 | for (; i < len ; i++) 30 | if (!s[cur].right) break ; 31 | else if (s[i].left > s[cur].right) s[++cur] = s[i] ; 32 | else if (s[cur].right < s[i].right) 33 | s[cur].right = s[i].right ; 34 | genalloc_setlen(disize, list, cur+1) ; 35 | } 36 | 37 | static void s6cut_scanlist (genalloc *list, char const *s) 38 | { 39 | size_t i = 0 ; 40 | genalloc_setlen(disize, list, 0) ; 41 | while (s[i]) 42 | { 43 | char const sep[4] = ", \t" ; 44 | disize iv ; 45 | if (s[i] == '-') iv.left = 1 ; 46 | else 47 | { 48 | size_t j = size_scan(s+i, &iv.left) ; 49 | if (!j || !iv.left) strerr_dief2x(100, "invalid list argument: ", s) ; 50 | i += j ; 51 | } 52 | if (s[i] != '-') iv.right = iv.left ; 53 | else 54 | { 55 | size_t j = size_scan(s + ++i, &iv.right) ; 56 | if (!j) iv.right = 0 ; 57 | else if (iv.right < iv.left) 58 | strerr_dief2x(100, "invalid list argument: ", s) ; 59 | else i += j ; 60 | } 61 | switch (byte_chr(sep, 4, s[i])) 62 | { 63 | case 0 : 64 | case 1 : 65 | case 2 : i++ ; 66 | case 3 : break ; 67 | case 4 : 68 | strerr_dief2x(100, "invalid list argument: ", s) ; 69 | } 70 | if (!genalloc_append(disize, list, &iv)) 71 | strerr_diefu1sys(111, "build interval list") ; 72 | } 73 | } 74 | 75 | static int s6cut_doit (int fd, disize const *s, size_t len, unsigned int flags, char delim) 76 | { 77 | char buf[BUFFER_INSIZE] ; 78 | buffer b = BUFFER_INIT(&buffer_flush1read, fd, buf, BUFFER_INSIZE) ; 79 | for (;;) 80 | { 81 | int r ; 82 | satmp.len = 0 ; 83 | r = skagetln(&b, &satmp, '\n') ; 84 | if ((r == -1) && (errno != EPIPE)) return 0 ; 85 | if (!r) break ; 86 | if (flags & 2) 87 | { 88 | size_t i = 0 ; 89 | for (; i < len ; i++) 90 | { 91 | size_t j = s[i].right ; 92 | if (s[i].left >= satmp.len) break ; 93 | if (!j || (j > satmp.len)) 94 | { 95 | j = satmp.len ; 96 | r = 0 ; 97 | } 98 | if (buffer_put(buffer_1, satmp.s + s[i].left - 1, j + 1 - s[i].left) == -1) 99 | return 0 ; 100 | } 101 | } 102 | else 103 | { 104 | size_t i = 0, j = 0, count = 1 ; 105 | for (; i < len ; i++) 106 | { 107 | for (; count < s[i].left ; count++) 108 | { 109 | j += byte_chr(satmp.s + j, satmp.len - j, delim) ; 110 | if (j == satmp.len) break ; 111 | j++ ; 112 | } 113 | if (j == satmp.len) 114 | { 115 | if (count == 1) 116 | { 117 | if ((flags & 1) && (buffer_put(buffer_1, satmp.s, satmp.len) < 0)) 118 | return 0 ; 119 | r = 0 ; 120 | } 121 | break ; 122 | } 123 | for (; !s[i].right || (count <= s[i].right) ; count++) 124 | { 125 | size_t k = byte_chr(satmp.s + j, satmp.len - j, delim) ; 126 | if ((count > s[0].left) && (buffer_put(buffer_1, &delim, 1) < 0)) return 0 ; 127 | if (buffer_put(buffer_1, satmp.s + j, k) < 0) return 0 ; 128 | j += k ; 129 | if (j == satmp.len) 130 | { 131 | r = 0 ; 132 | break ; 133 | } 134 | j++ ; 135 | } 136 | if (j == satmp.len) break ; 137 | } 138 | } 139 | if ((r > 0) && (buffer_put(buffer_1, "\n", 1) < 0)) return 0 ; 140 | } 141 | return 1 ; 142 | } 143 | 144 | int main (int argc, char const *const *argv) 145 | { 146 | genalloc list = GENALLOC_ZERO ; /* array of disize */ 147 | char delim = '\t' ; 148 | unsigned int what = 0 ; 149 | PROG = "s6-cut" ; 150 | { 151 | subgetopt l = SUBGETOPT_ZERO ; 152 | int flagnodel = 1 ; 153 | for (;;) 154 | { 155 | int opt = subgetopt_r(argc, argv, "nsb:c:f:d:", &l) ; 156 | if (opt == -1) break ; 157 | switch (opt) 158 | { 159 | case 'n': break ; /* ignored */ 160 | case 's': flagnodel = 0 ; break ; 161 | case 'd': delim = *l.arg ; break ; 162 | case 'b': 163 | case 'c': 164 | { 165 | if (what) strerr_dieusage(100, USAGE) ; 166 | what = 2 ; 167 | s6cut_scanlist(&list, l.arg) ; 168 | break ; 169 | } 170 | case 'f': 171 | { 172 | if (what) strerr_dieusage(100, USAGE) ; 173 | what = 4 ; 174 | s6cut_scanlist(&list, l.arg) ; 175 | break ; 176 | } 177 | default : strerr_dieusage(100, USAGE) ; 178 | } 179 | } 180 | what += flagnodel ; 181 | argc -= l.ind ; argv += l.ind ; 182 | } 183 | if (!genalloc_len(disize, &list)) strerr_dieusage(100, USAGE) ; 184 | disizealloc_normalize(&list) ; 185 | 186 | if (!argc) 187 | { 188 | if (!s6cut_doit(0, genalloc_s(disize, &list), genalloc_len(disize, &list), what, delim)) 189 | strerr_diefu1sys(111, "cut stdin") ; 190 | } 191 | else 192 | { 193 | for (; *argv ; argv++) 194 | { 195 | if ((argv[0][0] == '-') && !argv[0][1]) 196 | { 197 | if (!s6cut_doit(0, genalloc_s(disize, &list), genalloc_len(disize, &list), what, delim)) 198 | strerr_diefu1sys(111, "process stdin") ; 199 | } 200 | else 201 | { 202 | int fd = open_readb(*argv) ; 203 | if (fd == -1) 204 | strerr_diefu3sys(111, "open ", *argv, " for reading") ; 205 | if (!s6cut_doit(fd, genalloc_s(disize, &list), genalloc_len(disize, &list), what, delim)) 206 | strerr_diefu2sys(111, "cut ", *argv) ; 207 | fd_close(fd) ; 208 | } 209 | } 210 | } 211 | return 0 ; 212 | } 213 | -------------------------------------------------------------------------------- /doc/upgrade.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | s6-portable-utils: how to upgrade 7 | 8 | 9 | 10 | 11 | 12 | 13 |

14 | s6-portable-utils
15 | Software
16 | skarnet.org 17 |

18 | 19 |

What has changed in s6-portable-utils

20 | 21 |

in 2.3.1.1

22 | 23 |
    24 |
  • skalibs 25 | dependency bumped to 2.14.5.0.
  • 26 |
  • Shared libraries are now supported on MacOS.
  • 27 |
28 | 29 |

in 2.3.1.0

30 | 31 |
    32 |
  • skalibs 33 | dependency bumped to 2.14.4.0.
  • 34 |
35 | 36 |

in 2.3.0.4

37 | 38 |
    39 |
  • skalibs 40 | dependency bumped to 2.14.3.0.
  • 41 |
  • Static libraries (if any, which isn't the case for now) 42 | are installed in /usr/lib by default.
  • 43 |
44 | 45 |

in 2.3.0.3

46 | 47 |
    48 |
  • skalibs 49 | dependency bumped to 2.14.0.0.
  • 50 |
51 | 52 |

in 2.3.0.2

53 | 54 |
    55 |
  • skalibs 56 | dependency bumped to 2.13.1.1.
  • 57 |
58 | 59 |

in 2.3.0.1

60 | 61 |
    62 |
  • No functional changes.
  • 63 |
64 | 65 |

in 2.3.0.0

66 | 67 |
    68 |
  • skalibs 69 | dependency bumped to 2.13.1.0.
  • 70 |
  • s6-test removed. Use 71 | eltest 72 | instead.
  • 73 |
  • New s6-portable-utils 74 | multicall binary.
  • 75 |
76 | 77 |

in 2.2.5.1

78 | 79 |
    80 |
  • skalibs 81 | dependency bumped to 2.13.0.0.
  • 82 |
83 | 84 |

in 2.2.5.0

85 | 86 |
    87 |
  • skalibs 88 | dependency bumped to 2.12.0.0.
  • 89 |
90 | 91 |

in 2.2.4.0

92 | 93 |
    94 |
  • skalibs 95 | dependency bumped to 2.11.2.0.
  • 96 |
97 | 98 |

in 2.2.3.4

99 | 100 |
    101 |
  • skalibs 102 | dependency bumped to 2.11.1.0.
  • 103 |
104 | 105 |

in 2.2.3.3

106 | 107 |
    108 |
  • skalibs 109 | dependency bumped to 2.11.0.0.
  • 110 |
111 | 112 |

in 2.2.3.2

113 | 114 |
    115 |
  • skalibs 116 | dependency bumped to 2.10.0.3.
  • 117 |
118 | 119 |

in 2.2.3.1

120 | 121 |
    122 |
  • skalibs 123 | dependency bumped to 2.10.0.0.
  • 124 |
125 | 126 |

in 2.2.3.0

127 | 128 | 133 | 134 |

in 2.2.2.4

135 | 136 |
    137 |
  • Bugfix release, no changes.
  • 138 |
139 | 140 |

in 2.2.2.3

141 | 142 |
    143 |
  • skalibs 144 | dependency bumped to 2.9.2.1.
  • 145 |
146 | 147 |

in 2.2.2.2

148 | 149 |
    150 |
  • skalibs 151 | dependency bumped to 2.9.2.0.
  • 152 |
153 | 154 |

in 2.2.2.1

155 | 156 |
    157 |
  • skalibs 158 | dependency bumped to 2.9.1.0.
  • 159 |
160 | 161 |

in 2.2.2.0

162 | 163 |
    164 |
  • skalibs 165 | dependency bumped to 2.9.0.0.
  • 166 |
167 | 168 |

in 2.2.1.3

169 | 170 |
    171 |
  • skalibs 172 | dependency bumped to 2.8.0.0.
  • 173 |
  • Everything now builds as PIC by default no matter 174 | the toolchain's settings. Use the --disable-all-pic configure 175 | option to build executables and static libraries as non-PIC.
  • 176 |
177 | 178 |

in 2.2.1.2

179 | 180 |
    181 |
  • skalibs dependency bumped to 2.7.0.0.
  • 182 |
183 | 184 |

in 2.2.1.1

185 | 186 |
    187 |
  • skalibs dependency bumped to 2.6.0.0.
  • 188 |
189 | 190 |

in 2.2.1.0

191 | 192 |
    193 |
  • skalibs dependency bumped to 2.5.1.0.
  • 194 |
  • s6-ln now accepts the 195 | nonstandard -n option.
  • 196 |
197 | 198 |

in 2.2.0.0

199 | 200 |
    201 |
  • skalibs dependency bumped to 2.5.0.0.
  • 202 |
203 | 204 |

in 2.1.0.0

205 | 206 |
    207 |
  • skalibs dependency bumped to 2.4.0.0.
  • 208 |
209 | 210 |

in 2.0.6.0

211 | 212 |
    213 |
  • skalibs dependency bumped to 2.3.10.0.
  • 214 |
215 | 216 |

in 2.0.5.3

217 | 218 |
    219 |
  • GNU make dependency pushed back to 3.81.
  • 220 |
  • skalibs dependency bumped to 2.3.8.0.
  • 221 |
222 | 223 |

in 2.0.5.2

224 | 225 |
    226 |
  • Bugfix release, no changes.
  • 227 |
228 | 229 |

in 2.0.5.1

230 | 231 |
    232 |
  • skalibs dependency bumped to 2.3.6.1.
  • 233 |
234 | 235 |

in 2.0.5.0

236 | 237 |
    238 |
  • skalibs dependency bumped to 2.3.4.0.
  • 239 |
  • New command: s6-seq.
  • 240 |
241 | 242 |

in 2.0.4.0

243 | 244 | 247 | 248 |

in 2.0.3.0

249 | 250 | 253 | 254 |

in 2.0.2.0

255 | 256 |
    257 |
  • skalibs dependency bumped to 2.3.1.0.
  • 258 |
  • s6-hiercopy now belongs to this package. (It formely belonged 259 | to s6-linux-utils, but it is actually portable in practice.)
  • 260 |
261 | 262 |

in 2.0.1.0

263 | 264 |
    265 |
  • skalibs dependency bumped to 2.2.0.0.
  • 266 |
  • seekablepipe moved from 267 | s6-networking 268 | to s6-portable-utils.
  • 269 |
270 | 271 |

in 2.0.0.1

272 | 273 |
    274 |
  • skalibs dependency bumped to 2.1.0.0.
  • 275 |
276 | 277 |

in 2.0.0.0

278 | 279 |
    280 |
  • The build system has completely changed. It is now a standard 281 | ./configure && make && sudo make install 282 | build system. See the enclosed INSTALL file for details.
  • 283 |
  • slashpackage is not activated by default.
  • 284 |
  • shared libraries are not used by default.
  • 285 |
  • skalibs dependency bumped to 2.0.0.0.
  • 286 |
287 | 288 | 289 | 290 | -------------------------------------------------------------------------------- /package/deps.mak: -------------------------------------------------------------------------------- 1 | # 2 | # This file has been generated by tools/gen-deps.sh 3 | # 4 | 5 | src/s6-portable-utils/s6-basename.o src/s6-portable-utils/s6-basename.lo: src/s6-portable-utils/s6-basename.c 6 | src/s6-portable-utils/s6-cat.o src/s6-portable-utils/s6-cat.lo: src/s6-portable-utils/s6-cat.c 7 | src/s6-portable-utils/s6-chmod.o src/s6-portable-utils/s6-chmod.lo: src/s6-portable-utils/s6-chmod.c 8 | src/s6-portable-utils/s6-chown.o src/s6-portable-utils/s6-chown.lo: src/s6-portable-utils/s6-chown.c 9 | src/s6-portable-utils/s6-clock.o src/s6-portable-utils/s6-clock.lo: src/s6-portable-utils/s6-clock.c 10 | src/s6-portable-utils/s6-cut.o src/s6-portable-utils/s6-cut.lo: src/s6-portable-utils/s6-cut.c 11 | src/s6-portable-utils/s6-dirname.o src/s6-portable-utils/s6-dirname.lo: src/s6-portable-utils/s6-dirname.c 12 | src/s6-portable-utils/s6-dumpenv.o src/s6-portable-utils/s6-dumpenv.lo: src/s6-portable-utils/s6-dumpenv.c 13 | src/s6-portable-utils/s6-echo.o src/s6-portable-utils/s6-echo.lo: src/s6-portable-utils/s6-echo.c 14 | 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 15 | src/s6-portable-utils/s6-expr.o src/s6-portable-utils/s6-expr.lo: src/s6-portable-utils/s6-expr.c 16 | src/s6-portable-utils/s6-false.o src/s6-portable-utils/s6-false.lo: src/s6-portable-utils/s6-false.c 17 | src/s6-portable-utils/s6-format-filter.o src/s6-portable-utils/s6-format-filter.lo: src/s6-portable-utils/s6-format-filter.c 18 | src/s6-portable-utils/s6-grep.o src/s6-portable-utils/s6-grep.lo: src/s6-portable-utils/s6-grep.c 19 | src/s6-portable-utils/s6-head.o src/s6-portable-utils/s6-head.lo: src/s6-portable-utils/s6-head.c 20 | src/s6-portable-utils/s6-hiercopy.o src/s6-portable-utils/s6-hiercopy.lo: src/s6-portable-utils/s6-hiercopy.c 21 | src/s6-portable-utils/s6-linkname.o src/s6-portable-utils/s6-linkname.lo: src/s6-portable-utils/s6-linkname.c 22 | src/s6-portable-utils/s6-ln.o src/s6-portable-utils/s6-ln.lo: src/s6-portable-utils/s6-ln.c 23 | src/s6-portable-utils/s6-ls.o src/s6-portable-utils/s6-ls.lo: src/s6-portable-utils/s6-ls.c 24 | src/s6-portable-utils/s6-maximumtime.o src/s6-portable-utils/s6-maximumtime.lo: src/s6-portable-utils/s6-maximumtime.c 25 | src/s6-portable-utils/s6-mkdir.o src/s6-portable-utils/s6-mkdir.lo: src/s6-portable-utils/s6-mkdir.c 26 | src/s6-portable-utils/s6-mkfifo.o src/s6-portable-utils/s6-mkfifo.lo: src/s6-portable-utils/s6-mkfifo.c 27 | src/s6-portable-utils/s6-nice.o src/s6-portable-utils/s6-nice.lo: src/s6-portable-utils/s6-nice.c 28 | src/s6-portable-utils/s6-nuke.o src/s6-portable-utils/s6-nuke.lo: src/s6-portable-utils/s6-nuke.c 29 | src/s6-portable-utils/s6-pause.o src/s6-portable-utils/s6-pause.lo: src/s6-portable-utils/s6-pause.c 30 | src/s6-portable-utils/s6-printenv.o src/s6-portable-utils/s6-printenv.lo: src/s6-portable-utils/s6-printenv.c 31 | src/s6-portable-utils/s6-quote-filter.o src/s6-portable-utils/s6-quote-filter.lo: src/s6-portable-utils/s6-quote-filter.c 32 | src/s6-portable-utils/s6-quote.o src/s6-portable-utils/s6-quote.lo: src/s6-portable-utils/s6-quote.c 33 | src/s6-portable-utils/s6-rename.o src/s6-portable-utils/s6-rename.lo: src/s6-portable-utils/s6-rename.c 34 | src/s6-portable-utils/s6-rmrf.o src/s6-portable-utils/s6-rmrf.lo: src/s6-portable-utils/s6-rmrf.c 35 | src/s6-portable-utils/s6-seq.o src/s6-portable-utils/s6-seq.lo: src/s6-portable-utils/s6-seq.c 36 | src/s6-portable-utils/s6-sleep.o src/s6-portable-utils/s6-sleep.lo: src/s6-portable-utils/s6-sleep.c 37 | src/s6-portable-utils/s6-sort.o src/s6-portable-utils/s6-sort.lo: src/s6-portable-utils/s6-sort.c 38 | src/s6-portable-utils/s6-sync.o src/s6-portable-utils/s6-sync.lo: src/s6-portable-utils/s6-sync.c 39 | src/s6-portable-utils/s6-tai64ndiff.o src/s6-portable-utils/s6-tai64ndiff.lo: src/s6-portable-utils/s6-tai64ndiff.c 40 | src/s6-portable-utils/s6-tail.o src/s6-portable-utils/s6-tail.lo: src/s6-portable-utils/s6-tail.c 41 | src/s6-portable-utils/s6-touch.o src/s6-portable-utils/s6-touch.lo: src/s6-portable-utils/s6-touch.c 42 | src/s6-portable-utils/s6-true.o src/s6-portable-utils/s6-true.lo: src/s6-portable-utils/s6-true.c 43 | src/s6-portable-utils/s6-uniquename.o src/s6-portable-utils/s6-uniquename.lo: src/s6-portable-utils/s6-uniquename.c 44 | src/s6-portable-utils/s6-unquote-filter.o src/s6-portable-utils/s6-unquote-filter.lo: src/s6-portable-utils/s6-unquote-filter.c 45 | src/s6-portable-utils/s6-unquote.o src/s6-portable-utils/s6-unquote.lo: src/s6-portable-utils/s6-unquote.c 46 | src/s6-portable-utils/s6-update-symlinks.o src/s6-portable-utils/s6-update-symlinks.lo: src/s6-portable-utils/s6-update-symlinks.c 47 | src/s6-portable-utils/seekablepipe.o src/s6-portable-utils/seekablepipe.lo: src/s6-portable-utils/seekablepipe.c 48 | 49 | s6-portable-utils: EXTRA_LIBS := ${SPAWN_LIB} 50 | s6-portable-utils: src/multicall/s6-portable-utils.o -lskarnet 51 | s6-basename: EXTRA_LIBS := 52 | s6-basename: src/s6-portable-utils/s6-basename.o -lskarnet 53 | s6-cat: EXTRA_LIBS := 54 | s6-cat: src/s6-portable-utils/s6-cat.o -lskarnet 55 | s6-chmod: EXTRA_LIBS := 56 | s6-chmod: src/s6-portable-utils/s6-chmod.o -lskarnet 57 | s6-chown: EXTRA_LIBS := 58 | s6-chown: src/s6-portable-utils/s6-chown.o -lskarnet 59 | s6-clock: EXTRA_LIBS := ${SYSCLOCK_LIB} 60 | s6-clock: src/s6-portable-utils/s6-clock.o -lskarnet 61 | s6-cut: EXTRA_LIBS := 62 | s6-cut: src/s6-portable-utils/s6-cut.o -lskarnet 63 | s6-dirname: EXTRA_LIBS := 64 | s6-dirname: src/s6-portable-utils/s6-dirname.o -lskarnet 65 | s6-dumpenv: EXTRA_LIBS := 66 | s6-dumpenv: src/s6-portable-utils/s6-dumpenv.o -lskarnet 67 | s6-echo: EXTRA_LIBS := 68 | s6-echo: src/s6-portable-utils/s6-echo.o -lskarnet 69 | s6-env: EXTRA_LIBS := 70 | s6-env: src/s6-portable-utils/s6-env.o -lskarnet 71 | s6-expr: EXTRA_LIBS := 72 | s6-expr: src/s6-portable-utils/s6-expr.o -lskarnet 73 | s6-false: EXTRA_LIBS := 74 | s6-false: src/s6-portable-utils/s6-false.o 75 | s6-format-filter: EXTRA_LIBS := 76 | s6-format-filter: src/s6-portable-utils/s6-format-filter.o -lskarnet 77 | s6-grep: EXTRA_LIBS := 78 | s6-grep: src/s6-portable-utils/s6-grep.o -lskarnet 79 | s6-head: EXTRA_LIBS := 80 | s6-head: src/s6-portable-utils/s6-head.o -lskarnet 81 | s6-hiercopy: EXTRA_LIBS := 82 | s6-hiercopy: src/s6-portable-utils/s6-hiercopy.o -lskarnet 83 | s6-linkname: EXTRA_LIBS := 84 | s6-linkname: src/s6-portable-utils/s6-linkname.o -lskarnet 85 | s6-ln: EXTRA_LIBS := 86 | s6-ln: src/s6-portable-utils/s6-ln.o -lskarnet 87 | s6-ls: EXTRA_LIBS := 88 | s6-ls: src/s6-portable-utils/s6-ls.o -lskarnet 89 | s6-maximumtime: EXTRA_LIBS := ${SYSCLOCK_LIB} ${SPAWN_LIB} 90 | s6-maximumtime: src/s6-portable-utils/s6-maximumtime.o -lskarnet 91 | s6-mkdir: EXTRA_LIBS := 92 | s6-mkdir: src/s6-portable-utils/s6-mkdir.o -lskarnet 93 | s6-mkfifo: EXTRA_LIBS := 94 | s6-mkfifo: src/s6-portable-utils/s6-mkfifo.o -lskarnet 95 | s6-nice: EXTRA_LIBS := 96 | s6-nice: src/s6-portable-utils/s6-nice.o -lskarnet 97 | s6-nuke: EXTRA_LIBS := 98 | s6-nuke: src/s6-portable-utils/s6-nuke.o -lskarnet 99 | s6-pause: EXTRA_LIBS := 100 | s6-pause: src/s6-portable-utils/s6-pause.o -lskarnet 101 | s6-printenv: EXTRA_LIBS := 102 | s6-printenv: src/s6-portable-utils/s6-printenv.o -lskarnet 103 | s6-quote: EXTRA_LIBS := 104 | s6-quote: src/s6-portable-utils/s6-quote.o -lskarnet 105 | s6-quote-filter: EXTRA_LIBS := 106 | s6-quote-filter: src/s6-portable-utils/s6-quote-filter.o -lskarnet 107 | s6-rename: EXTRA_LIBS := 108 | s6-rename: src/s6-portable-utils/s6-rename.o -lskarnet 109 | s6-rmrf: EXTRA_LIBS := 110 | s6-rmrf: src/s6-portable-utils/s6-rmrf.o -lskarnet 111 | s6-seq: EXTRA_LIBS := 112 | s6-seq: src/s6-portable-utils/s6-seq.o -lskarnet 113 | s6-sleep: EXTRA_LIBS := ${SYSCLOCK_LIB} 114 | s6-sleep: src/s6-portable-utils/s6-sleep.o -lskarnet 115 | s6-sort: EXTRA_LIBS := 116 | s6-sort: src/s6-portable-utils/s6-sort.o -lskarnet 117 | s6-sync: EXTRA_LIBS := 118 | s6-sync: src/s6-portable-utils/s6-sync.o 119 | s6-tai64ndiff: EXTRA_LIBS := 120 | s6-tai64ndiff: src/s6-portable-utils/s6-tai64ndiff.o -lskarnet 121 | s6-tail: EXTRA_LIBS := 122 | s6-tail: src/s6-portable-utils/s6-tail.o -lskarnet 123 | s6-touch: EXTRA_LIBS := 124 | s6-touch: src/s6-portable-utils/s6-touch.o -lskarnet 125 | s6-true: EXTRA_LIBS := 126 | s6-true: src/s6-portable-utils/s6-true.o 127 | s6-uniquename: EXTRA_LIBS := 128 | s6-uniquename: src/s6-portable-utils/s6-uniquename.o -lskarnet 129 | s6-unquote: EXTRA_LIBS := 130 | s6-unquote: src/s6-portable-utils/s6-unquote.o -lskarnet 131 | s6-unquote-filter: EXTRA_LIBS := 132 | s6-unquote-filter: src/s6-portable-utils/s6-unquote-filter.o -lskarnet 133 | s6-update-symlinks: EXTRA_LIBS := 134 | s6-update-symlinks: src/s6-portable-utils/s6-update-symlinks.o -lskarnet 135 | seekablepipe: EXTRA_LIBS := 136 | seekablepipe: src/s6-portable-utils/seekablepipe.o -lskarnet 137 | INTERNAL_LIBS := 138 | --------------------------------------------------------------------------------