From bea0037dbdd979603fb0b5be8b43f5478c1f6fec Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Fri, 19 Sep 2014 02:53:32 +0000 Subject: initial commit --- .gitignore | 5 + AUTHORS | 8 + CHANGES | 62 ++++ COPYING | 13 + INSTALL | 118 +++++++ Makefile | 121 +++++++ README | 25 ++ README.solaris | 12 + configure | 383 +++++++++++++++++++++ doc/index.html | 162 +++++++++ doc/s6-basename.html | 50 +++ doc/s6-cat.html | 51 +++ doc/s6-chmod.html | 45 +++ doc/s6-chown.html | 52 +++ doc/s6-clock.html | 54 +++ doc/s6-cut.html | 44 +++ doc/s6-dirname.html | 50 +++ doc/s6-echo.html | 51 +++ doc/s6-env.html | 45 +++ doc/s6-expr.html | 50 +++ doc/s6-false.html | 39 +++ doc/s6-format-filter.html | 42 +++ doc/s6-grep.html | 67 ++++ doc/s6-head.html | 55 +++ doc/s6-linkname.html | 45 +++ doc/s6-ln.html | 44 +++ doc/s6-ls.html | 57 +++ doc/s6-maximumtime.html | 53 +++ doc/s6-mkdir.html | 50 +++ doc/s6-mkfifo.html | 44 +++ doc/s6-nice.html | 53 +++ doc/s6-nuke.html | 56 +++ doc/s6-pause.html | 39 +++ doc/s6-printenv.html | 46 +++ doc/s6-quote-filter.html | 56 +++ doc/s6-quote.html | 57 +++ doc/s6-rename.html | 35 ++ doc/s6-rmrf.html | 35 ++ doc/s6-sleep.html | 51 +++ doc/s6-sort.html | 59 ++++ doc/s6-sync.html | 32 ++ doc/s6-tail.html | 46 +++ doc/s6-test.html | 53 +++ doc/s6-touch.html | 45 +++ doc/s6-true.html | 39 +++ doc/s6-uniquename.html | 45 +++ doc/s6-unquote-filter.html | 69 ++++ doc/s6-unquote.html | 58 ++++ doc/s6-update-symlinks.html | 83 +++++ doc/upgrade.html | 32 ++ package/deps-build | 1 + package/deps.mak | 83 +++++ package/info | 4 + package/modes | 39 +++ package/targets.mak | 45 +++ patch-for-solaris | 17 + src/skaembutils/deps-exe/s6-basename | 1 + src/skaembutils/deps-exe/s6-cat | 1 + src/skaembutils/deps-exe/s6-chmod | 1 + src/skaembutils/deps-exe/s6-chown | 1 + src/skaembutils/deps-exe/s6-clock | 2 + src/skaembutils/deps-exe/s6-cut | 1 + src/skaembutils/deps-exe/s6-dirname | 1 + src/skaembutils/deps-exe/s6-echo | 1 + src/skaembutils/deps-exe/s6-env | 1 + src/skaembutils/deps-exe/s6-expr | 1 + src/skaembutils/deps-exe/s6-false | 0 src/skaembutils/deps-exe/s6-format-filter | 1 + src/skaembutils/deps-exe/s6-grep | 1 + src/skaembutils/deps-exe/s6-head | 1 + src/skaembutils/deps-exe/s6-linkname | 1 + src/skaembutils/deps-exe/s6-ln | 3 + src/skaembutils/deps-exe/s6-ls | 1 + src/skaembutils/deps-exe/s6-maximumtime | 2 + src/skaembutils/deps-exe/s6-mkdir | 1 + src/skaembutils/deps-exe/s6-mkfifo | 1 + src/skaembutils/deps-exe/s6-nice | 1 + src/skaembutils/deps-exe/s6-nuke | 1 + src/skaembutils/deps-exe/s6-pause | 0 src/skaembutils/deps-exe/s6-printenv | 1 + src/skaembutils/deps-exe/s6-quote | 1 + src/skaembutils/deps-exe/s6-quote-filter | 1 + src/skaembutils/deps-exe/s6-rename | 1 + src/skaembutils/deps-exe/s6-rmrf | 1 + src/skaembutils/deps-exe/s6-sleep | 2 + src/skaembutils/deps-exe/s6-sort | 1 + src/skaembutils/deps-exe/s6-sync | 0 src/skaembutils/deps-exe/s6-tail | 1 + src/skaembutils/deps-exe/s6-test | 1 + src/skaembutils/deps-exe/s6-touch | 1 + src/skaembutils/deps-exe/s6-true | 0 src/skaembutils/deps-exe/s6-uniquename | 3 + src/skaembutils/deps-exe/s6-unquote | 1 + src/skaembutils/deps-exe/s6-unquote-filter | 1 + src/skaembutils/deps-exe/s6-update-symlinks | 3 + src/skaembutils/s6-basename.c | 45 +++ src/skaembutils/s6-cat.c | 12 + src/skaembutils/s6-chmod.c | 34 ++ src/skaembutils/s6-chown.c | 60 ++++ src/skaembutils/s6-clock.c | 31 ++ src/skaembutils/s6-cut.c | 212 ++++++++++++ src/skaembutils/s6-dirname.c | 40 +++ src/skaembutils/s6-echo.c | 38 ++ src/skaembutils/s6-env.c | 43 +++ src/skaembutils/s6-expr.c | 211 ++++++++++++ src/skaembutils/s6-false.c | 6 + src/skaembutils/s6-format-filter.c | 61 ++++ src/skaembutils/s6-grep.c | 136 ++++++++ src/skaembutils/s6-head.c | 159 +++++++++ src/skaembutils/s6-linkname.c | 45 +++ src/skaembutils/s6-ln.c | 145 ++++++++ src/skaembutils/s6-ls.c | 56 +++ src/skaembutils/s6-maximumtime.c | 99 ++++++ src/skaembutils/s6-mkdir.c | 79 +++++ src/skaembutils/s6-mkfifo.c | 36 ++ src/skaembutils/s6-nice.c | 46 +++ src/skaembutils/s6-nuke.c | 50 +++ src/skaembutils/s6-pause.c | 9 + src/skaembutils/s6-printenv.c | 51 +++ src/skaembutils/s6-quote-filter.c | 72 ++++ src/skaembutils/s6-quote.c | 58 ++++ src/skaembutils/s6-rename.c | 16 + src/skaembutils/s6-rmrf.c | 17 + src/skaembutils/s6-sleep.c | 46 +++ src/skaembutils/s6-sort.c | 123 +++++++ src/skaembutils/s6-sync.c | 9 + src/skaembutils/s6-tail.c | 200 +++++++++++ src/skaembutils/s6-test.c | 515 ++++++++++++++++++++++++++++ src/skaembutils/s6-touch.c | 20 ++ src/skaembutils/s6-true.c | 6 + src/skaembutils/s6-uniquename.c | 40 +++ src/skaembutils/s6-unquote-filter.c | 198 +++++++++++ src/skaembutils/s6-unquote.c | 70 ++++ src/skaembutils/s6-update-symlinks.c | 367 ++++++++++++++++++++ tools/gen-deps.sh | 79 +++++ tools/install.sh | 64 ++++ 136 files changed, 6723 insertions(+) create mode 100644 .gitignore create mode 100644 AUTHORS create mode 100644 CHANGES create mode 100644 COPYING create mode 100644 INSTALL create mode 100644 Makefile create mode 100644 README create mode 100644 README.solaris create mode 100755 configure create mode 100644 doc/index.html create mode 100644 doc/s6-basename.html create mode 100644 doc/s6-cat.html create mode 100644 doc/s6-chmod.html create mode 100644 doc/s6-chown.html create mode 100644 doc/s6-clock.html create mode 100644 doc/s6-cut.html create mode 100644 doc/s6-dirname.html create mode 100644 doc/s6-echo.html create mode 100644 doc/s6-env.html create mode 100644 doc/s6-expr.html create mode 100644 doc/s6-false.html create mode 100644 doc/s6-format-filter.html create mode 100644 doc/s6-grep.html create mode 100644 doc/s6-head.html create mode 100644 doc/s6-linkname.html create mode 100644 doc/s6-ln.html create mode 100644 doc/s6-ls.html create mode 100644 doc/s6-maximumtime.html create mode 100644 doc/s6-mkdir.html create mode 100644 doc/s6-mkfifo.html create mode 100644 doc/s6-nice.html create mode 100644 doc/s6-nuke.html create mode 100644 doc/s6-pause.html create mode 100644 doc/s6-printenv.html create mode 100644 doc/s6-quote-filter.html create mode 100644 doc/s6-quote.html create mode 100644 doc/s6-rename.html create mode 100644 doc/s6-rmrf.html create mode 100644 doc/s6-sleep.html create mode 100644 doc/s6-sort.html create mode 100644 doc/s6-sync.html create mode 100644 doc/s6-tail.html create mode 100644 doc/s6-test.html create mode 100644 doc/s6-touch.html create mode 100644 doc/s6-true.html create mode 100644 doc/s6-uniquename.html create mode 100644 doc/s6-unquote-filter.html create mode 100644 doc/s6-unquote.html create mode 100644 doc/s6-update-symlinks.html create mode 100644 doc/upgrade.html create mode 100644 package/deps-build create mode 100644 package/deps.mak create mode 100644 package/info create mode 100644 package/modes create mode 100644 package/targets.mak create mode 100755 patch-for-solaris create mode 100644 src/skaembutils/deps-exe/s6-basename create mode 100644 src/skaembutils/deps-exe/s6-cat create mode 100644 src/skaembutils/deps-exe/s6-chmod create mode 100644 src/skaembutils/deps-exe/s6-chown create mode 100644 src/skaembutils/deps-exe/s6-clock create mode 100644 src/skaembutils/deps-exe/s6-cut create mode 100644 src/skaembutils/deps-exe/s6-dirname create mode 100644 src/skaembutils/deps-exe/s6-echo create mode 100644 src/skaembutils/deps-exe/s6-env create mode 100644 src/skaembutils/deps-exe/s6-expr create mode 100644 src/skaembutils/deps-exe/s6-false create mode 100644 src/skaembutils/deps-exe/s6-format-filter create mode 100644 src/skaembutils/deps-exe/s6-grep create mode 100644 src/skaembutils/deps-exe/s6-head create mode 100644 src/skaembutils/deps-exe/s6-linkname create mode 100644 src/skaembutils/deps-exe/s6-ln create mode 100644 src/skaembutils/deps-exe/s6-ls create mode 100644 src/skaembutils/deps-exe/s6-maximumtime create mode 100644 src/skaembutils/deps-exe/s6-mkdir create mode 100644 src/skaembutils/deps-exe/s6-mkfifo create mode 100644 src/skaembutils/deps-exe/s6-nice create mode 100644 src/skaembutils/deps-exe/s6-nuke create mode 100644 src/skaembutils/deps-exe/s6-pause create mode 100644 src/skaembutils/deps-exe/s6-printenv create mode 100644 src/skaembutils/deps-exe/s6-quote create mode 100644 src/skaembutils/deps-exe/s6-quote-filter create mode 100644 src/skaembutils/deps-exe/s6-rename create mode 100644 src/skaembutils/deps-exe/s6-rmrf create mode 100644 src/skaembutils/deps-exe/s6-sleep create mode 100644 src/skaembutils/deps-exe/s6-sort create mode 100644 src/skaembutils/deps-exe/s6-sync create mode 100644 src/skaembutils/deps-exe/s6-tail create mode 100644 src/skaembutils/deps-exe/s6-test create mode 100644 src/skaembutils/deps-exe/s6-touch create mode 100644 src/skaembutils/deps-exe/s6-true create mode 100644 src/skaembutils/deps-exe/s6-uniquename create mode 100644 src/skaembutils/deps-exe/s6-unquote create mode 100644 src/skaembutils/deps-exe/s6-unquote-filter create mode 100644 src/skaembutils/deps-exe/s6-update-symlinks create mode 100644 src/skaembutils/s6-basename.c create mode 100644 src/skaembutils/s6-cat.c create mode 100644 src/skaembutils/s6-chmod.c create mode 100644 src/skaembutils/s6-chown.c create mode 100644 src/skaembutils/s6-clock.c create mode 100644 src/skaembutils/s6-cut.c create mode 100644 src/skaembutils/s6-dirname.c create mode 100644 src/skaembutils/s6-echo.c create mode 100644 src/skaembutils/s6-env.c create mode 100644 src/skaembutils/s6-expr.c create mode 100644 src/skaembutils/s6-false.c create mode 100644 src/skaembutils/s6-format-filter.c create mode 100644 src/skaembutils/s6-grep.c create mode 100644 src/skaembutils/s6-head.c create mode 100644 src/skaembutils/s6-linkname.c create mode 100644 src/skaembutils/s6-ln.c create mode 100644 src/skaembutils/s6-ls.c create mode 100644 src/skaembutils/s6-maximumtime.c create mode 100644 src/skaembutils/s6-mkdir.c create mode 100644 src/skaembutils/s6-mkfifo.c create mode 100644 src/skaembutils/s6-nice.c create mode 100644 src/skaembutils/s6-nuke.c create mode 100644 src/skaembutils/s6-pause.c create mode 100644 src/skaembutils/s6-printenv.c create mode 100644 src/skaembutils/s6-quote-filter.c create mode 100644 src/skaembutils/s6-quote.c create mode 100644 src/skaembutils/s6-rename.c create mode 100644 src/skaembutils/s6-rmrf.c create mode 100644 src/skaembutils/s6-sleep.c create mode 100644 src/skaembutils/s6-sort.c create mode 100644 src/skaembutils/s6-sync.c create mode 100644 src/skaembutils/s6-tail.c create mode 100644 src/skaembutils/s6-test.c create mode 100644 src/skaembutils/s6-touch.c create mode 100644 src/skaembutils/s6-true.c create mode 100644 src/skaembutils/s6-uniquename.c create mode 100644 src/skaembutils/s6-unquote-filter.c create mode 100644 src/skaembutils/s6-unquote.c create mode 100644 src/skaembutils/s6-update-symlinks.c create mode 100755 tools/gen-deps.sh create mode 100755 tools/install.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5c6415e --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.o +*.a +*.lo +*.so +*.so.* diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..d2df44b --- /dev/null +++ b/AUTHORS @@ -0,0 +1,8 @@ +Main author: + Laurent Bercot + +Thanks to: + Dan J. Bernstein + Jean Marot + Jorge Almeida + Vallo Kallaste diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..9c67f65 --- /dev/null +++ b/CHANGES @@ -0,0 +1,62 @@ +20110701 + version: 0.10 +20110809 + bug: s6-head didn't handle chars properly + fix: rewrote variable management + version: 0.11 +20110822 + bug: s6-pause was incorrectly linked with libstddjb + impact: did not run when linked with libstddjb.so because of PROG + fix: :>deps-exe/s6-pause + version: 0.12 +20110929 + code: added s6-memoryhog + version: 0.13 +20111108 + bug: s6-ln.c did not define _ATFILE_SOURCE when needed + fix: trivial + version: 0.14 +20120110 + bug: s6-tail did not work with non-positive lines + fix: trivial + version: 0.15 +20120215 + internal: changed all bools from unsigned char to int +20120220 + version: 0.16 +20120327 + bug: potential crash (and wrong results) with s6-tail -c n when input is < n chars + impact: m( How many bugs can I leave in those stupid utilities ? + fix: added guard so n is never greater than the input length + version: 0.17 +20120929 + code: s6-update-symlinks accepts trailing slashes in dst + doc: fixed s6-update-symlinks.html +20130206 + build: switched to non-sp supporting build +20130212 + version: 1.0.0 +20130518 + bug: some binaries didn't link with flag-usert + fix: add `cat taianow.lib` to their deps-obj + version: 1.0.1 +20130913 + internal: removed deprecated calls +20130926 + version: 1.0.2 +20140327 + bug: s6-mkfifo respected umask + fix: add umask(0111) + version: 1.0.3 +20140409 + bug: segfault in s6-cut when passing dash filenames + fix: trivial +20140411 + build: changed to 4-number versioning + deps: moved to skalibs-1.6.0.0 +20140514 + version: 1.0.3.1 +20140604 + bug: wrong libexec directory in package/export + fix: trivial + version: 1.0.3.2 diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..63309ba --- /dev/null +++ b/COPYING @@ -0,0 +1,13 @@ +Copyright (c) 2011-2014 Laurent Bercot + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..f81ab06 --- /dev/null +++ b/INSTALL @@ -0,0 +1,118 @@ +Build Instructions +------------------ + +* Requirements + ------------ + + - A POSIX-compliant C development environment + - GNU make version 3.81 or later + - skalibs version 2.0.0.0 or later: http://skarnet.org/software/skalibs/ + + This software will run on any operating system that implements +POSIX.1-2008, available at: + http://pubs.opengroup.org/onlinepubs/9699919799/ + + +* Standard usage + -------------- + + ./configure && make && sudo make install + + will work for most users. + It will install the binaries in /bin. + + You can strip the binaries of their extra symbols via "make strip" +before the "make install" phase. It will shave a few bytes off them. + + +* Customization + ------------- + + You can customize paths via flags given to configure. + See ./configure --help for a list of all available configure options. + + +* Environment variables + --------------------- + + Controlling a build process via environment variables is a big and +dangerous hammer. You should try and pass flags to configure instead; +nevertheless, the standard environment variables are recognized. + + The value of the CROSS_COMPILE environment variable will prefix the +building tools' names. The --enable-cross option is preferred, see +"Cross-compilation" below. + + If the CC environment variable is set, its value will override compiler +detection by configure. + + The values of CFLAGS, CPPFLAGS and LDFLAGS will be appended to flags +auto-detected by configure. To entirely override the flags set by +configure, use make -e. + + The value of LDLIBS will be appended by make to command lines that link +an executable, even without the -e option. + + The Makefile supports the DESTDIR convention for staging. + + +* Static binaries + --------------- + + By default, binaries are linked against static versions of all the +libraries they depend on, except for the libc. You can enforce +linking against the static libc with --enable-static-libc. + + (If you are using a GNU/Linux system, be aware that the GNU libc +behaves badly with static linking and produces huge executables, +which is why it is not the default. Other libcs are better suited +to static linking, for instance musl: http://musl-libc.org/) + + +* Cross-compilation + ----------------- + + skarnet.org packages centralize all the difficulty of +cross-compilation in one place: skalibs. Once you have +cross-compiled skalibs, the rest is easy. + + Use the --enable-cross=PREFIX option to configure, or simply +--enable-cross if your default toolchain is a cross-compiling +toolchain. And make sure to use the correct version of skalibs +for your target, and the correct sysdeps directory, making use +of the --with-include, --with-lib, --with-dynlib and --with-sysdeps +options as necessary. + + +* The slashpackage convention + --------------------------- + + The slashpackage convention (http://cr.yp.to/slashpackage.html) +is a package installation scheme that provides a few guarantees +over other conventions such as the FHS, for instance fixed +absolute pathnames. skarnet.org packages support it: use the +--enable-slashpackage option to configure, or +--enable-slashpackage=DIR for a prefixed DIR/package tree. +This option will activate slashpackage support during the build +and set slashpackage-compatible installation directories. +Other options setting individual installation directories will be +ignored. + + When using slashpackage, two additional Makefile targets are +available after "make install": + - "make update" changes the default version of the software to the +freshly installed one. (This is useful when you have several installed +versions of the same software, which slashpackage supports.) + - "make -L global-links" adds links from /command and /library.so to the +default version of the binaries and shared libraries. The "-L" option to +make is necessary because targets are symbolic links, and the default make +behaviour is to check the pointed file's timestamp and not the symlink's +timestamp. + + +* Out-of-tree builds + ------------------ + + skarnet.org packages do not support out-of-tree builds. They +are small, so it does not cost much to duplicate the entire +source tree if parallel builds are needed. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7d8901c --- /dev/null +++ b/Makefile @@ -0,0 +1,121 @@ +# +# This Makefile requires GNU make. +# +# Do not make changes here. +# Use the included .mak files. +# + +it: all + +CC = $(error Please use ./configure first) + +include package/targets.mak +include package/deps.mak +-include config.mak + +version_m := $(basename $(version)) +version_M := $(basename $(version_m)) +version_l := $(basename $(version_M)) +CPPFLAGS_ALL := -iquote src/include-local -Isrc/include $(CPPFLAGS) +CFLAGS_ALL := $(CFLAGS) -pipe -Wall +CFLAGS_SHARED := -fPIC +LDFLAGS_ALL := $(LDFLAGS) +LDFLAGS_SHARED := -shared +LDLIBS_ALL := $(LDLIBS) +REALCC = $(CROSS_COMPILE)$(CC) +AR := $(CROSS_COMPILE)ar +RANLIB := $(CROSS_COMPILE)ranlib +STRIP := $(CROSS_COMPILE)strip +INSTALL := ./tools/install.sh + +ALL_BINS := $(LIBEXEC_TARGETS) $(BIN_TARGETS) $(SBIN_TARGETS) +ALL_LIBS := $(SHARED_LIBS) $(STATIC_LIBS) +ALL_INCLUDES := $(wildcard src/include/$(package)/*.h) + +all: $(ALL_LIBS) $(ALL_BINS) $(ALL_INCLUDES) + +clean: + @exec rm -f $(ALL_LIBS) $(ALL_BINS) $(wildcard src/*/*.o src/*/*.lo) + +distclean: clean + @exec rm -f config.mak src/include/${package}/config.h + +tgz: distclean + @. package/info && \ + rm -rf /tmp/$$package-$$version && \ + cp -a . /tmp/$$package-$$version && \ + cd /tmp && \ + tar -zpcv --owner=0 --group=0 --numeric-owner --exclude=.git* -f /tmp/$$package-$$version.tar.gz $$package-$$version && \ + exec rm -rf /tmp/$$package-$$version + +strip: $(ALL_LIBS) $(ALL_BINS) +ifneq ($(strip $(ALL_LIBS)),) + exec ${STRIP} -x -R .note -R .comment -R .note.GNU-stack $(ALL_LIBS) +endif +ifneq ($(strip $(ALL_BINS)),) + exec ${STRIP} -R .note -R .comment -R .note.GNU-stack $(ALL_BINS) +endif + +install: install-dynlib install-libexec install-bin install-sbin install-lib install-include +install-dynlib: $(SHARED_LIBS:lib%.so=$(DESTDIR)$(dynlibdir)/lib%.so) +install-libexec: $(LIBEXEC_TARGETS:%=$(DESTDIR)$(libexecdir)/%) +install-bin: $(BIN_TARGETS:%=$(DESTDIR)$(bindir)/%) +install-sbin: $(SBIN_TARGETS:%=$(DESTDIR)$(sbindir)/%) +install-lib: $(STATIC_LIBS:lib%.a=$(DESTDIR)$(libdir)/lib%.a) +install-include: $(ALL_INCLUDES:src/include/$(package)/%.h=$(DESTDIR)$(includedir)/$(package)/%.h) + +ifneq ($(exthome),) + +update: + exec $(INSTALL) -l $(notdir $(home)) $(DESTDIR)$(exthome) + +global-links: $(DESTDIR)$(exthome) $(SHARED_LIBS:lib%.so=$(DESTDIR)$(sproot)/library.so/lib%.so) $(BIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%) $(SBIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%) + +$(DESTDIR)$(sproot)/command/%: $(DESTDIR)$(home)/command/% + exec $(INSTALL) -D -l ..$(exthome)/command/$( + + Please use the mailing-list for +questions about s6-portable-utils. diff --git a/README.solaris b/README.solaris new file mode 100644 index 0000000..91a5b26 --- /dev/null +++ b/README.solaris @@ -0,0 +1,12 @@ + + This package assumes the existence of a POSIX shell in /bin/sh. + On Solaris, /bin/sh is not POSIX. Most versions of Solaris provide +a POSIX shell in /usr/xpg4/bin/sh. + + To compile this package on Solaris, you will need to run + + ./patch-for-solaris + + before you run ./configure. This script will change the #! invocation +of the configure script and various tools so that a POSIX shell is used +for the compilation process. diff --git a/configure b/configure new file mode 100755 index 0000000..552373d --- /dev/null +++ b/configure @@ -0,0 +1,383 @@ +#!/bin/sh + +usage () { +cat </dev/null 2>&1 && { echo "$1" ; return 0 ; } +$1 +EOF + echo "$1" | sed -e "s/'/'\\\\''/g" -e "1s/^/'/" -e "\$s/\$/'/" -e "s#^'\([-[:alnum:]_,./:]*\)=\(.*\)\$#\1='\2#" -e "s|\*/|* /|g" +} + +fail () { + echo "$*" + exit 1 +} + +fnmatch () { + eval "case \"\$2\" in $1) return 0 ;; *) return 1 ;; esac" +} + +cmdexists () { + type "$1" >/dev/null 2>&1 +} + +trycc () { + test -z "$CC_AUTO" && cmdexists "$1" && CC_AUTO=$1 +} + +stripdir () { + while eval "fnmatch '*/' \"\${$1}\"" ; do + eval "$1=\${$1%/}" + done +} + +tryflag () { + echo "checking whether compiler accepts $2 ..." + echo "typedef int x;" > "$tmpc" + if $CC_AUTO $CPPFLAGS_AUTO $CFLAGS_AUTO "$2" -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then + echo " ... yes" + eval "$1=\"\${$1} \$2\"" + eval "$1=\${$1# }" + return 0 + else + echo " ... no" + return 1 + fi +} + +tryldflag () { + echo "checking whether linker accepts $2 ..." + echo "typedef int x;" > "$tmpc" + if $CC_AUTO $CFLAGS_AUTO $LDFLAGS_AUTO -nostdlib "$2" -o /dev/null "$tmpc" >/dev/null 2>&1 ; then + echo " ... yes" + eval "$1=\"\${$1} \$2\"" + eval "$1=\${$1# }" + return 0 + else + echo " ... no" + return 1 + fi +} + + +# Actual script + +. package/info + +CC_AUTO="$CC" +CFLAGS_AUTO="$CFLAGS" +CPPFLAGS_AUTO="-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=600 $CPPFLAGS" +LDFLAGS_AUTO="$LDFLAGS" +LDFLAGS_NOSHARED= +prefix= +exec_prefix='$prefix' +dynlibdir='$prefix/lib' +libexecdir='$exec_prefix/libexec' +bindir='$exec_prefix/bin' +sbindir='$exec_prefix/sbin' +libdir='$prefix/usr/lib/'$package +includedir='$prefix/usr/include' +sysdeps='$prefix/usr/lib/skalibs/sysdeps' +manualsysdeps=false +shared=false +static=true +slashpackage=false +sproot= +home= +exthome= +allstatic=true +evenmorestatic=false +addincpath='' +addlibspath='' +addlibdpath='' +vpaths='' +vpathd='' +cross="$CROSS_COMPILE" + +for arg ; do + case "$arg" in + --help) usage ;; + --prefix=*) prefix=${arg#*=} ;; + --exec-prefix=*) exec_prefix=${arg#*=} ;; + --dynlibdir=*) dynlibdir=${arg#*=} ;; + --libexecdir=*) libexecdir=${arg#*=} ;; + --bindir=*) bindir=${arg#*=} ;; + --sbindir=*) sbindir=${arg#*=} ;; + --libdir=*) libdir=${arg#*=} ;; + --includedir=*) includedir=${arg#*=} ;; + --with-sysdeps=*) sysdeps=${arg#*=} manualsysdeps=true ;; + --with-include=*) var=${arg#*=} ; stripdir var ; addincpath="$addincpath -I$var" ;; + --with-lib=*) var=${arg#*=} ; stripdir var ; addlibspath="$addlibspath -L$var" ; vpaths="$vpaths $var" ;; + --with-dynlib=*) var=${arg#*=} ; stripdir var ; addlibdpath="$addlibdpath -L$var" ; vpathd="$vpathd $var" ;; + --enable-shared|--enable-shared=yes) shared=true ;; + --disable-shared|--enable-shared=no) shared=false ;; + --enable-static|--enable-static=yes) static=true ;; + --disable-static|--enable-static=no) static=false ;; + --enable-allstatic|--enable-allstatic=yes) allstatic=true ;; + --disable-allstatic|--enable-allstatic=no) allstatic=false ;; + --enable-static-libc|--enable-static-libc=yes) evenmorestatic=true ;; + --disable-static-libc|--enable-static-libc=no) evenmorestatic=false ;; + --enable-slashpackage=*) sproot=${arg#*=} ; slashpackage=true ; ;; + --enable-slashpackage) sproot= ; slashpackage=true ;; + --disable-slashpackage) sproot= ; slashpackage=false ;; + --enable-cross=*) cross=${arg#*=} ;; + --enable-cross) cross= ;; + --disable-cross) cross= ;; + --enable-*|--disable-*|--with-*|--without-*|--*dir=*|--build=*) ;; + --host=*|--target=*) target=${arg#*=} ;; + -* ) echo "$0: unknown option $arg" ;; + *=*) ;; + *) target=$arg ;; + esac +done + +for i in prefix exec_prefix dynlibdir libexecdir bindir sbindir libdir includedir linkdynlibdir linkbindir linksbindir sysdeps sproot skalibs ; do + eval tmp=\${$i} + eval $i=$tmp + stripdir $i +done + +# Get usable temp filenames +i=0 +set -C +while : ; do + i=$(($i+1)) + tmpc="./tmp-configure-$$-$PPID-$i.c" + tmpe="./tmp-configure-$$-$PPID-$i.tmp" + 2>|/dev/null > "$tmpc" && break + 2>|/dev/null > "$tmpe" && break + test "$i" -gt 50 && fail "$0: cannot create temporary files" +done +set +C +trap 'rm -f "$tmpc" "$tmpe"' EXIT ABRT INT QUIT TERM HUP + +# Set slashpackage values +if $slashpackage ; then + home=${sproot}/package/${category}/${package}-${version} + exthome=${sproot}/package/${category}/${package} + if $manualsysdeps ; then + : + else + sysdeps=${sproot}/package/prog/skalibs/sysdeps + fi + binprefix=${home}/command + extbinprefix=${exthome}/command + dynlibdir=${home}/library.so + libexecdir=$binprefix + bindir=$binprefix + sbindir=$binprefix + libdir=${home}/library + includedir=${home}/include + while read dep ; do + addincpath="$addincpath -I${sproot}${dep}/include" + vpaths="$vpaths ${sproot}${dep}/library" + addlibspath="$addlibspath -L${sproot}${dep}/library" + if $allstatic ; then : ; else + vpathd="$vpathd ${sproot}${dep}/library.so" + addlibdpath="$addlibdpath -L${sproot}${dep}/library.so" + fi + done < package/deps-build +fi + +# Find a C compiler to use +echo "checking for C compiler..." +trycc ${cross}gcc +trycc ${cross}c99 +trycc ${cross}cc +test -n "$CC_AUTO" || { echo "$0: cannot find a C compiler" ; exit 1 ; } +echo " ... $CC_AUTO" +echo "checking whether C compiler works... " +echo "typedef int x;" > "$tmpc" +if $CC_AUTO $CPPFLAGS_AUTO $CFLAGS_AUTO -c -o /dev/null "$tmpc" 2>"$tmpe" ; then + echo " ... yes" +else + echo " ... no. Compiler output follows:" + cat < "$tmpe" + exit 1 +fi + +echo "checking target system type..." +test -n "$target" || target=$($CC_AUTO -dumpmachine 2>/dev/null) || target=unknown +echo " ... $target" +if test ! -d $sysdeps || test ! -f $sysdeps/target ; then + echo "$0: error: $sysdeps is not a valid sysdeps directory" + exit 1 +fi +if [ "x$target" != "x$(cat $sysdeps/target)" ] ; then + echo "$0: error: target $target does not match the contents of $sysdeps/target" + exit 1 +fi + +rt_lib=$(cat $sysdeps/rt.lib) +socket_lib=$(cat $sysdeps/socket.lib) +sysclock_lib=$(cat $sysdeps/sysclock.lib) +tainnow_lib=$(cat $sysdeps/tainnow.lib) +util_lib=$(cat $sysdeps/util.lib) + +tryflag CFLAGS_AUTO -std=c99 +tryflag CFLAGS_AUTO -fomit-frame-pointer +tryflag CFLAGS_AUTO -fno-exceptions +tryflag CFLAGS_AUTO -fno-unwind-tables +tryflag CFLAGS_AUTO -fno-asynchronous-unwind-tables +tryflag CFLAGS_AUTO -Wa,--noexecstack +tryflag CFLAGS_AUTO -fno-stack-protector +tryflag CPPFLAGS_AUTO -Werror=implicit-function-declaration +tryflag CPPFLAGS_AUTO -Werror=implicit-int +tryflag CPPFLAGS_AUTO -Werror=pointer-sign +tryflag CPPFLAGS_AUTO -Werror=pointer-arith +tryflag CPPFLAGS_AUTO -Wno-parentheses +tryflag CPPFLAGS_AUTO -Wno-uninitialized +tryflag CPPFLAGS_AUTO -Wno-missing-braces +tryflag CPPFLAGS_AUTO -Wno-unused-value +tryflag CPPFLAGS_AUTO -Wno-unused-but-set-variable +tryflag CPPFLAGS_AUTO -Wno-unknown-pragmas +tryflag CPPFLAGS_AUTO -Wno-pointer-to-int-cast + +if $evenmorestatic ; then + LDFLAGS_NOSHARED=-static +fi + +if $shared ; then + tryldflag LDFLAGS_AUTO -Wl,--hash-style=both +fi + +if test -z "$vpaths" ; then + while read dep ; do + base=$(basename $dep) ; + vpaths="$vpaths /usr/lib/$base" + addlibspath="$addlibspath -L/usr/lib/$base" + done < package/deps-build +fi + +CPPFLAGS_AUTO="$CPPFLAGS_AUTO $addincpath" +LDFLAGS_AUTO="$LDFLAGS_AUTO $addlibspath" +$allstatic || LDFLAGS_AUTO="$LDFLAGS_AUTO $addlibdpath" + +echo "creating config.mak..." +cmdline=$(quote "$0") +for i ; do cmdline="$cmdline $(quote "$i")" ; done +exec 3>&1 1>config.mak +cat << EOF +# This file was generated by: +# $cmdline +# Any changes made here will be lost if configure is re-run. + +target := $target +package := $package +prefix := $prefix +exec_prefix := $exec_prefix +dynlibdir := $dynlibdir +libexecdir := $libexecdir +bindir := $bindir +sbindir := $sbindir +libdir := $libdir +includedir := $includedir +sysdeps := $sysdeps +slashpackage := $slashpackage +sp_root := $sproot +version := $version +home := $home +exthome := $exthome +RT_LIB := ${rt_lib} +SOCKET_LIB := ${socket_lib} +SYSCLOCK_LIB := ${sysclock_lib} +TAINNOW_LIB := ${tainnow_lib} +UTIL_LIB := ${util_lib} + +CC := $CC_AUTO +CFLAGS := $CFLAGS_AUTO +CPPFLAGS := $CPPFLAGS_AUTO +LDFLAGS := $LDFLAGS_AUTO +LDFLAGS_NOSHARED := $LDFLAGS_NOSHARED +CROSS_COMPILE := $cross + +vpath lib%a$vpaths +EOF +if $allstatic ; then + echo ".LIBPATTERNS := lib%.a" + vpathd= +fi + echo "vpath lib%.so$vpathd" +echo +$static || echo "STATIC_LIBS :=" +$shared || echo "SHARED_LIBS :=" +exec 1>&3 3>&- +echo " ... done." + +echo "creating src/include/${package}/config.h..." +mkdir -p -m 0755 src/include/${package} +exec 3>&1 1> src/include/${package}/config.h +cat <&3 3>&- +echo " ... done." diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000..1775002 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,162 @@ + + + + + s6-portable-utils - skarnet.org's tiny general Unix utilities + + + + + + +

+Software
+skarnet.org +

+ +

s6-portable-utils

+ + + +

What is it ?

+ +

+ s6-portable-utils is a set of tiny general Unix utilities, often +performing well-known tasks such as cut and grep, +but optimized for simplicity and small size. They were designed +for embedded systems and other constrained environments, but they +work everywhere. +

+ +

+ Other set of small utilities are usually system-specific; for +instance, the (otherwise excellent) +BusyBox project only works on Linux. +

+ +

+ Some of s6-portable-utils' programs are a conformant implementation +of a POSIX utility as determined by the +Single +Unix Specification, version 4; the relevant documentation pages mentions +this. +However, none of the s6-portable-utils programs supports internationalization. +

+ +

+It is now an explicit non-goal of s6-portable-utils to duplicate the work of +existing projects that aim to provide a lightweight implementation of +standard commands. + No more rewriting of standard commands will occur in s6-portable-utils; +the package is now used to host specific utilities such as +s6-uniquename. +

+ +
+ +

Installation

+ +

Requirements

+ +
    +
  • A POSIX-compliant system with a standard C development environment
  • +
  • GNU make, version 3.81 or later
  • +
  • skalibs version +2.0.0.0 or later
  • +
+ +

Licensing

+ +

+ s6-portable-utils is free software. It is available under the +ISC license. +

+ +

Download

+ +
    +
  • The current released version of s6-portable-utils is +2.0.0.0.
  • +
  • Alternatively, you can checkout a copy of the s6-portable-utils git repository: +
     git clone git://git.skarnet.org/s6-portable-utils 
  • +
+ +

Compilation

+ +
    +
  • See the enclosed INSTALL file for installation details.
  • +
+ +

Upgrade notes

+ +
    +
  • This page lists the differences to be aware of between +the previous versions of s6-portable-utils and the current one.
  • +
+ +
+ +

Reference

+ +

Commands

+ +

+ All these commands exit 111 if they encounter a temporary error, and +100 if they encounter a permanent error - such as a misuse. +

+ + + +

Related resources

+ +
    +
  • s6-portable-utils is discussed on the +skaware mailing-list.
  • + +
+ + + diff --git a/doc/s6-basename.html b/doc/s6-basename.html new file mode 100644 index 0000000..b656599 --- /dev/null +++ b/doc/s6-basename.html @@ -0,0 +1,50 @@ + + + + + s6-portable-utils: the s6-basename program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-basename program

+ +

+ s6-basename prints the basename of a pathname. +

+ +

Interface

+ +
+     s6-basename [ -n ] path [ suffix ]
+
+ +

+ s6-basename acts as the generic +basename utility. +

+ +

Extra options

+ +
    +
  • -n : do not print a trailing newline after the output.
  • +
+ +

Posixness

+ +

+ s6-basename is suitable as a Single Unix +basename +program. +

+ + + diff --git a/doc/s6-cat.html b/doc/s6-cat.html new file mode 100644 index 0000000..71610e8 --- /dev/null +++ b/doc/s6-cat.html @@ -0,0 +1,51 @@ + + + + + s6-portable-utils: the s6-cat program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-cat program

+ +

+ s6-cat copies stdin to stdout. +

+ +

Interface

+ +
+     s6-cat
+
+ +

+ s6-cat transfers data from stdin to stdout, until it receives EOF or +gets killed. +

+ +

Notes

+ +

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

+ +

Posixness

+ +

+ s6-cat is not suitable as a Single Unix +cat +program. +

+ + + diff --git a/doc/s6-chmod.html b/doc/s6-chmod.html new file mode 100644 index 0000000..165790c --- /dev/null +++ b/doc/s6-chmod.html @@ -0,0 +1,45 @@ + + + + + s6-portable-utils: the s6-chmod program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-chmod program

+ +

+ s6-chmod changes the permissions of a file. +

+ +

Interface

+ +
+     s6-chmod perms file
+
+ +

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

+ +

Posixness

+ +

+ s6-chmod is not suitable as a Single Unix +chmod +program. +

+ + + diff --git a/doc/s6-chown.html b/doc/s6-chown.html new file mode 100644 index 0000000..0cbbe57 --- /dev/null +++ b/doc/s6-chown.html @@ -0,0 +1,52 @@ + + + + + s6-portable-utils: the s6-chown program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-chown program

+ +

+ s6-chown changes the owner and/or group of a file. +

+ +

Interface

+ +
+     s6-chown [ -U ] [ -u uid ] [ -g gid ] file
+
+ +
    +
  • s6-chown changes file's owner to (numeric) uid and group +to (numeric) gid.
  • +
  • If uid isn't provided, the owner remains the same; if gid +isn't provided, the group remains the same.
  • +
  • The -U option sets uid to the value of the UID +environment variable and gid to the value of the GID environment variable. +This makes s6-chown easily usable with +s6-envuidgid: + s6-envuidgid account s6-chown -U file changes file's uid and +gid to account's.
  • +
+ +

Posixness

+ +

+ s6-chown is not suitable as a Single Unix +chown +program. +

+ + + diff --git a/doc/s6-clock.html b/doc/s6-clock.html new file mode 100644 index 0000000..37e05ec --- /dev/null +++ b/doc/s6-clock.html @@ -0,0 +1,54 @@ + + + + + s6-portable-utils: the s6-clock program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-clock program

+ +

+ s6-clock gets or sets the system clock. +

+ +

Interface

+ +
+     s6-clock [ label ]
+
+ +

+ When called without an argument, s6-clock writes the current system +time, as a +TAI64N +timestamp, to stdout. +

+ +

+ When given an argument label, which must be a +TAI64N +timestamp, s6-clock sets the system time to this value. +

+ +

Notes

+ +

+ s6-clock only prints or accepts TAI time, no matter what the system clock is set +to (TAI-10 or UTC); it will automatically make the right conversions for your +system clock. Make sure your +skalibs has been built with +the right settings. +

+ + + diff --git a/doc/s6-cut.html b/doc/s6-cut.html new file mode 100644 index 0000000..2d93762 --- /dev/null +++ b/doc/s6-cut.html @@ -0,0 +1,44 @@ + + + + + s6-portable-utils: the s6-cut program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-cut program

+ +

+ s6-cut prints selected portions of the lines of its input. +

+ +

Interface

+ +
+     s6-cut [ -b list | -c list | -f list ] [ -n ] [ -s ] [ file ... ]
+
+ +

+ s6-cut acts as the generic +cut utility. +

+ +

Posixness

+ +

+ s6-cut is suitable as a Single Unix +cut +program. +

+ + + diff --git a/doc/s6-dirname.html b/doc/s6-dirname.html new file mode 100644 index 0000000..4fee876 --- /dev/null +++ b/doc/s6-dirname.html @@ -0,0 +1,50 @@ + + + + + s6-portable-utils: the s6-dirname program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-dirname program

+ +

+ s6-dirname prints the dirname of a path. +

+ +

Interface

+ +
+     s6-dirname [ -n ] path
+
+ +

+ s6-dirname acts as the generic +dirname utility. +

+ +

Extra options

+ +
    +
  • -n : do not print a trailing newline after the output.
  • +
+ +

Posixness

+ +

+ s6-dirname is suitable as a Single Unix +dirname +program. +

+ + + diff --git a/doc/s6-echo.html b/doc/s6-echo.html new file mode 100644 index 0000000..5cbcc88 --- /dev/null +++ b/doc/s6-echo.html @@ -0,0 +1,51 @@ + + + + + s6-portable-utils: the s6-echo program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-echo program

+ +

+ s6-echo writes its arguments to stdout. +

+ +

Interface

+ +
+     s6-echo [ -n ] [ -s sep ] args...
+
+ +

+ s6-echo writes its arguments args to stdout, separated with spaces. +

+ +

Options

+ +
    +
  • -n : do not output a trailing newline.
  • +
  •  -s sep : separate arguments with the sep +character instead of a space.
  • +
+ +

Posixness

+ +

+ s6-echo is not suitable as a Single Unix +echo +program. +

+ + + diff --git a/doc/s6-env.html b/doc/s6-env.html new file mode 100644 index 0000000..fa53a45 --- /dev/null +++ b/doc/s6-env.html @@ -0,0 +1,45 @@ + + + + + s6-portable-utils: the s6-env program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-env program

+ +

+s6-env prints the current environment or modifies the environment +before running a program. +

+ +

Interface

+ +
+     s6-env [ -i ] [ name=value... ] [ prog... ]
+
+ +

+ s6-env acts as the generic +env utility. +

+ +

Posixness

+ +

+ s6-env is suitable as a Single Unix +env +program. +

+ + + diff --git a/doc/s6-expr.html b/doc/s6-expr.html new file mode 100644 index 0000000..b535eb6 --- /dev/null +++ b/doc/s6-expr.html @@ -0,0 +1,50 @@ + + + + + s6-portable-utils: the s6-expr program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-expr program

+ +

+ s6-expr evaluates an expression and writes the result to stdout. +

+ +

Interface

+ +
+     s6-expr expression...
+
+ +

+ s6-expr acts as the generic +expr utility, +except that the : operator (pattern matching) is not supported. +

+ +

+ s6-expr accepts an arbitrary number of arguments. +

+ +

Posixness

+ +

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

+ + + diff --git a/doc/s6-false.html b/doc/s6-false.html new file mode 100644 index 0000000..4b21046 --- /dev/null +++ b/doc/s6-false.html @@ -0,0 +1,39 @@ + + + + + s6-portable-utils: the s6-false program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-false program

+ +

+ s6-false returns 1. +

+ +

Interface

+ +
+     s6-false
+
+ +

Posixness

+ +

+ s6-false is suitable as a Single Unix +false +program. +

+ + + diff --git a/doc/s6-format-filter.html b/doc/s6-format-filter.html new file mode 100644 index 0000000..4492786 --- /dev/null +++ b/doc/s6-format-filter.html @@ -0,0 +1,42 @@ + + + + + s6-portable-utils: the s6-format-filter program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-format-filter program

+ +

+s6-format-filter processes lines according to its arguments, and +prints the result. +

+ +

Interface

+ +
+     s6-format-filter format [ args... ]
+
+ +
    +
  • format is a format string that can contain the following special sequences: +%%, %s, and %0 to %9.
  • +
  • For every line it reads on stdin, s6-format-filter prints format on +stdout, replacing %% with %, %0 with the command name +(probably s6-format-filter), %1 to %9 with the first +to the ninth argument in args, and %s with the input line.
  • +
  • s6-format-filter exits 0 when it reads EOF.
  • +
+ + + diff --git a/doc/s6-grep.html b/doc/s6-grep.html new file mode 100644 index 0000000..fc0cb1b --- /dev/null +++ b/doc/s6-grep.html @@ -0,0 +1,67 @@ + + + + + s6-portable-utils: the s6-grep program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-grep program

+ +

+ s6-grep matches its input against a pattern. +

+ +

Interface

+ +
+     s6-grep [ -E | -F ] [ -i ] [ -c ] [ -n ] [ -q ] [ -v ] pattern
+
+ +
    +
  • s6-grep compiles pattern as an +Basic +Regular Expression
  • +
  • It reads stdin and matches every line against this regexp
  • +
  • If the line matches, it prints it to stdout
  • +
  • It exits on EOF with code 0 if one or more lines matched and 1 +otherwise.
  • +
+ +

Options

+ +
    +
  • -F : pattern is not compiled as a BRE, but is +interpreted as a literal string.
  • +
  • -E : pattern is not compiled as a BRE, but as an +Extended +Regular Expression (ERE).
  • +
  • -i : ignore case during the match
  • +
  • -c : do not write normal output; only write the number of +lines that have matched pattern after EOF is received
  • +
  • -n : precede every output line by its number and a colon. +The first input line has number 1.
  • +
  • -q : do not write anything to stdout
  • +
  • -v : invert the pattern matching (select lines that do not +match pattern).
  • +
+ +

Posixness

+ +

+ s6-grep is not suitable as a Single Unix +grep +program. +

+ + + diff --git a/doc/s6-head.html b/doc/s6-head.html new file mode 100644 index 0000000..3fd3360 --- /dev/null +++ b/doc/s6-head.html @@ -0,0 +1,55 @@ + + + + + s6-portable-utils: the s6-head program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-head program

+ +

+ s6-head prints the first lines of its input files. +

+ +

Interface

+ +
+     s6-head [ -S ] [ -1..9 | -n lines | -c chars ] file...
+
+ +

+ s6-head acts as the generic +head utility. +

+ +

Extra options

+ +
    +
  • -S : safe mode. s6-head stops reading its input files right after +getting all the lines it needs. The rest of the stream can then be handled by other +utilities without any data loss.
  • +
  • -1..9 : equivalent to -n 1 .. -n 9.
  • +
  • -c chars : cuts after chars characters instead +of lines lines.
  • +
+ +

Posixness

+ +

+ s6-head is suitable as a Single Unix +head +program. +

+ + + diff --git a/doc/s6-linkname.html b/doc/s6-linkname.html new file mode 100644 index 0000000..e4caf84 --- /dev/null +++ b/doc/s6-linkname.html @@ -0,0 +1,45 @@ + + + + + s6-portable-utils: the s6-linkname program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-linkname program

+ +

+ s6-linkname gives the content of a symbolic link or resolves a path. +

+ +

Interface

+ +
+     s6-linkname [ -f ] path
+
+ +
    +
  • If path is a symbolic link, s6-linkname prints its +content then exits 0.
  • +
  • Else it prints an error message and exits 111.
  • +
+ +

Options

+ +
    +
  • -f : s6-linkname fully resolves path then +prints the result on stdout. path does not have to be a symbolic +link.
  • +
+ + + diff --git a/doc/s6-ln.html b/doc/s6-ln.html new file mode 100644 index 0000000..392476f --- /dev/null +++ b/doc/s6-ln.html @@ -0,0 +1,44 @@ + + + + + s6-portable-utils: the s6-ln program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-ln program

+ +

+ s6-ln creates a link to a file. +

+ +

Interface

+ +
+     s6-ln [ -s ] [ -f ] [ -L ] [ -P ] old new
+
+ +

+ s6-ln acts as the generic +ln utility. +

+ +

Posixness

+ +

+ s6-ln is suitable as a Single Unix +ln +program. +

+ + + diff --git a/doc/s6-ls.html b/doc/s6-ls.html new file mode 100644 index 0000000..492ea25 --- /dev/null +++ b/doc/s6-ls.html @@ -0,0 +1,57 @@ + + + + + s6-portable-utils: the s6-ls program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-ls program

+ +

+ s6-ls lists the contents of a directory. +

+ +

Interface

+ +
+     s6-ls [ -0 ] [ -a | -A ] [ -x exclude ] dir
+
+ +

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

+ +

Options

+ +
    +
  • -0 : separate file names with a null character +instead of a newline.
  • +
  • -a : do not omit files starting with a dot. Do +not list . or .. though.
  • +
  • -A : do not omit files starting with a dot, even +. and ..
  • +
  • -x exclude : if a file name is +exclude, do not print it.
  • +
+ +

Posixness

+ +

+ s6-ls is not suitable as a Single Unix +ls +program. +

+ + + diff --git a/doc/s6-maximumtime.html b/doc/s6-maximumtime.html new file mode 100644 index 0000000..eea72b3 --- /dev/null +++ b/doc/s6-maximumtime.html @@ -0,0 +1,53 @@ + + + + + s6-portable-utils: the s6-maximumtime program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-maximumtime program

+ +

+ s6-maximumtime executes a program with a time limit. +

+ +

Interface

+ +
+     s6-maximumtime [ -0 | -a | -b | -i | -k | -q | -t | -x | -1 | -2 ] milli prog...
+
+ +
    +
  • s6-maximumtime forks and execs prog... as a child.
  • +
  • If milli milliseconds elapse before prog exits, +s6-maximumtime sends it a signal and exits 99 with a message.
  • +
  • Else s6-maximumtime exits with the same exit code as prog.
  • +
+ +

Options

+ +
    +
  • -0 : on timeout, do not send any signal, just exit
  • +
  • -a : on timeout, send a SIGALRM
  • +
  • -b : on timeout, send a SIGABRT
  • +
  • -i : on timeout, send a SIGINT
  • +
  • -k : on timeout, send a SIGKILL
  • +
  • -q : on timeout, send a SIGQUIT
  • +
  • -t : on timeout, send a SIGTERM - this is the default
  • +
  • -x : on timeout, send a SIGXCPU
  • +
  • -1 : on timeout, send a SIGUSR1
  • +
  • -2 : on timeout, send a SIGUSR2
  • +
+ + + diff --git a/doc/s6-mkdir.html b/doc/s6-mkdir.html new file mode 100644 index 0000000..8dd0e02 --- /dev/null +++ b/doc/s6-mkdir.html @@ -0,0 +1,50 @@ + + + + + s6-portable-utils: the s6-mkdir program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-mkdir program

+ +

+ s6-mkdir creates directories. +

+ +

Interface

+ +
+     s6-mkdir [ -p ] [ -v ] [ -m mode ] [ dir... ]
+
+ +

+ s6-mkdir acts as the generic +mkdir utility. +

+ +

Extra options

+ +
    +
  • -v : write what it does to stderr.
  • +
+ +

Posixness

+ +

+ s6-mkdir is suitable as a Single Unix +mkdir +program. +

+ + + diff --git a/doc/s6-mkfifo.html b/doc/s6-mkfifo.html new file mode 100644 index 0000000..5f38072 --- /dev/null +++ b/doc/s6-mkfifo.html @@ -0,0 +1,44 @@ + + + + + s6-portable-utils: the s6-mkfifo program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-mkfifo program

+ +

+ s6-mkfifo creates FIFOs, a.k.a. named pipes. +

+ +

Interface

+ +
+     s6-mkfifo [ -m mode ] [ fifo... ]
+
+ +

+ s6-mkfifo acts as the generic +mkfifo utility. +

+ +

Posixness

+ +

+ s6-mkfifo is suitable as a Single Unix +mkfifo +program. +

+ + + diff --git a/doc/s6-nice.html b/doc/s6-nice.html new file mode 100644 index 0000000..98149c8 --- /dev/null +++ b/doc/s6-nice.html @@ -0,0 +1,53 @@ + + + + + s6-portable-utils: the s6-nice program + + + + + + +

+s6-portable-utils
+Software
+www.skarnet.org +

+ +

The s6-nice program

+ +

+ s6-nice executes into a program with an altered nice value. +

+ +

Interface

+ +
+     s6-nice [ -I | -i ] [ -n value ] [ prog... ]
+
+ +

+ s6-nice acts as the generic +nice utility. +

+ +

Extra options

+ +
    +
  • -I : loose. If the nice value cannot be set to value, +print a warning message and exec into prog... anyway. This is the default.
  • +
  • -i : strict. If the nice value cannot be set to value, +exit 111 with an error message. +
+ +

Posixness

+ +

+ s6-nice is suitable as a Single Unix +nice +program. +

+ + + diff --git a/doc/s6-nuke.html b/doc/s6-nuke.html new file mode 100644 index 0000000..3db674c --- /dev/null +++ b/doc/s6-nuke.html @@ -0,0 +1,56 @@ + + + + + s6-portable-utils: the s6-nuke program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-nuke program

+ +

+ s6-nuke sends signals to every process it is allowed to send. +

+ +

Interface

+ +
+     s6-nuke [ -h | -t | -k ]
+
+ +
    +
  • Depending on the options it is given, s6-nuke sends signals to +all processes; depending on s6-nuke's rights, not all processes may +receive them.
  • +
  • s6-nuke protects itself against the signals it sends (which +doesn't do much good against SIGKILL). If it survives the blast, +it exits 0.
  • +
+ +

Options

+ +
    +
  • -h : send a SIGHUP
  • +
  • -t : send a SIGTERM then a SIGCONT
  • +
  • -k : send a SIGKILL
  • +
+ +

Usage notes

+ +

+ s6-nuke can be used during the shutdown procedure of a system, which is +described +here. +

+ + + diff --git a/doc/s6-pause.html b/doc/s6-pause.html new file mode 100644 index 0000000..edb129f --- /dev/null +++ b/doc/s6-pause.html @@ -0,0 +1,39 @@ + + + + + s6-portable-utils: the s6-pause program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-pause program

+ +

+ s6-pause blocks until it is killed. +

+ +

Interface

+ +
+     s6-pause
+
+ +

Usage notes

+ +

+ s6-pause is one of the smallest possible long-lived programs. It can be +used to emulate a running service with the least possible resource +consumption. +

+ + + diff --git a/doc/s6-printenv.html b/doc/s6-printenv.html new file mode 100644 index 0000000..96216ab --- /dev/null +++ b/doc/s6-printenv.html @@ -0,0 +1,46 @@ + + + + + s6-portable-utils: the s6-printenv program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-printenv program

+ +

+ s6-printenv prints its environment variables. +

+ +

Interface

+ +
+     s6-printenv [ -n ] [ -0 | -d delim ]
+
+ +

+ s6-printenv prints its environment on stdout, like +s6-env. +

+ +

Options

+ +
    +
  • -0 : separate file names with a null character +instead of a newline.
  • +
  • -d delim : separate file names with the +first character of delim instead of a newline
  • +
  • -n : omit the last delimiter character
  • +
+ + + diff --git a/doc/s6-quote-filter.html b/doc/s6-quote-filter.html new file mode 100644 index 0000000..867acbe --- /dev/null +++ b/doc/s6-quote-filter.html @@ -0,0 +1,56 @@ + + + + + s6-portable-utils: the s6-quote-filter program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-quote-filter program

+ +

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

+ +

Interface

+ +
+     s6-quote-filter [ -u ] [ -d delim ]
+
+ +
    +
  • s6-quote reads lines on stdin; it quotes every line, putting it inside double quotes +and escaping all dubious characters
  • +
  • It writes the quoted strings to stdout
  • +
  • It exits 0 on EOF
  • +
+ +

Options

+ +
    +
  • -u : do not put read lines inside double quotes, only escape +characters if needed
  • +
  • -d delim : use the first character of delim +as a quote character, instead of double quotes
  • +
+ +

Notes

+ +
    +
  • Quoted strings are guaranteed to be pure printable ASCII, without control characters.
  • +
  • Quoted strings can be unquoted via the s6-unquote or +s6-unquote-filter programs.
  • +
+ + + diff --git a/doc/s6-quote.html b/doc/s6-quote.html new file mode 100644 index 0000000..a24069f --- /dev/null +++ b/doc/s6-quote.html @@ -0,0 +1,57 @@ + + + + + s6-portable-utils: the s6-quote program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-quote program

+ +

+ s6-quote quotes a string and writes it to stdout. +

+ +

Interface

+ +
+     s6-quote [ -n ] [ -u ] [ -d delim ] string
+
+ +
    +
  • s6-quote quotes string, putting it inside double quotes +and escaping all dubious characters
  • +
  • It writes the quoted string to stdout and exits 0
  • +
+ +

Options

+ +
    +
  • -n : do not print a trailing newline
  • +
  • -u : do not put string inside double quotes, only escape +characters if needed
  • +
  • -d delim : use the first character of delim +as a quote character, instead of double quotes
  • +
+ +

Notes

+ +
    +
  • Quoted strings are guaranteed to be pure printable ASCII, without control characters.
  • +
  • Quoted strings can be unquoted via the s6-unquote or +s6-unquote-filter programs.
  • +
  • Quoted strings are suitable for interpretation by +execlineb.
  • +
+ + + diff --git a/doc/s6-rename.html b/doc/s6-rename.html new file mode 100644 index 0000000..1691328 --- /dev/null +++ b/doc/s6-rename.html @@ -0,0 +1,35 @@ + + + + + s6-portable-utils: the s6-rename program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-rename program

+ +

+ s6-rename atomically renames a file. +

+ +

Interface

+ +
+     s6-rename old new
+
+ +

+ s6-rename atomically renames old to new. +

+ + + diff --git a/doc/s6-rmrf.html b/doc/s6-rmrf.html new file mode 100644 index 0000000..ccbded4 --- /dev/null +++ b/doc/s6-rmrf.html @@ -0,0 +1,35 @@ + + + + + s6-portable-utils: the s6-rmrf program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-rmrf program

+ +

+ s6-rmrf removes a file or directory tree entirely. +

+ +

Interface

+ +
+     s6-rmrf subtree
+
+ +

+ s6-rmrf removes the subtree file hierarchy. +

+ + + diff --git a/doc/s6-sleep.html b/doc/s6-sleep.html new file mode 100644 index 0000000..68137d3 --- /dev/null +++ b/doc/s6-sleep.html @@ -0,0 +1,51 @@ + + + + + s6-portable-utils: the s6-sleep program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-sleep program

+ +

+ s6-sleep sleeps for a given time. +

+ +

Interface

+ +
+     s6-sleep [ -m ] time
+
+ +

+ s6-sleep acts as the generic +sleep utility. +It ignores non-lethal signals. +

+ +

Extra options

+ +
    +
  • -m : Interpret time as milliseconds instead of seconds.
  • +
+ +

Posixness

+ +

+ s6-sleep is suitable as a Single Unix +sleep +program. +

+ + + diff --git a/doc/s6-sort.html b/doc/s6-sort.html new file mode 100644 index 0000000..5e2d468 --- /dev/null +++ b/doc/s6-sort.html @@ -0,0 +1,59 @@ + + + + + s6-portable-utils: the s6-sort program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-sort program

+ +

+ s6-sort sorts its input. +

+ +

Interface

+ +
+     s6-sort [ -b ] [ -c ] [ -f ] [ -r ] [ -u ] [ -0 ]
+
+ +
    +
  • s6-sort reads its stdin until EOF
  • +
  • It sorts all the lines it read alphanumerically
  • +
  • It prints the sorted lines to stdout and exits 0
  • +
+ +

Options

+ +
    +
  • -b : ignore leading spaces and tabs at the beginning of each +line when sorting
  • +
  • -c : suppresses normal output, just returns 0 if the output +would have been the same as the input and 1 otherwise
  • +
  • -f : ignore case when sorting
  • +
  • -r : reverse sort
  • +
  • -u : suppresses duplicate lines
  • +
  • -0 : input and output lines are separated by null characters +instead of newlines
  • +
+ +

Posixness

+ +

+ s6-sort is not suitable as a Single Unix +sort +program. +

+ + + diff --git a/doc/s6-sync.html b/doc/s6-sync.html new file mode 100644 index 0000000..daf88f3 --- /dev/null +++ b/doc/s6-sync.html @@ -0,0 +1,32 @@ + + + + + s6-portable-utils: the s6-sync program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-sync program

+ +

+ s6-sync flushes all the dirty system buffers, and blocks until they're +clean. +

+ +

Interface

+ +
+     s6-sync
+
+ + + diff --git a/doc/s6-tail.html b/doc/s6-tail.html new file mode 100644 index 0000000..abf2b76 --- /dev/null +++ b/doc/s6-tail.html @@ -0,0 +1,46 @@ + + + + + s6-portable-utils: the s6-tail program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-tail program

+ +

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

+ +

Interface

+ +
+     s6-tail [ -n lines | -c chars ] [ file ]
+
+ +

+ s6-tail acts as the generic +tail utility, +except that the -f option is not supported. +

+ +

Posixness

+ +

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

+ + + diff --git a/doc/s6-test.html b/doc/s6-test.html new file mode 100644 index 0000000..22b6fbd --- /dev/null +++ b/doc/s6-test.html @@ -0,0 +1,53 @@ + + + + + s6-portable-utils: the s6-test program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-test program

+ +

+ s6-test evaluates an expression and indicates the result via its +exit status. +

+ +

Interface

+ +
+     s6-test expression...
+
+ +

+ s6-test acts as the generic +test utility, +but it diverges from the specification on one point: if an argument starts with a backslash, +this backslash is ignored (and the argument cannot be an operation). This is a simple +disambiguation technique that has unfortunately not been chosen by the standard. +

+ +

+ s6-test accepts an arbitrary number of arguments. +

+ +

Posixness

+ +

+ s6-test is not suitable as a Single Unix +test +program; however, if your arguments never start with a backslash, it exhibits the +exact same behaviour. +

+ + + diff --git a/doc/s6-touch.html b/doc/s6-touch.html new file mode 100644 index 0000000..ccc40ca --- /dev/null +++ b/doc/s6-touch.html @@ -0,0 +1,45 @@ + + + + + s6-portable-utils: the s6-touch program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-touch program

+ +

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

+ +

Interface

+ +
+     s6-touch file...
+
+ +

+ s6-touch touches every file in the list by opening them for appending +then closing them. +

+ +

Posixness

+ +

+ s6-touch is not suitable as a Single Unix +touch +program. +

+ + + diff --git a/doc/s6-true.html b/doc/s6-true.html new file mode 100644 index 0000000..60ec1c7 --- /dev/null +++ b/doc/s6-true.html @@ -0,0 +1,39 @@ + + + + + s6-portable-utils: the s6-true program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-true program

+ +

+ s6-true returns 0. +

+ +

Interface

+ +
+     s6-true
+
+ +

Posixness

+ +

+ s6-true is suitable as a Single Unix +true +program. +

+ + + diff --git a/doc/s6-uniquename.html b/doc/s6-uniquename.html new file mode 100644 index 0000000..7315d9b --- /dev/null +++ b/doc/s6-uniquename.html @@ -0,0 +1,45 @@ + + + + + s6-portable-utils: the s6-uniquename program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-uniquename program

+ +

+ s6-uniquename creates a guaranteed unique file name and prints it to stdout. +

+ +

Interface

+ +
+     s6-uniquename [ -n randomlen ] prefix
+
+ +
    +
  • s6-uniquename creates a unique filename starting with prefix +involving a TAI64N timestamp, the machine's FQDN and the process' PID.
  • +
  • It prints it to stdout and exits 0.
  • +
+ +

Options

+ +
    +
  • -n randomlen : for added security, also +add a random readable string of randomlen characters to the +created pathname.
  • +
+ + + diff --git a/doc/s6-unquote-filter.html b/doc/s6-unquote-filter.html new file mode 100644 index 0000000..7262722 --- /dev/null +++ b/doc/s6-unquote-filter.html @@ -0,0 +1,69 @@ + + + + + s6-portable-utils: the s6-unquote-filter program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-unquote-filter program

+ +

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

+ +

Interface

+ +
+     s6-unquote-filter [ -q | -Q | -v | -w ] [ -d delim ]
+
+ +
    +
  • s6-unquote-filter reads lines on stdin. It exits 0 on EOF.
  • +
  • It expects read lines to follow the +syntax of s6-quote's output strings
  • +
  • Depending on the strictness options, it prints various warning +or error messages to stderr if it cannot properly unquote lines. In +the very strict mode, it exits 100 on the first unquoting error.
  • +
  • If it is successful at unquoting, it prints the resulting +lines to stdout.
  • +
+ +

Options

+ +
    +
  • -d delim : a list of characters that +will be considered as delimitors (to start and end the quoted string). +By default, only the double quote is such a character. If delim +is the empty string, s6-unquote-filter interprets string as +non-delimited, only escaped (i.e. for instance the result of some +s6-quote-filter -u operation).
  • +
  • -q : loose/quiet mode. s6-unquote-filter will +silently accommodate errors.
  • +
  • -Q : normal mode. This is the default. s6-unquote-filter +will warn on errors.
  • +
  • -v : strict/verbose mode. s6-unquote-filter will +warn loudly on errors, with many details.
  • +
  • -w : very strict mode. s6-unquote-filter will complain +and die on the first unquoting error it encounters.
  • +
+ +

Notes

+ + + + + diff --git a/doc/s6-unquote.html b/doc/s6-unquote.html new file mode 100644 index 0000000..546082e --- /dev/null +++ b/doc/s6-unquote.html @@ -0,0 +1,58 @@ + + + + + s6-portable-utils: the s6-unquote program + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

The s6-unquote program

+ +

+ s6-unquote unquotes a quoted string and writes it to stdout. +

+ +

Interface

+ +
+     s6-unquote [ -n ] [ -d delim ] string
+
+ +
    +
  • s6-unquote unquotes string, which must follow the +syntax of s6-quote's output strings
  • +
  • It prints various warning or error messages to stderr if it +cannot unquote string properly
  • +
  • If successful, it prints the result to stdout and exits 0
  • +
+ +

Options

+ +
    +
  • -n : do not print a trailing newline.
  • +
  • -d delim : a list of characters that +will be considered as delimitors (to start and end the quoted string). +By default, only the double quote is such a character. If delim +is the empty string, s6-unquote interprets string as +non-delimited, only escaped (i.e. the result of some +s6-quote -u operation).
  • +
+ +

Notes

+ + + + + diff --git a/doc/s6-update-symlinks.html b/doc/s6-update-symlinks.html new file mode 100644 index 0000000..96cc15b --- /dev/null +++ b/doc/s6-update-symlinks.html @@ -0,0 +1,83 @@ + + + + + s6-portable-utils: the s6-update-symlinks program + + + + + + +

+s6
+Software
+skarnet.org +

+ +

The s6-update-symlinks program

+ +

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

+ +

+s6-update-symlinks is useful when one wants to combine +a logical package system, like Dan Bernstein's +/package and +/command, with +physical filesystem constraints, like /, /usr and +/usr/local on separate filesystems. +

+ +

Interface

+ +
+     s6-update-symlinks d src1 src2 ...
+
+ +
    +
  • d is the destination directory. It will be created if it doesn't +exist.
  • +
  • src1, src2, ... are the directory containing the files +to be linked.
  • +
  • d and srcn must be +absolute paths, else s6-update-symlinks refuses to run. Using +relative paths doesn't make sense here, anyway.
  • +
  • If src2 is empty, then d becomes a link to src1.
  • +
  • If src1 is empty or entirely overridden by src2, then +d becomes a link to src2.
  • +
  • If src1/file exists but not src2/file, then d +becomes a real directory and d/file a link to src1/file. +Then if src2/file2 exists, d/file2 links to it.
  • +
  • And so on with other src directories, and subdirs.
  • +
  • If s6-update-symlinks manages to performs all the requested +tasks, it exits 0. If it encounters a hard error, it exits 111. If it is +unable to resolve a conflict between given sources, it exits 100.
  • +
+ +

Examples

+ +
    +
  • +s6-update-symlinks /command /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin +
    makes all files under /bin, ..., /usr/local/sbin +available under /command. The programs linked are the same as the ones +that would be accessed with PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin". +
  • +
  • +s6-update-symlinks /package /initrd/package /slash/package /usr/package /usr/local/package +
    builds a /package hierarchy with what it finds in the listed +directories. This allows oddities like, for instance, having the daemontools +sources in /usr/package/admin/daemontools/src, and the daemontools +binaries in /initrd/package/admin/daemontools/bin, but accessing +both through /package/admin/daemontools/.
  • +
+ + + diff --git a/doc/upgrade.html b/doc/upgrade.html new file mode 100644 index 0000000..978f397 --- /dev/null +++ b/doc/upgrade.html @@ -0,0 +1,32 @@ + + + + + s6-portable-utils: how to upgrade + + + + + + +

+s6-portable-utils
+Software
+skarnet.org +

+ +

How to upgrade s6-portable-utils

+ +

to 2.0.0.0

+ +
    +
  • The build system has completely changed. It is now a standard +./configure && make && sudo make install +build system. See the enclosed INSTALL file for details.
  • +
  • slashpackage is not activated by default.
  • +
  • shared libraries are not used by default.
  • +
  • skalibs dependency bumped to 2.0.0.0
  • +
+ + + diff --git a/package/deps-build b/package/deps-build new file mode 100644 index 0000000..05d5af4 --- /dev/null +++ b/package/deps-build @@ -0,0 +1 @@ +/package/prog/skalibs diff --git a/package/deps.mak b/package/deps.mak new file mode 100644 index 0000000..425b475 --- /dev/null +++ b/package/deps.mak @@ -0,0 +1,83 @@ +# +# This file has been generated by tools/gen-deps.sh +# + +src/skaembutils/s6-basename.o src/skaembutils/s6-basename.lo: src/skaembutils/s6-basename.c +src/skaembutils/s6-cat.o src/skaembutils/s6-cat.lo: src/skaembutils/s6-cat.c +src/skaembutils/s6-chmod.o src/skaembutils/s6-chmod.lo: src/skaembutils/s6-chmod.c +src/skaembutils/s6-chown.o src/skaembutils/s6-chown.lo: src/skaembutils/s6-chown.c +src/skaembutils/s6-clock.o src/skaembutils/s6-clock.lo: src/skaembutils/s6-clock.c +src/skaembutils/s6-cut.o src/skaembutils/s6-cut.lo: src/skaembutils/s6-cut.c +src/skaembutils/s6-dirname.o src/skaembutils/s6-dirname.lo: src/skaembutils/s6-dirname.c +src/skaembutils/s6-echo.o src/skaembutils/s6-echo.lo: src/skaembutils/s6-echo.c +src/skaembutils/s6-env.o src/skaembutils/s6-env.lo: src/skaembutils/s6-env.c src/include/s6-portable-utils/config.h +src/skaembutils/s6-expr.o src/skaembutils/s6-expr.lo: src/skaembutils/s6-expr.c +src/skaembutils/s6-false.o src/skaembutils/s6-false.lo: src/skaembutils/s6-false.c +src/skaembutils/s6-format-filter.o src/skaembutils/s6-format-filter.lo: src/skaembutils/s6-format-filter.c +src/skaembutils/s6-grep.o src/skaembutils/s6-grep.lo: src/skaembutils/s6-grep.c +src/skaembutils/s6-head.o src/skaembutils/s6-head.lo: src/skaembutils/s6-head.c +src/skaembutils/s6-linkname.o src/skaembutils/s6-linkname.lo: src/skaembutils/s6-linkname.c +src/skaembutils/s6-ln.o src/skaembutils/s6-ln.lo: src/skaembutils/s6-ln.c +src/skaembutils/s6-ls.o src/skaembutils/s6-ls.lo: src/skaembutils/s6-ls.c +src/skaembutils/s6-maximumtime.o src/skaembutils/s6-maximumtime.lo: src/skaembutils/s6-maximumtime.c +src/skaembutils/s6-mkdir.o src/skaembutils/s6-mkdir.lo: src/skaembutils/s6-mkdir.c +src/skaembutils/s6-mkfifo.o src/skaembutils/s6-mkfifo.lo: src/skaembutils/s6-mkfifo.c +src/skaembutils/s6-nice.o src/skaembutils/s6-nice.lo: src/skaembutils/s6-nice.c +src/skaembutils/s6-nuke.o src/skaembutils/s6-nuke.lo: src/skaembutils/s6-nuke.c +src/skaembutils/s6-pause.o src/skaembutils/s6-pause.lo: src/skaembutils/s6-pause.c +src/skaembutils/s6-printenv.o src/skaembutils/s6-printenv.lo: src/skaembutils/s6-printenv.c +src/skaembutils/s6-quote-filter.o src/skaembutils/s6-quote-filter.lo: src/skaembutils/s6-quote-filter.c +src/skaembutils/s6-quote.o src/skaembutils/s6-quote.lo: src/skaembutils/s6-quote.c +src/skaembutils/s6-rename.o src/skaembutils/s6-rename.lo: src/skaembutils/s6-rename.c +src/skaembutils/s6-rmrf.o src/skaembutils/s6-rmrf.lo: src/skaembutils/s6-rmrf.c +src/skaembutils/s6-sleep.o src/skaembutils/s6-sleep.lo: src/skaembutils/s6-sleep.c +src/skaembutils/s6-sort.o src/skaembutils/s6-sort.lo: src/skaembutils/s6-sort.c +src/skaembutils/s6-sync.o src/skaembutils/s6-sync.lo: src/skaembutils/s6-sync.c +src/skaembutils/s6-tail.o src/skaembutils/s6-tail.lo: src/skaembutils/s6-tail.c +src/skaembutils/s6-test.o src/skaembutils/s6-test.lo: src/skaembutils/s6-test.c +src/skaembutils/s6-touch.o src/skaembutils/s6-touch.lo: src/skaembutils/s6-touch.c +src/skaembutils/s6-true.o src/skaembutils/s6-true.lo: src/skaembutils/s6-true.c +src/skaembutils/s6-uniquename.o src/skaembutils/s6-uniquename.lo: src/skaembutils/s6-uniquename.c +src/skaembutils/s6-unquote-filter.o src/skaembutils/s6-unquote-filter.lo: src/skaembutils/s6-unquote-filter.c +src/skaembutils/s6-unquote.o src/skaembutils/s6-unquote.lo: src/skaembutils/s6-unquote.c +src/skaembutils/s6-update-symlinks.o src/skaembutils/s6-update-symlinks.lo: src/skaembutils/s6-update-symlinks.c + +s6-basename: src/skaembutils/s6-basename.o -lskarnet +s6-cat: src/skaembutils/s6-cat.o -lskarnet +s6-chmod: src/skaembutils/s6-chmod.o -lskarnet +s6-chown: src/skaembutils/s6-chown.o -lskarnet +s6-clock: src/skaembutils/s6-clock.o -lskarnet ${SYSCLOCK_LIB} +s6-cut: src/skaembutils/s6-cut.o -lskarnet +s6-dirname: src/skaembutils/s6-dirname.o -lskarnet +s6-echo: src/skaembutils/s6-echo.o -lskarnet +s6-env: src/skaembutils/s6-env.o -lskarnet +s6-expr: src/skaembutils/s6-expr.o -lskarnet +s6-false: src/skaembutils/s6-false.o +s6-format-filter: src/skaembutils/s6-format-filter.o -lskarnet +s6-grep: src/skaembutils/s6-grep.o -lskarnet +s6-head: src/skaembutils/s6-head.o -lskarnet +s6-linkname: src/skaembutils/s6-linkname.o -lskarnet +s6-ln: src/skaembutils/s6-ln.o -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB} +s6-ls: src/skaembutils/s6-ls.o -lskarnet +s6-maximumtime: src/skaembutils/s6-maximumtime.o -lskarnet ${TAINNOW_LIB} +s6-mkdir: src/skaembutils/s6-mkdir.o -lskarnet +s6-mkfifo: src/skaembutils/s6-mkfifo.o -lskarnet +s6-nice: src/skaembutils/s6-nice.o -lskarnet +s6-nuke: src/skaembutils/s6-nuke.o -lskarnet +s6-pause: src/skaembutils/s6-pause.o +s6-printenv: src/skaembutils/s6-printenv.o -lskarnet +s6-quote: src/skaembutils/s6-quote.o -lskarnet +s6-quote-filter: src/skaembutils/s6-quote-filter.o -lskarnet +s6-rename: src/skaembutils/s6-rename.o -lskarnet +s6-rmrf: src/skaembutils/s6-rmrf.o -lskarnet +s6-sleep: src/skaembutils/s6-sleep.o -lskarnet ${TAINNOW_LIB} +s6-sort: src/skaembutils/s6-sort.o -lskarnet +s6-sync: src/skaembutils/s6-sync.o +s6-tail: src/skaembutils/s6-tail.o -lskarnet +s6-test: src/skaembutils/s6-test.o -lskarnet +s6-touch: src/skaembutils/s6-touch.o -lskarnet +s6-true: src/skaembutils/s6-true.o +s6-uniquename: src/skaembutils/s6-uniquename.o -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB} +s6-unquote: src/skaembutils/s6-unquote.o -lskarnet +s6-unquote-filter: src/skaembutils/s6-unquote-filter.o -lskarnet +s6-update-symlinks: src/skaembutils/s6-update-symlinks.o -lskarnet ${SOCKET_LIB} ${TAINNOW_LIB} diff --git a/package/info b/package/info new file mode 100644 index 0000000..6d862af --- /dev/null +++ b/package/info @@ -0,0 +1,4 @@ +package=s6-portable-utils +version=2.0.0.0 +category=admin +package_macro_name=S6_PORTABLE_UTILS diff --git a/package/modes b/package/modes new file mode 100644 index 0000000..f32d538 --- /dev/null +++ b/package/modes @@ -0,0 +1,39 @@ +s6-basename 0755 +s6-cat 0755 +s6-chmod 0755 +s6-chown 0755 +s6-clock 0755 +s6-cut 0755 +s6-dirname 0755 +s6-echo 0755 +s6-env 0755 +s6-expr 0755 +s6-false 0755 +s6-format-filter 0755 +s6-grep 0755 +s6-head 0755 +s6-linkname 0755 +s6-ln 0755 +s6-ls 0755 +s6-maximumtime 0755 +s6-mkdir 0755 +s6-mkfifo 0755 +s6-nice 0755 +s6-nuke 0755 +s6-pause 0755 +s6-printenv 0755 +s6-quote 0755 +s6-quote-filter 0755 +s6-rename 0755 +s6-rmrf 0755 +s6-sleep 0755 +s6-sort 0755 +s6-sync 0755 +s6-tail 0755 +s6-test 0755 +s6-touch 0755 +s6-true 0755 +s6-uniquename 0755 +s6-unquote 0755 +s6-unquote-filter 0755 +s6-update-symlinks 0755 diff --git a/package/targets.mak b/package/targets.mak new file mode 100644 index 0000000..256c88a --- /dev/null +++ b/package/targets.mak @@ -0,0 +1,45 @@ +BIN_TARGETS = \ +s6-basename \ +s6-cat \ +s6-chmod \ +s6-chown \ +s6-clock \ +s6-cut \ +s6-dirname \ +s6-echo \ +s6-env \ +s6-expr \ +s6-false \ +s6-format-filter \ +s6-grep \ +s6-head \ +s6-linkname \ +s6-ln \ +s6-ls \ +s6-maximumtime \ +s6-mkdir \ +s6-mkfifo \ +s6-nice \ +s6-nuke \ +s6-pause \ +s6-printenv \ +s6-quote \ +s6-quote-filter \ +s6-rename \ +s6-rmrf \ +s6-sleep \ +s6-sort \ +s6-sync \ +s6-tail \ +s6-test \ +s6-touch \ +s6-true \ +s6-uniquename \ +s6-unquote \ +s6-unquote-filter \ +s6-update-symlinks + +SBIN_TARGETS = +LIBEXEC_TARGETS = +SHARED_LIBS = +STATIC_LIBS = diff --git a/patch-for-solaris b/patch-for-solaris new file mode 100755 index 0000000..02f2e3c --- /dev/null +++ b/patch-for-solaris @@ -0,0 +1,17 @@ +#!/usr/xpg4/bin/sh + +patchit () { + echo '#!/usr/xpg4/bin/sh' > $1.tmp + tail -n +2 $1 >> $1.tmp + mv -f $1.tmp $1 + chmod 755 $1 +} + +patchit ./configure +patchit ./tools/install.sh +patchit ./tools/gen-deps.sh + +echo 'SHELL := /usr/xpg4/bin/sh' > Makefile.tmp +echo >> Makefile.tmp +cat Makefile >> Makefile.tmp +mv -f Makefile.tmp Makefile diff --git a/src/skaembutils/deps-exe/s6-basename b/src/skaembutils/deps-exe/s6-basename new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-basename @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-cat b/src/skaembutils/deps-exe/s6-cat new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-cat @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-chmod b/src/skaembutils/deps-exe/s6-chmod new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-chmod @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-chown b/src/skaembutils/deps-exe/s6-chown new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-chown @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-clock b/src/skaembutils/deps-exe/s6-clock new file mode 100644 index 0000000..a11a5f4 --- /dev/null +++ b/src/skaembutils/deps-exe/s6-clock @@ -0,0 +1,2 @@ +-lskarnet +${SYSCLOCK_LIB} diff --git a/src/skaembutils/deps-exe/s6-cut b/src/skaembutils/deps-exe/s6-cut new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-cut @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-dirname b/src/skaembutils/deps-exe/s6-dirname new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-dirname @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-echo b/src/skaembutils/deps-exe/s6-echo new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-echo @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-env b/src/skaembutils/deps-exe/s6-env new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-env @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-expr b/src/skaembutils/deps-exe/s6-expr new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-expr @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-false b/src/skaembutils/deps-exe/s6-false new file mode 100644 index 0000000..e69de29 diff --git a/src/skaembutils/deps-exe/s6-format-filter b/src/skaembutils/deps-exe/s6-format-filter new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-format-filter @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-grep b/src/skaembutils/deps-exe/s6-grep new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-grep @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-head b/src/skaembutils/deps-exe/s6-head new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-head @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-linkname b/src/skaembutils/deps-exe/s6-linkname new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-linkname @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-ln b/src/skaembutils/deps-exe/s6-ln new file mode 100644 index 0000000..e027835 --- /dev/null +++ b/src/skaembutils/deps-exe/s6-ln @@ -0,0 +1,3 @@ +-lskarnet +${SOCKET_LIB} +${TAINNOW_LIB} diff --git a/src/skaembutils/deps-exe/s6-ls b/src/skaembutils/deps-exe/s6-ls new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-ls @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-maximumtime b/src/skaembutils/deps-exe/s6-maximumtime new file mode 100644 index 0000000..1840bc1 --- /dev/null +++ b/src/skaembutils/deps-exe/s6-maximumtime @@ -0,0 +1,2 @@ +-lskarnet +${TAINNOW_LIB} diff --git a/src/skaembutils/deps-exe/s6-mkdir b/src/skaembutils/deps-exe/s6-mkdir new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-mkdir @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-mkfifo b/src/skaembutils/deps-exe/s6-mkfifo new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-mkfifo @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-nice b/src/skaembutils/deps-exe/s6-nice new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-nice @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-nuke b/src/skaembutils/deps-exe/s6-nuke new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-nuke @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-pause b/src/skaembutils/deps-exe/s6-pause new file mode 100644 index 0000000..e69de29 diff --git a/src/skaembutils/deps-exe/s6-printenv b/src/skaembutils/deps-exe/s6-printenv new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-printenv @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-quote b/src/skaembutils/deps-exe/s6-quote new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-quote @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-quote-filter b/src/skaembutils/deps-exe/s6-quote-filter new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-quote-filter @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-rename b/src/skaembutils/deps-exe/s6-rename new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-rename @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-rmrf b/src/skaembutils/deps-exe/s6-rmrf new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-rmrf @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-sleep b/src/skaembutils/deps-exe/s6-sleep new file mode 100644 index 0000000..1840bc1 --- /dev/null +++ b/src/skaembutils/deps-exe/s6-sleep @@ -0,0 +1,2 @@ +-lskarnet +${TAINNOW_LIB} diff --git a/src/skaembutils/deps-exe/s6-sort b/src/skaembutils/deps-exe/s6-sort new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-sort @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-sync b/src/skaembutils/deps-exe/s6-sync new file mode 100644 index 0000000..e69de29 diff --git a/src/skaembutils/deps-exe/s6-tail b/src/skaembutils/deps-exe/s6-tail new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-tail @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-test b/src/skaembutils/deps-exe/s6-test new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-test @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-touch b/src/skaembutils/deps-exe/s6-touch new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-touch @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-true b/src/skaembutils/deps-exe/s6-true new file mode 100644 index 0000000..e69de29 diff --git a/src/skaembutils/deps-exe/s6-uniquename b/src/skaembutils/deps-exe/s6-uniquename new file mode 100644 index 0000000..e027835 --- /dev/null +++ b/src/skaembutils/deps-exe/s6-uniquename @@ -0,0 +1,3 @@ +-lskarnet +${SOCKET_LIB} +${TAINNOW_LIB} diff --git a/src/skaembutils/deps-exe/s6-unquote b/src/skaembutils/deps-exe/s6-unquote new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-unquote @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-unquote-filter b/src/skaembutils/deps-exe/s6-unquote-filter new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/skaembutils/deps-exe/s6-unquote-filter @@ -0,0 +1 @@ +-lskarnet diff --git a/src/skaembutils/deps-exe/s6-update-symlinks b/src/skaembutils/deps-exe/s6-update-symlinks new file mode 100644 index 0000000..e027835 --- /dev/null +++ b/src/skaembutils/deps-exe/s6-update-symlinks @@ -0,0 +1,3 @@ +-lskarnet +${SOCKET_LIB} +${TAINNOW_LIB} diff --git a/src/skaembutils/s6-basename.c b/src/skaembutils/s6-basename.c new file mode 100644 index 0000000..113e14b --- /dev/null +++ b/src/skaembutils/s6-basename.c @@ -0,0 +1,45 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-basename [ -n ] file [ suffix ]" + +int main (int argc, char const *const *argv) +{ + stralloc sa = STRALLOC_ZERO ; + int nl = 1 ; + PROG = "s6-basename" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "n", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'n' : nl = 0 ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) strerr_dieusage(100, USAGE) ; + if (!sabasename(&sa, argv[0], str_len(argv[0]))) + strerr_diefu2sys(111, "get basename of ", argv[0]) ; + if (argc >= 2) + { + unsigned int n = str_len(argv[1]) ; + if ((n < sa.len) && !byte_diff(argv[1], n, sa.s + sa.len - n)) + sa.len -= n ; + } + if (nl && !stralloc_catb(&sa, "\n", 1)) + strerr_diefu2sys(111, "get basename of ", argv[0]) ; + if (allwrite(1, sa.s, sa.len) < sa.len) + strerr_diefu1sys(111, "write to stdout") ; + return 0 ; +} diff --git a/src/skaembutils/s6-cat.c b/src/skaembutils/s6-cat.c new file mode 100644 index 0000000..f0166be --- /dev/null +++ b/src/skaembutils/s6-cat.c @@ -0,0 +1,12 @@ +/* ISC license. */ + +#include +#include +#include + +int main (void) +{ + PROG = "s6-cat" ; + if (fd_cat(0, 1) < 0) strerr_diefu1sys(111, "fd_cat") ; + return 0 ; +} diff --git a/src/skaembutils/s6-chmod.c b/src/skaembutils/s6-chmod.c new file mode 100644 index 0000000..9cf6f80 --- /dev/null +++ b/src/skaembutils/s6-chmod.c @@ -0,0 +1,34 @@ +/* ISC license. */ + +#include +#include +#include +#include + +#define USAGE "s6-chmod mode file" + +int main (int argc, char const *const *argv) +{ + mode_t mode = 0 ; + unsigned int m ; + PROG = "s6-chmod" ; + if (argc < 3) strerr_dieusage(100, USAGE) ; + if (!uint0_oscan(argv[1], &m)) strerr_dieusage(100, USAGE) ; + + if (m & 0001) mode |= S_IXOTH ; + if (m & 0002) mode |= S_IWOTH ; + if (m & 0004) mode |= S_IROTH ; + if (m & 0010) mode |= S_IXGRP ; + if (m & 0020) mode |= S_IWGRP ; + if (m & 0040) mode |= S_IRGRP ; + if (m & 0100) mode |= S_IXUSR ; + if (m & 0200) mode |= S_IWUSR ; + if (m & 0400) mode |= S_IRUSR ; + if (m & 01000) mode |= S_ISVTX ; + if (m & 02000) mode |= S_ISGID ; + if (m & 04000) mode |= S_ISUID ; + + if (chmod(argv[2], mode) == -1) + strerr_diefu2sys(111, "change mode of ", argv[2]) ; + return 0 ; +} diff --git a/src/skaembutils/s6-chown.c b/src/skaembutils/s6-chown.c new file mode 100644 index 0000000..ef6a4a0 --- /dev/null +++ b/src/skaembutils/s6-chown.c @@ -0,0 +1,60 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-chown [ -U ] [ -u uid ] [ -g gid ] file" + +int main (int argc, char const *const *argv, char const *const *envp) +{ + int uid = -1, gid = -1 ; + PROG = "s6-chown" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "Uu:g:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'u': + { + unsigned int u ; + if (!uint0_scan(l.arg, &u)) strerr_dieusage(100, USAGE) ; + uid = u ; + break ; + } + case 'g': + { + unsigned int g ; + if (!uint0_scan(l.arg, &g)) strerr_dieusage(100, USAGE) ; + gid = g ; + break ; + } + case 'U': + { + unsigned int x ; + char const *s = env_get2(envp, "UID") ; + if (!s) strerr_dienotset(100, "UID") ; + if (!uint0_scan(s, &x)) strerr_dieinvalid(100, "UID") ; + uid = x ; + s = env_get2(envp, "GID") ; + if (!s) strerr_dienotset(100, "GID") ; + if (!uint0_scan(s, &x)) strerr_dieinvalid(100, "GID") ; + gid = x ; + break ; + } + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) strerr_dieusage(100, USAGE) ; + if (chown(*argv, uid, gid) == -1) + strerr_diefu2sys(111, "chown ", argv[0]) ; + return 0 ; +} diff --git a/src/skaembutils/s6-clock.c b/src/skaembutils/s6-clock.c new file mode 100644 index 0000000..822500a --- /dev/null +++ b/src/skaembutils/s6-clock.c @@ -0,0 +1,31 @@ +/* ISC license. */ + +#include +#include +#include + +#define USAGE "s6-clock [ tai64nlabel ]" + +static int getit (void) +{ + char fmt[TIMESTAMP+1] ; + timestamp(fmt) ; + fmt[TIMESTAMP] = '\n' ; + if (allwrite(1, fmt, TIMESTAMP+1) < TIMESTAMP+1) + strerr_diefu1sys(111, "write to stdout") ; + return 0 ; +} + +static int setit (char const *h) +{ + tain_t a ; + if (!timestamp_scan(h, &a)) strerr_dieusage(100, USAGE) ; + if (!tain_setnow(&a)) strerr_diefu1sys(111, "taia_setnow") ; + return 0 ; +} + +int main (int argc, char const *const *argv) +{ + PROG = "s6-clock" ; + return (argc < 2) ? getit() : setit(argv[1]) ; +} diff --git a/src/skaembutils/s6-cut.c b/src/skaembutils/s6-cut.c new file mode 100644 index 0000000..bb729d0 --- /dev/null +++ b/src/skaembutils/s6-cut.c @@ -0,0 +1,212 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-cut [ -b list | -c list | -f list ] [ -d delim ] [ -n ] [ -s ] [ file... ]" + +static int diuint_cmpleft (void const *a, void const *b) +{ + return ((diuint const *)a)->left - ((diuint const *)b)->left ; +} + +static void diuintalloc_normalize (genalloc *list) +{ + unsigned int i = 1, cur = 0 ; + unsigned int len = genalloc_len(diuint, list) ; + register diuint *const s = genalloc_s(diuint, list) ; + qsort(s, len, sizeof(diuint), &diuint_cmpleft) ; + for (; i < len ; i++) + if (!s[cur].right) break ; + else if (s[i].left > s[cur].right) s[++cur] = s[i] ; + else if (s[cur].right < s[i].right) + s[cur].right = s[i].right ; + genalloc_setlen(diuint, list, cur+1) ; +} + +static void scanlist (genalloc *list, char const *s) +{ + register unsigned int i = 0 ; + genalloc_setlen(diuint, list, 0) ; + while (s[i]) + { + char const sep[4] = ", \t" ; + diuint iv ; + if (s[i] == '-') iv.left = 1 ; + else + { + unsigned int j = uint_scan(s+i, &iv.left) ; + if (!j || !iv.left) strerr_dief2x(100, "invalid list argument: ", s) ; + i += j ; + } + if (s[i] != '-') iv.right = iv.left ; + else + { + unsigned int j = uint_scan(s + ++i, &iv.right) ; + if (!j) iv.right = 0 ; + else if (iv.right < iv.left) + strerr_dief2x(100, "invalid list argument: ", s) ; + else i += j ; + } + switch (byte_chr(sep, 4, s[i])) + { + case 0 : + case 1 : + case 2 : i++ ; + case 3 : break ; + case 4 : + strerr_dief2x(100, "invalid list argument: ", s) ; + } + if (!genalloc_append(diuint, list, &iv)) + strerr_diefu1sys(111, "build interval list") ; + } +} + +static int doit (int fd, diuint const *s, unsigned int len, unsigned int flags, char delim) +{ + char buf[BUFFER_INSIZE] ; + buffer b = BUFFER_INIT(&buffer_flush1read, fd, buf, BUFFER_INSIZE) ; + for (;;) + { + int r ; + satmp.len = 0 ; + r = skagetln(&b, &satmp, '\n') ; + if ((r == -1) && (errno != EPIPE)) return 0 ; + if (!r) break ; + if (flags & 2) + { + register unsigned int i = 0 ; + for (; i < len ; i++) + { + register unsigned int j = s[i].right ; + if (s[i].left >= satmp.len) break ; + if (!j || (j > satmp.len)) + { + j = satmp.len ; + r = 0 ; + } + if (buffer_put(buffer_1, satmp.s + s[i].left - 1, j + 1 - s[i].left) == -1) + return 0 ; + } + } + else + { + register unsigned int i = 0, j = 0, count = 1 ; + for (; i < len ; i++) + { + for (; count < s[i].left ; count++) + { + j += byte_chr(satmp.s + j, satmp.len - j, delim) ; + if (j == satmp.len) break ; + j++ ; + } + if (j == satmp.len) + { + if (count == 1) + { + if ((flags & 1) && (buffer_put(buffer_1, satmp.s, satmp.len) < 0)) + return 0 ; + r = 0 ; + } + break ; + } + for (; !s[i].right || (count <= s[i].right) ; count++) + { + register unsigned int k = byte_chr(satmp.s + j, satmp.len - j, delim) ; + if ((count > s[0].left) && (buffer_put(buffer_1, &delim, 1) < 0)) return 0 ; + if (buffer_put(buffer_1, satmp.s + j, k) < 0) return 0 ; + j += k ; + if (j == satmp.len) + { + r = 0 ; + break ; + } + j++ ; + } + if (j == satmp.len) break ; + } + } + if ((r > 0) && (buffer_put(buffer_1, "\n", 1) < 0)) return 0 ; + } + return 1 ; +} + +int main (int argc, char const *const *argv) +{ + genalloc list = GENALLOC_ZERO ; /* array of diuint */ + char delim = '\t' ; + unsigned int what = 0 ; + PROG = "s6-cut" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + int flagnodel = 1 ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "nsb:c:f:d:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'n': break ; /* ignored */ + case 's': flagnodel = 0 ; break ; + case 'd': delim = *l.arg ; break ; + case 'b': + case 'c': + { + if (what) strerr_dieusage(100, USAGE) ; + what = 2 ; + scanlist(&list, l.arg) ; + break ; + } + case 'f': + { + if (what) strerr_dieusage(100, USAGE) ; + what = 4 ; + scanlist(&list, l.arg) ; + break ; + } + default : strerr_dieusage(100, USAGE) ; + } + } + what += flagnodel ; + argc -= l.ind ; argv += l.ind ; + } + if (!genalloc_len(diuint, &list)) strerr_dieusage(100, USAGE) ; + diuintalloc_normalize(&list) ; + + if (!argc) + { + if (!doit(0, genalloc_s(diuint, &list), genalloc_len(diuint, &list), what, delim)) + strerr_diefu1sys(111, "cut stdin") ; + } + else + { + for (; *argv ; argv++) + { + if ((argv[0][0] == '-') && !argv[0][1]) + { + if (!doit(0, genalloc_s(diuint, &list), genalloc_len(diuint, &list), what, delim)) + strerr_diefu1sys(111, "process stdin") ; + } + else + { + int fd = open_readb(*argv) ; + if (fd == -1) + strerr_diefu3sys(111, "open ", *argv, " for reading") ; + if (!doit(fd, genalloc_s(diuint, &list), genalloc_len(diuint, &list), what, delim)) + strerr_diefu2sys(111, "cut ", *argv) ; + fd_close(fd) ; + } + } + } + return 0 ; +} diff --git a/src/skaembutils/s6-dirname.c b/src/skaembutils/s6-dirname.c new file mode 100644 index 0000000..5883180 --- /dev/null +++ b/src/skaembutils/s6-dirname.c @@ -0,0 +1,40 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-dirname [ -n ] file" + +int main (int argc, char const *const *argv) +{ + stralloc sa = STRALLOC_ZERO ; + int nl = 1 ; + PROG = "s6-dirname" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "n", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'n' : nl = 0 ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + + if (!argc) strerr_dieusage(100, USAGE) ; + if (!sadirname(&sa, argv[0], str_len(argv[0]))) + strerr_diefu2sys(111, "get dirname of ", argv[0]) ; + if (nl && !stralloc_catb(&sa, "\n", 1)) + strerr_diefu2sys(111, "get dirname of ", argv[0]) ; + if (allwrite(1, sa.s, sa.len) < sa.len) + strerr_diefu1sys(111, "write to stdout") ; + return 0 ; +} diff --git a/src/skaembutils/s6-echo.c b/src/skaembutils/s6-echo.c new file mode 100644 index 0000000..6d30576 --- /dev/null +++ b/src/skaembutils/s6-echo.c @@ -0,0 +1,38 @@ +/* ISC license. */ + +#include +#include +#include + +#define USAGE "s6-echo [ -n ] [ -s sep ] args..." + +int main (int argc, char const *const *argv) +{ + char sep = ' ' ; + char donl = 1 ; + PROG = "s6-echo" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "ns:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'n': donl = 0 ; break ; + case 's': sep = *l.arg ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + for ( ; *argv ; argv++) + if ((buffer_puts(buffer_1small, *argv) < 0) + || (argv[1] && (buffer_put(buffer_1small, &sep, 1) == -1))) + goto err ; + if (donl && (buffer_put(buffer_1small, "\n", 1) == -1)) goto err ; + if (!buffer_flush(buffer_1small)) goto err ; + return 0 ; +err: + strerr_diefu1sys(111, "write to stdout") ; +} diff --git a/src/skaembutils/s6-env.c b/src/skaembutils/s6-env.c new file mode 100644 index 0000000..b2e1312 --- /dev/null +++ b/src/skaembutils/s6-env.c @@ -0,0 +1,43 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-env [ -i ] [ name=value... ] prog..." + +int main (int argc, char const *const *argv, char const *const *envp) +{ + stralloc modifs = STRALLOC_ZERO ; + char const *arg_zero[2] = { S6_PORTABLE_UTILS_BINPREFIX "s6-printenv", 0 } ; + char const *env_zero[1] = { 0 } ; + PROG = "s6-env" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "i", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'i': envp = env_zero ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + for (; argc ; argc--, argv++) + { + if (!(*argv)[str_chr(*argv, '=')]) break ; + if (!stralloc_cats(&modifs, *argv) || !stralloc_0(&modifs)) + strerr_diefu1sys(111, "stralloc_cats") ; + } + if (!argc) argv = arg_zero ; + pathexec_r(argv, envp, env_len(envp), modifs.s, modifs.len) ; + stralloc_free(&modifs) ; + strerr_dieexec((errno == ENOENT) ? 127 : 126, argv[0]) ; +} diff --git a/src/skaembutils/s6-expr.c b/src/skaembutils/s6-expr.c new file mode 100644 index 0000000..4404d44 --- /dev/null +++ b/src/skaembutils/s6-expr.c @@ -0,0 +1,211 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-expr arithmetic expression" + +enum opnum +{ + T_DATA, + T_AND, + T_OR, + T_LEFTP, + T_RIGHTP, + T_EQUAL, + T_NEQUAL, + T_GREATER, + T_GREATERE, + T_LESSER, + T_LESSERE, + T_PLUS, + T_MINUS, + T_TIMES, + T_DIV, + T_MOD +} ; + +struct token +{ + char const *string ; + enum opnum op ; + unsigned int type ; +} ; + +struct node +{ + enum opnum op ; + unsigned int type ; + unsigned int arg1 ; + unsigned int arg2 ; + int data ; +} ; + +static unsigned int lex (struct node *tree, char const *const *argv) +{ + static struct token const tokens[16] = + { + { "+", T_PLUS, 3 }, + { "-", T_MINUS, 3 }, + { "*", T_TIMES, 2 }, + { "/", T_DIV, 2 }, + { "%", T_MOD, 2 }, + { "(", T_LEFTP, 7 }, + { ")", T_RIGHTP, 8 }, + { "=", T_EQUAL, 4 }, + { "!=", T_NEQUAL, 4 }, + { "<", T_LESSER, 4 }, + { "<=", T_LESSERE, 4 }, + { ">", T_GREATER, 4 }, + { ">=", T_GREATERE, 4 }, + { "|", T_OR, 6 }, + { "&", T_AND, 5 }, + { 0, 0, 0 } + } ; + register unsigned int pos = 0 ; + + for (; argv[pos] ; pos++) + { + register unsigned int i = 0 ; + for (i = 0 ; tokens[i].string ; i++) + if (!str_diff(argv[pos], tokens[i].string)) + { + tree[pos].op = tokens[i].op ; + tree[pos].type = tokens[i].type ; + break ; + } + if (!tokens[i].string) + { + tree[pos].op = T_DATA ; + tree[pos].type = 0 ; + if (!int_scan(argv[pos], &tree[pos].data)) + strerr_dief1x(2, "invalid expression") ; + } + } + return pos ; +} + +static void reduce (struct node *tree, register unsigned int *stack, register unsigned int *sp, unsigned int type) +{ + if (tree[stack[*sp-1]].type == type) + { + tree[stack[*sp-1]].arg1 = stack[*sp-2] ; + tree[stack[*sp-1]].arg2 = stack[*sp] ; + stack[*sp-2] = stack[*sp-1] ; + *sp -= 2 ; + } + tree[stack[*sp]].type = type + 7 ; +} + +static unsigned int parse (struct node *tree, unsigned int n) +{ + static char const table[9][15] = + { + "xsssssssxzzzzzz", + "xxxxxxxx!zzzzzz", + "mxxxxxxxMszzzzz", + "mxxxxxxxMaszzzz", + "mxxxxxxxMacszzz", + "mxxxxxxxMacAszz", + "mxxxxxxxMacAOsz", + "xsssssssxzzzzzz", + "mxxxxxxxMacAOEs" + } ; + unsigned int stack[n] ; + unsigned int sp = 0, pos = 0 ; + char cont = 1 ; + stack[0] = n + 1 ; + tree[n].type = 8 ; /* add ) for the final reduce */ + tree[n+1].type = 1 ; /* add EOF */ + while (cont) + { + switch (table[tree[pos].type][tree[stack[sp]].type]) + { + case 'x' : _exit(2) ; + case '!' : cont = 0 ; break ; + case 's' : stack[++sp] = pos++ ; break ; + case 'm' : reduce(tree, stack, &sp, 2) ; break ; + case 'a' : reduce(tree, stack, &sp, 3) ; break ; + case 'c' : reduce(tree, stack, &sp, 4) ; break ; + case 'A' : reduce(tree, stack, &sp, 5) ; break ; + case 'O' : reduce(tree, stack, &sp, 6) ; break ; + case 'E' : tree[stack[sp]].type = 14 ; break ; + case 'M' : + { + if (tree[stack[sp-2]].type != 7) _exit(2) ; + stack[sp-2] = stack[sp-1] ; + sp -= 2 ; + reduce(tree, stack, &sp, 2) ; + break ; + } + case 'z' : + default : strerr_dief1x(101, "internal error in parse, please submit a bug-report.") ; /* can't happen */ + } + } + if (sp != 2) strerr_dief1x(2, "invalid expression") ; + return stack[1] ; +} + +static int run (struct node const *tree, unsigned int root) +{ + switch (tree[root].op) + { + case T_DATA : + return tree[root].data ; + case T_OR : + { + int r = run(tree, tree[root].arg1) ; + return r ? r : run(tree, tree[root].arg2) ; + } + case T_AND : + { + int r = run(tree, tree[root].arg1) ; + return r ? run(tree, tree[root].arg2) ? r : 0 : 0 ; + } + case T_EQUAL : + return run(tree, tree[root].arg1) == run(tree, tree[root].arg2) ; + case T_NEQUAL : + return run(tree, tree[root].arg1) != run(tree, tree[root].arg2) ; + case T_GREATER : + return run(tree, tree[root].arg1) > run(tree, tree[root].arg2) ; + case T_GREATERE : + return run(tree, tree[root].arg1) >= run(tree, tree[root].arg2) ; + case T_LESSER : + return run(tree, tree[root].arg1) < run(tree, tree[root].arg2) ; + case T_LESSERE : + return run(tree, tree[root].arg1) <= run(tree, tree[root].arg2) ; + case T_PLUS : + return run(tree, tree[root].arg1) + run(tree, tree[root].arg2) ; + case T_MINUS : + return run(tree, tree[root].arg1) - run(tree, tree[root].arg2) ; + case T_TIMES : + return run(tree, tree[root].arg1) * run(tree, tree[root].arg2) ; + case T_DIV : + return run(tree, tree[root].arg1) / run(tree, tree[root].arg2) ; + case T_MOD : + return run(tree, tree[root].arg1) % run(tree, tree[root].arg2) ; + default: strerr_dief1x(101, "internal error in run, please submit a bug-report") ; + } +} + +int main (int argc, char const *const *argv) +{ + char fmt[UINT_FMT+1] ; + int val ; + unsigned int len ; + PROG = "s6-expr" ; + if (argc <= 1) return 2 ; + { + struct node tree[argc + 1] ; + val = run(tree, parse(tree, lex(tree, argv+1))) ; + } + len = int_fmt(fmt, val) ; + fmt[len++] = '\n' ; + if (allwrite(1, fmt, len) < len) + strerr_diefu1sys(111, "write to stdout") ; + return !val ; +} diff --git a/src/skaembutils/s6-false.c b/src/skaembutils/s6-false.c new file mode 100644 index 0000000..fb13dcd --- /dev/null +++ b/src/skaembutils/s6-false.c @@ -0,0 +1,6 @@ +/* ISC license. */ + +int main () +{ + return 1 ; +} diff --git a/src/skaembutils/s6-format-filter.c b/src/skaembutils/s6-format-filter.c new file mode 100644 index 0000000..78e4437 --- /dev/null +++ b/src/skaembutils/s6-format-filter.c @@ -0,0 +1,61 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include + +#define USAGE "s6-format-filter format [ args... ]" + +int main (int argc, char const *const *argv) +{ + stralloc src = STRALLOC_ZERO ; + stralloc dst = STRALLOC_ZERO ; + char vars[12] = "s0123456789" ; + char const *args[12] = { "" } ; + char const *format ; + PROG = "s6-format-filter" ; + argc-- ; args[1] = *argv++ ; + if (!argc--) strerr_dieusage(100, USAGE) ; + format = *argv++ ; + if (argc > 9) argc = 9 ; + vars[argc+2] = 0 ; + { + register unsigned int i = 0 ; + for (; i < (unsigned int)argc ; i++) args[2+i] = argv[i] ; + } + if (!string_format(&dst, vars, format, args)) + strerr_diefu1sys(111, "compile format") ; + + for (;;) + { + register int r ; + src.len = 0 ; + dst.len = 0 ; + r = skagetln(buffer_0f1, &src, '\n') ; + if (!r) break ; + else if (r < 0) + { + if ((errno != EPIPE) || !stralloc_0(&src)) + strerr_diefu1sys(111, "read from stdin") ; + } + else src.s[src.len-1] = 0 ; + args[0] = src.s ; + if (!string_format(&dst, vars, format, args)) + { + int e = errno ; + buffer_flush(buffer_1) ; + errno = e ; + strerr_diefu1sys(111, "format") ; + } + if (r > 0) + { + if (!stralloc_catb(&dst, "\n", 1)) + strerr_diefu1sys(111, "format") ; + } + if (buffer_put(buffer_1, dst.s, dst.len) < 0) + strerr_diefu1sys(111, "write to stdout") ; + } + return 0 ; +} diff --git a/src/skaembutils/s6-grep.c b/src/skaembutils/s6-grep.c new file mode 100644 index 0000000..cd991e7 --- /dev/null +++ b/src/skaembutils/s6-grep.c @@ -0,0 +1,136 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-grep [ -E | -F ] [ -i ] [ -c ] [ -n ] [ -q ] [ -v ] pattern" + +typedef struct flags_s flags_t, *flags_t_ref ; +struct flags_s +{ + unsigned int extended : 1 ; + unsigned int ignorecase: 1 ; + unsigned int fixed : 1 ; + unsigned int count : 1 ; + unsigned int num : 1 ; + unsigned int quiet : 1 ; + unsigned int not : 1 ; +} ; +#define FLAGS_ZERO { .extended = 0, .ignorecase = 0, .fixed = 0, .count = 0, .num = 0, .quiet = 0, .not = 0 } + +int main (int argc, char const *const *argv) +{ + unsigned int count = 0 ; + flags_t flags = FLAGS_ZERO ; + PROG = "s6-grep" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "EFicnqv", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'E': flags.extended = 1 ; break ; + case 'F': flags.fixed = 1 ; break ; + case 'i': flags.ignorecase = 1 ; break ; + case 'c': flags.count = 1 ; break ; + case 'n': flags.num = 1 ; break ; + case 'q': flags.quiet = 1 ; break ; + case 'v': flags.not = 1 ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) strerr_dieusage(100, USAGE) ; + { + stralloc line = STRALLOC_ZERO ; + regex_t re ; + unsigned int num = 0 ; + unsigned int arglen ; + if (flags.fixed) + { + if (flags.ignorecase) arglen = str_len(argv[0]) ; + } + else + { + register int e = regcomp(&re, argv[0], REG_NOSUB | (flags.extended ? REG_EXTENDED : 0) | (flags.ignorecase ? REG_ICASE : 0)) ; + if (e) + { + char buf[256] ; + regerror(e, &re, buf, 256) ; + strerr_diefu2x(111, "compile regular expression: ", buf) ; + } + } + + for (;;) + { + register int r ; + line.len = 0 ; + r = skagetln(buffer_0f1, &line, '\n') ; + if (!r) break ; + if (r < 0) + { + if ((errno != EPIPE) || !stralloc_catb(&line, "\n", 1)) + strerr_diefu1sys(111, "read from stdin") ; + } + num++ ; line.s[line.len-1] = 0 ; + if (flags.fixed) + { + if (flags.ignorecase) + r = case_str(line.s, argv[0]) >= arglen ; + else + r = !strstr(line.s, argv[0]) ; + } + else + { + r = regexec(&re, line.s, 0, 0, 0) ; + if (r && r != REG_NOMATCH) + { + char buf[256] ; + regerror(r, &re, buf, 256) ; + strerr_diefu2x(111, "match regular expression: ", buf) ; + } + } + line.s[line.len-1] = '\n' ; + if (!r ^ flags.not) + { + count++ ; + if (!flags.quiet && !flags.count) + { + if (flags.num) + { + char fmt[UINT_FMT] ; + register unsigned int n = uint_fmt(fmt, num) ; + fmt[n++] = ':' ; + if (buffer_put(buffer_1, fmt, n) < (int)n) + strerr_diefu1sys(111, "write to stdout") ; + } + if (buffer_put(buffer_1, line.s, line.len) < (int)line.len) + strerr_diefu1sys(111, "write to stdout") ; + } + } + } + if (flags.quiet) return !count ; + stralloc_free(&line) ; + if (!flags.fixed) regfree(&re) ; + } + if (flags.count) + { + char fmt[UINT_FMT] ; + register unsigned int n = uint_fmt(fmt, count) ; + fmt[n++] = '\n' ; + if (buffer_put(buffer_1, fmt, n) < (int)n) + strerr_diefu1sys(111, "write to stdout") ; + } + return !count ; +} diff --git a/src/skaembutils/s6-head.c b/src/skaembutils/s6-head.c new file mode 100644 index 0000000..1ef24c0 --- /dev/null +++ b/src/skaembutils/s6-head.c @@ -0,0 +1,159 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-head [ -S ] [ -1..9 | -n lines | -c chars ] [ file... ]" +#define dieusage() strerr_dieusage(100, USAGE) + +typedef int headfunc_t (int, unsigned int) ; +typedef headfunc_t *headfunc_t_ref ; + +static int dolines (int fd, unsigned int lines) +{ + char buf[BUFFER_INSIZE] ; + buffer in = BUFFER_INIT(&buffer_read, fd, buf, BUFFER_INSIZE) ; + buffer out = BUFFER_INIT(&buffer_write, 1, buf, BUFFER_INSIZE) ; + siovec_t v[2] ; + while (lines) + { + unsigned int w = 0 ; + register int r = buffer_fill(&in) ; + if (r <= 0) return !r ; + out.c.n = in.c.n ; out.c.p = in.c.p ; + buffer_rpeek(&in, v) ; + for (;;) + { + unsigned int n = siovec_len(v, 2) ; + register unsigned int i ; + if (!n) break ; + i = siovec_bytechr(v, 2, '\n') ; + if (i < n) + { + w += i+1 ; + siovec_seek(v, 2, i+1) ; + if (!--lines) + { + out.c.n = (out.c.p + w) % out.c.a ; + break ; + } + } + else siovec_seek(v, 2, i) ; + } + if (!buffer_flush(&out)) return 0 ; + in.c.n = out.c.n ; in.c.p = out.c.p ; + } + return 1 ; +} + +static int safedolines (int fd, unsigned int lines) +{ + char tmp[lines] ; + while (lines) + { + unsigned int r = allread(fd, tmp, lines) ; + if ((r < lines) && (errno != EPIPE)) return 0 ; + lines -= byte_count(tmp, r, '\n') ; + if (buffer_put(buffer_1, tmp, r) < (int)r) return 0 ; + } + if (!buffer_flush(buffer_1)) return 0 ; + return 1 ; +} + +static int safedochars (int fd, unsigned int chars) +{ + return (fd_catn(fd, 1, chars) >= chars) ; +} + +int main (int argc, char const *const *argv) +{ + headfunc_t_ref f ; + unsigned int lines = 10 ; + int islines = 1, safe = 0 ; + PROG = "s6-head" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + int done = 0 ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "S123456789n:c:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'S' : safe = 1 ; break ; + case '1' : + case '2' : + case '3' : + case '4' : + case '5' : + case '6' : + case '7' : + case '8' : + case '9' : + { + if (done) dieusage() ; + islines = 1 ; + lines = opt - '0' ; + done = 1 ; + break ; + } + case 'n' : + { + if (done || !uint0_scan(l.arg, &lines)) + strerr_dieusage(100, USAGE) ; + islines = 1 ; + done = 1 ; + break ; + } + case 'c' : + { + if (done || !uint0_scan(l.arg, &lines)) + strerr_dieusage(100, USAGE) ; + islines = 0 ; + done = 1 ; + break ; + } + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (argc) safe = 0 ; + f = islines ? safe ? &safedolines : &dolines : &safedochars ; + if (!argc) + { + if (!(*f)(0, lines)) + strerr_diefu1sys(111, "head stdin") ; + } + else + { + unsigned int i = 0 ; + for (; argv[i] ; i++) + { + int fd ; + if (argc >= 2) + { + if (i) buffer_putnoflush(buffer_1, "\n", 1) ; + buffer_putnoflush(buffer_1, "==> ", 4) ; + if ((buffer_puts(buffer_1, argv[i]) <= 0) + || (buffer_putflush(buffer_1, " <==\n", 5) < 0)) + strerr_diefu1sys(111, "write to stdout") ; + } + if ((argv[i][0] == '-') && !argv[i][1]) fd = 0 ; + else fd = open_readb(argv[i]) ; + if (fd == -1) + strerr_diefu3sys(111, "open ", argv[i], " for reading") ; + if (!(*f)(fd, lines)) + strerr_diefu2sys(111, "head ", argv[i]) ; + fd_close(fd) ; + } + } + return 0 ; +} diff --git a/src/skaembutils/s6-linkname.c b/src/skaembutils/s6-linkname.c new file mode 100644 index 0000000..a9425a1 --- /dev/null +++ b/src/skaembutils/s6-linkname.c @@ -0,0 +1,45 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-linkname [ -n ] [ -f ] link" +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv) +{ + stralloc sa = STRALLOC_ZERO ; + int path = 0, nl = 1 ; + PROG = "s6-linkname" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "nf", &l) ; + if (opt == -1) break ; + switch(opt) + { + case 'n' : nl = 0 ; break ; + case 'f' : path = 1 ; break ; + default : dieusage() ; + } + } + argv += l.ind ; argc -= l.ind ; + } + if (!argc) dieusage() ; + + if ((path ? sarealpath(&sa, *argv) : sareadlink(&sa, *argv)) < 0) + strerr_diefu2sys(111, "resolve ", *argv) ; + + if ((buffer_put(buffer_1small, sa.s, sa.len) < 0) + || (nl && (buffer_put(buffer_1small, "\n", 1)) < 0) + || (!buffer_flush(buffer_1small))) + strerr_diefu1sys(111, "write to stdout") ; + + /* stralloc_free(&sa) ; */ + return 0 ; +} diff --git a/src/skaembutils/s6-ln.c b/src/skaembutils/s6-ln.c new file mode 100644 index 0000000..7f6f7b6 --- /dev/null +++ b/src/skaembutils/s6-ln.c @@ -0,0 +1,145 @@ +/* ISC license. */ + +#include + +#ifdef SKALIBS_HASLINKAT +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-ln [ -s ] [ -f ] [ -L ] [ -P ] src... dest" + +typedef int linkfunc_t (char const *, char const *) ; +typedef linkfunc_t *linkfunc_t_ref ; + +typedef void ln_t (char const *, char const *, linkfunc_t_ref) ; +typedef ln_t *ln_t_ref ; + +#ifdef SKALIBS_HASLINKAT + +static int linknoderef (char const *old, char const *new) +{ + return linkat(AT_FDCWD, old, AT_FDCWD, new, 0) ; +} + +static int linkderef (char const *old, char const *new) +{ + return linkat(AT_FDCWD, old, AT_FDCWD, new, AT_SYMLINK_FOLLOW) ; +} + +#else /* can't implement SUSv4, default to link */ + +# define linknoderef link +# define linkderef link + +#endif + +static void force (char const *old, char const *new, linkfunc_t_ref doit) +{ + if ((*doit)(old, new) == -1) + { + unsigned int base = satmp.len ; + if (errno != EEXIST) + strerr_diefu5sys(111, "make a link", " from ", new, " to ", old) ; + if (!stralloc_catb(&satmp, new, str_len(new)) + || (random_sauniquename(&satmp, 8) == -1) + || !stralloc_0(&satmp)) + strerr_diefu2sys(111, "make a unique name for ", old) ; + if ((*doit)(old, satmp.s + base) == -1) + strerr_diefu3sys(111, "make a link", " to ", old) ; + if (rename(satmp.s + base, new) == -1) + { + unlink(satmp.s + base) ; + strerr_diefu2sys(111, "atomically replace ", new) ; + } + satmp.len = base ; + } +} + +static void noforce (char const *old, char const *new, linkfunc_t_ref doit) +{ + if ((*doit)(old, new) == -1) + strerr_diefu5sys(111, "make a link", " from ", new, " to ", old) ; +} + +int main (int argc, char const *const *argv) +{ + linkfunc_t_ref mylink = &link ; /* default to system behaviour */ + ln_t_ref f = &noforce ; + PROG = "s6-ln" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "sfLP", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 's': mylink = &symlink ; break ; + case 'f': f = &force ; break ; + case 'L': if (mylink != &symlink) mylink = &linkderef ; break ; + case 'P': if (mylink != &symlink) mylink = &linknoderef ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (argc < 2) strerr_dieusage(100, USAGE) ; + if (argc > 2) + { + stralloc sa = STRALLOC_ZERO ; + unsigned int i = 0 ; + unsigned int base ; + if (!stralloc_cats(&sa, argv[argc-1]) || !stralloc_catb(&sa, "/", 1)) + strerr_diefu1sys(111, "stralloc_cats") ; + base = sa.len ; + for (; i < (unsigned int)(argc-1) ; i++) + { + sa.len = base ; + if (!sabasename(&sa, argv[i], str_len(argv[i]))) + strerr_diefu1sys(111, "sabasename") ; + if (!stralloc_0(&sa)) strerr_diefu1sys(111, "stralloc_0") ; + (*f)(argv[i], sa.s, mylink) ; + } + return 0 ; + } + + { + struct stat st ; + if (stat(argv[1], &st) < 0) + { + if (errno != ENOENT) strerr_diefu2sys(111, "stat ", argv[1]) ; + (*f)(argv[0], argv[1], mylink) ; + return 0 ; + } + if (!S_ISDIR(st.st_mode)) + { + (*f)(argv[0], argv[1], mylink) ; + return 0 ; + } + } + + { + stralloc sa = STRALLOC_ZERO ; + if (!stralloc_cats(&sa, argv[1]) + || !stralloc_catb(&sa, "/", 1) + || !sabasename(&sa, argv[0], str_len(argv[0])) + || !stralloc_0(&sa)) + strerr_diefu1sys(111, "stralloc_catb") ; + (*f)(argv[0], sa.s, mylink) ; + } + return 0 ; +} diff --git a/src/skaembutils/s6-ls.c b/src/skaembutils/s6-ls.c new file mode 100644 index 0000000..25045a7 --- /dev/null +++ b/src/skaembutils/s6-ls.c @@ -0,0 +1,56 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include + +#define USAGE "s6-ls [ -0 ] [ -a | -A ] [ -x exclude ] dir" + +int main (int argc, char const *const *argv) +{ + unsigned int all = 0 ; + char const *exclude = 0 ; + char delim = '\n' ; + PROG = "s6-ls" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "0aAx:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case '0': delim = '\0' ; break ; + case 'a': all = 1 ; break ; + case 'A': all = 2 ; break ; + case 'x': exclude = l.arg ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) strerr_dieusage(100, USAGE) ; + { + direntry *d ; + DIR *dir = opendir(*argv) ; + if (!dir) + strerr_diefu2sys(111, "open directory ", *argv) ; + while ((d = readdir(dir))) + { + if ((d->d_name[0] == '.') && (all < 2)) + { + if (!all || !d->d_name[1] || ((d->d_name[1] == '.') && !d->d_name[2])) continue ; + } + if (exclude && !str_diff(exclude, d->d_name)) continue ; + if ((buffer_puts(buffer_1, d->d_name) < 0) + || (buffer_put(buffer_1, &delim, 1) < 0)) + strerr_diefu1sys(111, "write to stdout") ; + } + dir_close(dir) ; + } + if (!buffer_flush(buffer_1)) + strerr_diefu1sys(111, "write to stdout") ; + return 0 ; +} diff --git a/src/skaembutils/s6-maximumtime.c b/src/skaembutils/s6-maximumtime.c new file mode 100644 index 0000000..571914f --- /dev/null +++ b/src/skaembutils/s6-maximumtime.c @@ -0,0 +1,99 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-maximumtime [ -0 | -a | -b | -i | -k | -q | -t | -x | -1 | -2 ] milliseconds prog..." + +int main (int argc, char const *const *argv, char const *const *envp) +{ + unsigned int timeout ; + tain_t stamp, deadline ; + iopause_fd x[1] = { { .fd = -1, .events = IOPAUSE_READ, .revents = 0 } } ; + pid_t pid = 0 ; + int tosend = SIGTERM ; + PROG = "s6-maximumtime" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "0abikqtx12", &l) ; + if (opt == -1) break ; + switch (opt) + { + case '0': tosend = 0 ; break ; + case 'a': tosend = SIGALRM ; break ; + case 'b': tosend = SIGABRT ; break ; + case 'i': tosend = SIGINT ; break ; + case 'k': tosend = SIGKILL ; break ; + case 'q': tosend = SIGQUIT ; break ; + case 't': tosend = SIGTERM ; break ; + case 'x': tosend = SIGXCPU ; break ; + case '1': tosend = SIGUSR1 ; break ; + case '2': tosend = SIGUSR2 ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + + if ((argc < 2) || !uint0_scan(argv[0], &timeout)) strerr_dieusage(100, USAGE) ; + if (!timeout) timeout = 1 ; + if (!tain_from_millisecs(&deadline, timeout)) + strerr_diefu1sys(111, "taia_from_millisecs") ; + + x[0].fd = selfpipe_init() ; + if (x[0].fd < 0) strerr_diefu1sys(111, "selfpipe_init") ; + + if (selfpipe_trap(SIGCHLD) < 0) strerr_diefu1sys(111, "selfpipe_trap") ; + + pid = child_spawn0(argv[1], argv+1, envp) ; + if (!pid) strerr_diefu2sys(111, "spawn ", argv[1]) ; + tain_now(&stamp) ; + tain_add(&deadline, &deadline, &stamp) ; + + for (;;) + { + int r = iopause_stamp(x, 1, &deadline, &stamp) ; + if (r < 0) strerr_diefu1sys(111, "iopause") ; + if (!r) break ; + if (x[0].revents & IOPAUSE_READ) + { + int cont = 1 ; + while (cont) + { + switch (selfpipe_read()) + { + case -1 : strerr_diefu1sys(111, "selfpipe_read") ; + case 0 : cont = 0 ; break ; + case SIGCHLD : + { + int wstat ; + if (wait_pid_nohang(pid, &wstat) == pid) + { + if (WIFSIGNALED(wstat)) + strerr_diew1x(111, "child process crashed") ; + else return WEXITSTATUS(wstat) ; + } + } + default : strerr_diefu1x(101, "internal error, please submit a bug-report.") ; + } + } + } + } + kill(pid, tosend) ; + errno = ETIMEDOUT ; + strerr_diewu1sys(99, "wait for child process") ; +} diff --git a/src/skaembutils/s6-mkdir.c b/src/skaembutils/s6-mkdir.c new file mode 100644 index 0000000..92bae67 --- /dev/null +++ b/src/skaembutils/s6-mkdir.c @@ -0,0 +1,79 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-mkdir [ -p ] [ -v ] [ -m mode ] dir" + +static int doit (char const *s, unsigned int mode, int verbose, int ee) +{ + if (mkdir(s, mode) == -1) + { + if (ee || (errno != EEXIST)) + { + strerr_warnwu2sys("mkdir ", s) ; + return 111 ; + } + } + else if (verbose) + { + buffer_puts(buffer_2, PROG) ; + buffer_puts(buffer_2, ": created directory ") ; + buffer_puts(buffer_2, s) ; + buffer_putflush(buffer_2, "\n", 1) ; + } + return 0 ; +} + +static int doparents (char const *s, unsigned int mode, int verbose) +{ + unsigned int n = str_len(s), i = 0 ; + char tmp[n+1] ; + for (; i < n ; i++) + { + if ((s[i] == '/') && i) + { + register int e ; + tmp[i] = 0 ; + e = doit(tmp, mode, verbose, 0) ; + if (e) return e ; + } + tmp[i] = s[i] ; + } + return doit(s, mode, verbose, 0) ; +} + +int main (int argc, char const *const *argv) +{ + int parents = 0, verbose = 0 ; + unsigned int mode = 0777 ; + int e = 0 ; + PROG = "s6-mkdir" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "pvm:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'p': parents = 1 ; break ; + case 'v': verbose = 1 ; break ; + case 'm': if (uint_oscan(l.arg, &mode)) break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + for ( ; *argv ; argv++) + e |= parents ? doparents(*argv, mode, verbose) : + doit(*argv, mode, verbose, 1) ; + return e ; +} diff --git a/src/skaembutils/s6-mkfifo.c b/src/skaembutils/s6-mkfifo.c new file mode 100644 index 0000000..9278eb9 --- /dev/null +++ b/src/skaembutils/s6-mkfifo.c @@ -0,0 +1,36 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-mkfifo [ -m mode ] fifo..." + +int main (int argc, char const *const *argv) +{ + unsigned int mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH ; + PROG = "s6-mkfifo" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "m:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'm': if (uint0_oscan(l.arg, &mode)) break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) strerr_dieusage(100, USAGE) ; + umask(S_IXUSR|S_IXGRP|S_IXOTH) ; + for (; *argv ; argv++) + if (mkfifo(*argv, mode) < 0) + strerr_diefu2sys(111, "mkfifo ", *argv) ; + return 0 ; +} diff --git a/src/skaembutils/s6-nice.c b/src/skaembutils/s6-nice.c new file mode 100644 index 0000000..ec9f477 --- /dev/null +++ b/src/skaembutils/s6-nice.c @@ -0,0 +1,46 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-nice [ -I | -i ] [ -n value ] prog..." + +int main (int argc, char const *const *argv, char const *const *envp) +{ + int incr = 10 ; + int strict = 0 ; + PROG = "s6-nice" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "Iin:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'I' : strict = 0 ; break ; + case 'i' : strict = 1 ; break ; + case 'n': if (!int_scan(l.arg, &incr)) strerr_dieusage(100, USAGE) ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) strerr_dieusage(100, USAGE) ; + + errno = 0 ; + if ((nice(incr) < 0) && errno) + { + char fmt[1+UINT_FMT] ; + fmt[int_fmt(fmt, incr)] = 0 ; + if (strict) strerr_diefu2sys(111, "nice to ", fmt) ; + else strerr_warnwu2sys("nice to ", fmt) ; + } + pathexec_run(argv[0], argv, envp) ; + strerr_dieexec((errno == ENOENT) ? 127 : 126, argv[0]) ; +} diff --git a/src/skaembutils/s6-nuke.c b/src/skaembutils/s6-nuke.c new file mode 100644 index 0000000..cda1279 --- /dev/null +++ b/src/skaembutils/s6-nuke.c @@ -0,0 +1,50 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-nuke [ -h | -t | -k ]" + +int main (int argc, char const *const *argv) +{ + int doterm = 0, dohangup = 0, dokill = 0 ; + PROG = "s6-nuke" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "htk", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'h': dohangup = 1 ; break ; + case 't': doterm = 1 ; break ; + case 'k': dokill = 1 ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + + if (dohangup) + { + sig_ignore(SIGHUP) ; + kill(-1, SIGHUP) ; + } + + if (doterm) + { + sig_ignore(SIGTERM) ; + kill(-1, SIGTERM) ; + kill(-1, SIGCONT) ; + } + + if (dokill) kill(-1, SIGKILL) ; + + if (errno) strerr_diefu1sys(111, "kill") ; + return 0 ; +} diff --git a/src/skaembutils/s6-pause.c b/src/skaembutils/s6-pause.c new file mode 100644 index 0000000..8eafdce --- /dev/null +++ b/src/skaembutils/s6-pause.c @@ -0,0 +1,9 @@ +/* ISC license. */ + +#include + +int main () +{ + pause() ; + return 0 ; +} diff --git a/src/skaembutils/s6-printenv.c b/src/skaembutils/s6-printenv.c new file mode 100644 index 0000000..3f4571b --- /dev/null +++ b/src/skaembutils/s6-printenv.c @@ -0,0 +1,51 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include + +#define USAGE "s6-printenv [ -n ] [ -0 | -d delimchar ]" + +int main (int argc, char const *const *argv, char const *const *envp) +{ + char delim = '\n' ; + int zero = 0, nl = 1 ; + PROG = "s6-printenv" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "nd:0", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'n' : nl = 0 ; break ; + case 'd' : delim = *l.arg ; break ; + case '0' : zero = 1 ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (zero) delim = 0 ; + for (; *envp ; envp++) + { + if (delim || zero) + { + if ((buffer_puts(buffer_1, *envp) < 0) + || ((nl || envp[1]) && (buffer_put(buffer_1, &delim, 1) < 0))) + strerr_diefu1sys(111, "write to stdout") ; + } + else + { + unsigned int written = 0 ; + if (!netstring_put(buffer_1, *envp, str_len(*envp), &written)) + strerr_diefu1sys(111, "write a netstring to stdout") ; + } + } + if (!buffer_flush(buffer_1)) + strerr_diefu1sys(111, "write to stdout") ; + return 0 ; +} diff --git a/src/skaembutils/s6-quote-filter.c b/src/skaembutils/s6-quote-filter.c new file mode 100644 index 0000000..d9489a1 --- /dev/null +++ b/src/skaembutils/s6-quote-filter.c @@ -0,0 +1,72 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-quote-filter [ -u ] [ -d delim ]" + +int main (int argc, char const *const *argv) +{ + stralloc src = STRALLOC_ZERO ; + stralloc dst = STRALLOC_ZERO ; + char const *delim = "\"" ; + unsigned int delimlen ; + unsigned int startquote = 1 ; + PROG = "s6-quote-filter" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "ud:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'u' : startquote = 0 ; break ; + case 'd': delim = l.arg ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + delimlen = str_len(delim) ; + if (startquote) + { + if(!delimlen) strerr_dief1x(100, "no character to quote with!") ; + if (!stralloc_catb(&dst, delim, 1)) + strerr_diefu1sys(111, "stralloc_catb") ; + } + for (;;) + { + int r ; + src.len = 0 ; + r = skagetln(buffer_0f1, &src, '\n') ; + if (!r) break ; + if ((r < 0) && (errno != EPIPE)) + strerr_diefu1sys(111, "read from stdin") ; + dst.len = startquote ; + if (!string_quote_nodelim_mustquote(&dst, src.s, src.len - (r > 0), delim, delimlen)) + { + int e = errno ; + buffer_flush(buffer_1) ; + errno = e ; + strerr_diefu1sys(111, "quote") ; + } + if (startquote) + { + if (!stralloc_catb(&dst, delim, 1)) + strerr_diefu1sys(111, "stralloc_catb") ; + } + if (r > 0) + { + if (!stralloc_catb(&dst, "\n", 1)) + strerr_diefu1sys(111, "stralloc_catb") ; + } + if (buffer_put(buffer_1, dst.s, dst.len) < 0) + strerr_diefu1sys(111, "write to stdout") ; + } + return 0 ; +} diff --git a/src/skaembutils/s6-quote.c b/src/skaembutils/s6-quote.c new file mode 100644 index 0000000..b370e39 --- /dev/null +++ b/src/skaembutils/s6-quote.c @@ -0,0 +1,58 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include + +#define USAGE "s6-quote [ -n ] [ -u ] [ -d delim ] string" + +int main (int argc, char const *const *argv) +{ + stralloc sa = STRALLOC_ZERO ; + char const *delim = "\"" ; + unsigned int delimlen ; + int nl = 1 ; + int startquote = 1 ; + PROG = "s6-quote" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "nud:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'n' : nl = 0 ; break ; + case 'u' : startquote = 0 ; break ; + case 'd': delim = l.arg ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) strerr_dieusage(100, USAGE) ; + delimlen = str_len(delim) ; + if (startquote) + { + if (!delimlen) strerr_dief1x(100, "no character to quote with!") ; + if (!stralloc_catb(&sa, delim, 1)) + strerr_diefu1sys(111, "stralloc_catb") ; + } + if (!string_quote_nodelim_mustquote(&sa, *argv, str_len(*argv), delim, delimlen)) + strerr_diefu1sys(111, "quote") ; + if (startquote) + { + if (!stralloc_catb(&sa, delim, 1)) + strerr_diefu1sys(111, "stralloc_catb") ; + } + if (nl) + { + if (!stralloc_catb(&sa, "\n", 1)) + strerr_diefu1sys(111, "stralloc_catb") ; + } + if (allwrite(1, sa.s, sa.len) < sa.len) + strerr_diefu1sys(111, "write to stdout") ; + return 0 ; +} diff --git a/src/skaembutils/s6-rename.c b/src/skaembutils/s6-rename.c new file mode 100644 index 0000000..55c92fa --- /dev/null +++ b/src/skaembutils/s6-rename.c @@ -0,0 +1,16 @@ +/* ISC license. */ + +#include +#include +#include + +#define USAGE "s6-rename old new" + +int main (int argc, char const *const *argv) +{ + PROG = "s6-rename" ; + if (argc < 3) strerr_dieusage(100, USAGE) ; + if (rename(argv[1], argv[2]) == -1) + strerr_diefu4sys(111, "rename ", argv[1], " to ", argv[2]) ; + return 0 ; +} diff --git a/src/skaembutils/s6-rmrf.c b/src/skaembutils/s6-rmrf.c new file mode 100644 index 0000000..4d57530 --- /dev/null +++ b/src/skaembutils/s6-rmrf.c @@ -0,0 +1,17 @@ +/* ISC license. */ + +#include +#include + +#define USAGE "s6-rmrf file ..." + +int main (int argc, char const *const *argv) +{ + char const *const *p = argv + 1 ; + PROG = "s6-rmrf" ; + if (argc < 2) strerr_dieusage(100, USAGE) ; + for (; *p ; p++) + if (rm_rf(*p) == -1) + strerr_diefu2sys(111, "remove ", argv[1]) ; + return 0 ; +} diff --git a/src/skaembutils/s6-sleep.c b/src/skaembutils/s6-sleep.c new file mode 100644 index 0000000..ea25514 --- /dev/null +++ b/src/skaembutils/s6-sleep.c @@ -0,0 +1,46 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-sleep [ -m ] duration prog..." + +int main (int argc, char const *const *argv, char const *const *envp) +{ + unsigned int n ; + int milli = 0 ; + PROG = "s6-sleep" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "m", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'm': milli = 1 ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) strerr_dieusage(100, USAGE) ; + if (!uint0_scan(argv[0], &n)) strerr_dieusage(100, USAGE) ; + + { + tain_t deadline ; + if (milli) tain_from_millisecs(&deadline, n) ; + else tain_uint(&deadline, n) ; + tain_now_g() ; + tain_add_g(&deadline, &deadline) ; + deepsleepuntil_g(&deadline) ; + } + + pathexec0_run(argv+1, envp) ; + strerr_dieexec(111, argv[1]) ; +} diff --git a/src/skaembutils/s6-sort.c b/src/skaembutils/s6-sort.c new file mode 100644 index 0000000..5b259b8 --- /dev/null +++ b/src/skaembutils/s6-sort.c @@ -0,0 +1,123 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-sort [ -bcfru0 ]" + +typedef int strncmp_t (char const *, unsigned int, char const *) ; +typedef strncmp_t *strncmp_t_ref ; +typedef int qsortcmp_t (void const *, void const *) ; +typedef qsortcmp_t *qsortcmp_t_ref ; + +static int flagnoblanks = 0, flagreverse = 0, flaguniq = 0 ; + +static int str_diffb_f (register char const *s1, register unsigned int n, register char const *s2) +{ + return str_diffb(s1, n, s2) ; +} + +static strncmp_t_ref comp = &str_diffb_f ; + +static int compit (register char const *s1, register unsigned int n1, register char const *s2, register unsigned int n2) +{ + register int r ; + if (flagnoblanks) + { + while ((*s1 == ' ') || (*s1 == '\t')) (s1++, n1--) ; + while ((*s2 == ' ') || (*s2 == '\t')) (s2++, n2--) ; + } + r = (*comp)(s1, n1 < n2 ? n1 : n2, s2) ; + if (!r) r = n1 - n2 ; + return flagreverse ? -r : r ; +} + +static int sacmp (stralloc const *a, stralloc const *b) +{ + return compit(a->s, a->len - 1, b->s, b->len - 1) ; +} + +static int slurplines (genalloc *lines, char sep) +{ + unsigned int i = 0 ; + for (;; i++) + { + stralloc sa = STRALLOC_ZERO ; + int r = skagetln(buffer_0, &sa, sep) ; + if (!r) break ; + if ((r < 0) && ((errno != EPIPE) || !stralloc_catb(&sa, &sep, 1))) + return -1 ; + stralloc_shrink(&sa) ; + if (!genalloc_append(stralloc, lines, &sa)) return -1 ; + } + return (int)i ; +} + +static void uniq (genalloc *lines) +{ + unsigned int len = genalloc_len(stralloc, lines) ; + register stralloc *s = genalloc_s(stralloc, lines) ; + register unsigned int i = 1 ; + for (; i < len ; i++) + if (!sacmp(s+i-1, s+i)) stralloc_free(s+i-1) ; +} + +static int outputlines (stralloc const *s, unsigned int len) +{ + register unsigned int i = 0 ; + for (; i < len ; i++) + if (buffer_put(buffer_1, s[i].s, s[i].len) < 0) return 0 ; + return buffer_flush(buffer_1) ; +} + +static int check (stralloc const *s, unsigned int len) +{ + register unsigned int i = 1 ; + for (; i < len ; i++) + if (sacmp(s+i-1, s+i) >= !flaguniq) return 0 ; + return 1 ; +} + +int main (int argc, char const *const *argv) +{ + genalloc lines = GENALLOC_ZERO ; /* array of stralloc */ + char sep = '\n' ; + int flagcheck = 0 ; + PROG = "s6-sort" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "bcfru0", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'b' : flagnoblanks = 1 ; break ; + case 'c' : flagcheck = 1 ; break ; + case 'f' : comp = &case_diffb ; break ; + case 'r' : flagreverse = 1 ; break ; + case 'u' : flaguniq = 1 ; break ; + case '0' : sep = '\0' ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + + if (slurplines(&lines, sep) < 0) strerr_diefu1sys(111, "read from stdin") ; + if (flagcheck) return !check(genalloc_s(stralloc, &lines), genalloc_len(stralloc, &lines)) ; + qsort(genalloc_s(stralloc, &lines), genalloc_len(stralloc, &lines), sizeof(stralloc), (qsortcmp_t_ref)&sacmp) ; + if (flaguniq) uniq(&lines) ; + if (!outputlines(genalloc_s(stralloc, &lines), genalloc_len(stralloc, &lines))) + strerr_diefu1sys(111, "write to stdout") ; + return 0 ; +} diff --git a/src/skaembutils/s6-sync.c b/src/skaembutils/s6-sync.c new file mode 100644 index 0000000..a8829cd --- /dev/null +++ b/src/skaembutils/s6-sync.c @@ -0,0 +1,9 @@ +/* ISC license. */ + +#include + +int main (void) +{ + sync() ; + return 0 ; +} diff --git a/src/skaembutils/s6-tail.c b/src/skaembutils/s6-tail.c new file mode 100644 index 0000000..cc2d1f1 --- /dev/null +++ b/src/skaembutils/s6-tail.c @@ -0,0 +1,200 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-tail [ -c chars | -n lines | -1..9 ] [ file ]" + +typedef int tailfunc_t (int, unsigned int) ; +typedef tailfunc_t *tailfunc_t_ref ; + +static int pluslines (int fd, unsigned int n) +{ + if (n) n-- ; + { + char buf[BUFFER_INSIZE] ; + buffer b = BUFFER_INIT(&buffer_read, fd, buf, BUFFER_INSIZE) ; + unsigned int count = 0 ; + while (count < n) + { + register int r = buffer_fill(&b) ; + if (r <= 0) return !r ; + while (!buffer_isempty(&b) && (count < n)) + { + siovec_t v[2] ; + unsigned int i ; + buffer_rpeek(&b, v) ; + i = siovec_bytechr(v, 2, '\n') ; + if (i < buffer_len(&b)) + { + count++ ; i++ ; + } + buffer_rseek(&b, i) ; + } + } + b.op = &buffer_write ; + b.fd = 1 ; + if (!buffer_flush(&b)) return 0 ; + } + return (fd_cat(fd, 1) >= 0) ; +} + +static int pluschars (int fd, unsigned int n) +{ + if (n-- > 1) + { + int nil = open_write("/dev/null") ; + if (nil < 0) return 0 ; + if (!fd_catn(fd, nil, n)) + { + register int e = errno ; + fd_close(nil) ; + errno = e ; + return 0 ; + } + fd_close(nil) ; + } + return (fd_cat(fd, 1) >= 0) ; +} + +static int minuslines (int fd, unsigned int n) +{ + char buf[BUFFER_INSIZE] ; + buffer b = BUFFER_INIT(&buffer_read, fd, buf, BUFFER_INSIZE) ; + unsigned int head = 0, tail = 0 ; + stralloc tab[n+1] ; + for (; head <= n ; head++) tab[head] = stralloc_zero ; + head = 0 ; + for (;;) + { + register int r ; + r = skagetln(&b, tab + tail, '\n') ; + if (!r) break ; + if (r < 0) + { + if (errno == EPIPE) break ; + else goto err ; + } + tail = (tail + 1) % (n+1) ; + if (tail == head) + { + tab[head].len = 0 ; + head = (head + 1) % (n+1) ; + } + } + buffer_init(&b, &buffer_write, 1, buf, BUFFER_INSIZE) ; + for (; head != tail ; head = (head + 1) % (n+1)) + { + if (buffer_put(&b, tab[head].s, tab[head].len) < tab[head].len) + goto err ; + } + for (head = 0 ; head <= n ; head++) stralloc_free(tab + head) ; + return buffer_flush(&b) ; + err: + for (head = 0 ; head <= n ; head++) stralloc_free(tab + head) ; + return 0 ; +} + +static int minuschars (int fd, unsigned int n) +{ + char buf[BUFFER_INSIZE + n] ; + buffer b = BUFFER_INIT(&buffer_read, fd, buf, BUFFER_INSIZE + n) ; + for (;;) + { + register int r = buffer_fill(&b) ; + if (!r) break ; + if (r < 0) return 0 ; + buffer_rseek(&b, buffer_len(&b)) ; + buffer_unget(&b, n) ; + } + b.op = &buffer_write ; + b.fd = 1 ; + return buffer_flush(&b) ; +} + +int main (int argc, char const *const *argv) +{ + tailfunc_t_ref f = &minuslines ; + unsigned int n = 10 ; + int gotit = 0 ; + PROG = "s6-tail" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "123456789n:c:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case '1' : + case '2' : + case '3' : + case '4' : + case '5' : + case '6' : + case '7' : + case '8' : + case '9' : + { + if (gotit) strerr_dieusage(100, USAGE) ; + gotit = 1 ; + f = &minuslines ; + n = opt - '0' ; + break ; + } + case 'n': + { + if (gotit) strerr_dieusage(100, USAGE) ; + gotit = 1 ; + f = &minuslines ; + if (*l.arg == '-') l.arg++ ; + else if (*l.arg == '+') + { + f = &pluslines ; + l.arg++ ; + } + if (!uint0_scan(l.arg, &n)) strerr_dieusage(100, USAGE) ; + break ; + } + case 'c': + { + if (gotit) strerr_dieusage(100, USAGE) ; + gotit = 1 ; + f = &minuschars ; + if (*l.arg == '-') l.arg++ ; + else if (*l.arg == '+') + { + f = &pluschars ; + l.arg++ ; + } + if (!uint0_scan(l.arg, &n)) strerr_dieusage(100, USAGE) ; + break ; + } + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) + { + if (!(*f)(0, n)) + strerr_diefu1sys(111, "tail stdin") ; + } + else + { + int fd = open_readb(argv[0]) ; + if (fd == -1) strerr_diefu3sys(111, "open ", argv[0], " for reading") ; + if (!(*f)(fd, n)) + strerr_diefu2sys(111, "tail ", argv[0]) ; + fd_close(fd) ; + } + return 0 ; +} diff --git a/src/skaembutils/s6-test.c b/src/skaembutils/s6-test.c new file mode 100644 index 0000000..3dda0b7 --- /dev/null +++ b/src/skaembutils/s6-test.c @@ -0,0 +1,515 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-test expression or [ expression ]" + +enum opnum +{ + T_NOT, + T_AND, + T_OR, + T_LEFTP, + T_RIGHTP, + T_BLOCK, + T_CHAR, + T_DIR, + T_EXIST, + T_REGULAR, + T_SGID, + T_SYMLINK, + T_STICKY, + T_NONZERO, + T_FIFO, + T_READABLE, + T_NONZEROFILE, + T_TERM, + T_SUID, + T_WRITABLE, + T_EXECUTABLE, + T_ZERO, + T_EUID, + T_EGID, + T_SOCKET, + T_MODIFIED, + T_NEWER, + T_OLDER, + T_DEVINO, + T_STREQUAL, + T_STRNEQUAL, + T_STRLESSER, + T_STRLESSERE, + T_STRGREATER, + T_STRGREATERE, + T_NUMEQUAL, + T_NUMNEQUAL, + T_NUMGREATER, + T_NUMGREATERE, + T_NUMLESSER, + T_NUMLESSERE +} ; + +struct token +{ + char const *string ; + enum opnum op ; + unsigned int type ; +} ; + +struct node +{ + enum opnum op ; + unsigned int type ; + unsigned int arg1 ; + unsigned int arg2 ; + char const *data ; +} ; + +static unsigned int lex (struct node *tree, char const *const *argv) +{ + static struct token const tokens[44] = + { + { "-n", T_NONZERO, 2 }, + { "-z", T_ZERO, 2 }, + { "=", T_STREQUAL, 3 }, + { "!=", T_STRNEQUAL, 3 }, + { "-eq", T_NUMEQUAL, 3 }, + { "-ne", T_NUMNEQUAL, 3 }, + { "-gt", T_NUMGREATER, 3 }, + { "-ge", T_NUMGREATERE, 3 }, + { "-lt", T_NUMLESSER, 3 }, + { "-le", T_NUMLESSERE, 3 }, + { "-f", T_REGULAR, 2 }, + { "-h", T_SYMLINK, 2 }, + { "-L", T_SYMLINK, 2 }, + { "-e", T_EXIST, 2 }, + { "-k", T_STICKY, 2 }, + { "-a", T_AND, 7 }, + { "-o", T_OR, 8 }, + { "!", T_NOT, 6 }, + { "(", T_LEFTP, 4 }, + { ")", T_RIGHTP, 5 }, + { "-b", T_BLOCK, 2 }, + { "-c", T_CHAR, 2 }, + { "-d", T_DIR, 2 }, + { "-g", T_SGID, 2 }, + { "-p", T_FIFO, 2 }, + { "-r", T_READABLE, 2 }, + { "-s", T_NONZEROFILE, 2 }, + { "-t", T_TERM, 2 }, + { "-u", T_SUID, 2 }, + { "-w", T_WRITABLE, 2 }, + { "-x", T_EXECUTABLE, 2 }, + { "-O", T_EUID, 2 }, + { "-U", T_EUID, 2 }, + { "-G", T_EGID, 2 }, + { "-S", T_SOCKET, 2 }, + { "-N", T_MODIFIED, 2 }, + { "-nt", T_NEWER, 3 }, + { "-ot", T_OLDER, 3 }, + { "-ef", T_DEVINO, 3 }, + { "<", T_STRLESSER, 3 }, + { "<=", T_STRLESSERE, 3 }, + { ">", T_STRGREATER, 3 }, + { ">=", T_STRGREATERE, 3 }, + { 0, 0, 0 } + } ; + register unsigned int pos = 0 ; + + for (; argv[pos] ; pos++) + { + unsigned int i = 0 ; + tree[pos].data = argv[pos] ; + for (i = 0 ; tokens[i].string ; i++) + if (!str_diff(argv[pos], tokens[i].string)) + { + tree[pos].op = tokens[i].op ; + tree[pos].type = tokens[i].type ; + break ; + } + if (!tokens[i].string) + { + tree[pos].op = T_NONZERO ; + tree[pos].type = 0 ; + tree[pos].arg1 = pos ; + if (*(argv[pos]) == '\\') tree[pos].data++ ; /* better than SUSv3 */ + } + } + return pos ; +} + +static unsigned int parse (struct node *tree, unsigned int n) +{ + static char const table[9][13] = + { + "xssssxsssxxxx", + "xxxxxaxxxxxxx", + "xsxxsxsssxxxx", + "sxxxxxxxxxxxx", + "xsxxsxsssxxxx", + "nxxxxNxxxAOEs", + "xsxxsxsssxxxx", + "nxxxxNxxxAsxx", + "nxxxxNxxxAOsx" + } ; + + unsigned int stack[n+2] ; + unsigned int sp = 0, pos = 0 ; + int cont = 1 ; + + stack[0] = n+1 ; + tree[n].type = 5 ; /* add ) for the final reduce */ + tree[n+1].type = 1 ; /* add EOF */ + + while (cont) + { + switch (table[tree[pos].type][tree[stack[sp]].type]) + { + case 'x' : /* error */ + { + char fmt[UINT_FMT] ; + fmt[uint_fmt(fmt, pos)] = 0 ; + strerr_dief2x(100, "parse error at argument ", fmt) ; + break ; + } + case 'a' : /* accept */ + { + cont = 0 ; + break ; + } + case 's' : /* shift */ + { + stack[++sp] = pos++ ; + break ; + } + case 'n' : /* reduce -> expr without nots, from atom */ + { + switch (tree[stack[sp-1]].type) + { + case 2 : + { + tree[stack[sp-1]].arg1 = stack[sp] ; + sp-- ; + break ; + } + case 3 : + { + tree[stack[sp-1]].arg1 = stack[sp-2] ; + tree[stack[sp-1]].arg2 = stack[sp] ; + stack[sp-2] = stack[sp-1] ; + sp -= 2 ; + break ; + } + /* default : assert: its a zero */ + } + tree[stack[sp]].type = 9 ; + while (tree[stack[sp-1]].type == 6) + { + tree[stack[sp-1]].type = 9 ; + tree[stack[sp-1]].arg1 = stack[sp] ; + sp-- ; + } + break ; + } + case 'N' : /* reduce -> expr without nots, from expr */ + { + if (tree[stack[sp-2]].type != 4) + { + char fmt[UINT_FMT] ; + fmt[uint_fmt(fmt, pos)] = 0 ; + strerr_dief2x(100, "parse error: bad right parenthesis at argument ", fmt) ; + } + stack[sp-2] = stack[sp-1] ; + sp -= 2 ; + tree[stack[sp]].type = 9 ; + while (tree[stack[sp-1]].type == 6) + { + tree[stack[sp-1]].type = 9 ; + tree[stack[sp-1]].arg1 = stack[sp] ; + sp-- ; + } + break ; + } + case 'A' : /* reduce -> exprs without ands */ + { + if (tree[stack[sp-1]].type == 7) + { + tree[stack[sp-1]].arg1 = stack[sp-2] ; + tree[stack[sp-1]].arg2 = stack[sp] ; + stack[sp-2] = stack[sp-1] ; + sp -= 2 ; + } + tree[stack[sp]].type = 10 ; + break ; + } + case 'O' : /* reduce -> expr without ors */ + { + if (tree[stack[sp-1]].type == 8) + { + tree[stack[sp-1]].arg1 = stack[sp-2] ; + tree[stack[sp-1]].arg2 = stack[sp] ; + stack[sp-2] = stack[sp-1] ; + sp -= 2 ; + } + tree[stack[sp]].type = 11 ; + break ; + } + case 'E' : /* reduce -> expr */ + { + tree[stack[sp]].type = 12 ; + break ; + } + default : /* can't happen */ + strerr_dief1x(101, "internal error, please submit a bug-report.") ; + } + } + if (sp != 2) strerr_dief1x(100, "parse error: too many left parentheses") ; + return stack[1] ; +} + +static int run (struct node const *tree, unsigned int root) +{ + switch (tree[root].op) + { + case T_NOT : + return !run(tree, tree[root].arg1) ; + case T_AND : + return run(tree, tree[root].arg1) && run(tree, tree[root].arg2) ; + case T_OR : + return run(tree, tree[root].arg1) || run(tree, tree[root].arg2) ; + case T_EXIST : + { + struct stat st ; + return !stat(tree[tree[root].arg1].data, &st) ; + } + case T_BLOCK : + { + struct stat st ; + if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; + return S_ISBLK(st.st_mode) ; + } + case T_CHAR : + { + struct stat st ; + if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; + return S_ISCHR(st.st_mode) ; + } + case T_DIR : + { + struct stat st ; + if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; + return S_ISDIR(st.st_mode) ; + } + case T_REGULAR : + { + struct stat st ; + if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; + return S_ISREG(st.st_mode) ; + } + case T_FIFO : + { + struct stat st ; + if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; + return S_ISFIFO(st.st_mode) ; + } + case T_SOCKET : + { + struct stat st ; + if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; + return S_ISSOCK(st.st_mode) ; + } + case T_SYMLINK : + { + struct stat st ; + if (lstat(tree[tree[root].arg1].data, &st) == -1) return 0 ; + return S_ISLNK(st.st_mode) ; + } + case T_SGID : + { + struct stat st ; + if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; + return (st.st_mode & S_ISGID) ; + } + case T_SUID : + { + struct stat st ; + if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; + return (st.st_mode & S_ISUID) ; + } + case T_STICKY : + { + struct stat st ; + if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; + return (st.st_mode & S_ISVTX) ; + } + case T_NONZEROFILE : + { + struct stat st ; + if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; + return (st.st_size > 0) ; + } + case T_MODIFIED : + { + struct stat st ; + if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; + return (st.st_mtime > st.st_atime) ; + } + case T_EUID : + { + struct stat st ; + if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; + return st.st_uid == geteuid() ; + } + case T_EGID : + { + struct stat st ; + if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; + return st.st_gid == getegid() ; + } + case T_READABLE : + { + struct stat st ; + if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; + if (st.st_uid == geteuid()) return st.st_mode & S_IRUSR ; + else if (st.st_gid == getegid()) return st.st_mode & S_IRGRP ; + else return st.st_mode & S_IROTH ; + } + case T_WRITABLE : + { + struct stat st ; + if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; + if (st.st_uid == geteuid()) return st.st_mode & S_IWUSR ; + else if (st.st_gid == getegid()) return st.st_mode & S_IWGRP ; + else return st.st_mode & S_IWOTH ; + } + case T_EXECUTABLE : + { + struct stat st ; + if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; + if (st.st_uid == geteuid()) return st.st_mode & S_IXUSR ; + else if (st.st_gid == getegid()) return st.st_mode & S_IXGRP ; + else return st.st_mode & S_IXOTH ; + } + case T_NEWER : + { + struct stat st1, st2 ; + if (stat(tree[tree[root].arg1].data, &st1) == -1) return 0 ; + if (stat(tree[tree[root].arg2].data, &st2) == -1) return 1 ; + return st1.st_mtime > st2.st_mtime ; + } + case T_OLDER : + { + struct stat st1, st2 ; + if (stat(tree[tree[root].arg1].data, &st1) == -1) return 1 ; + if (stat(tree[tree[root].arg2].data, &st2) == -1) return 0 ; + return st1.st_mtime < st2.st_mtime ; + } + case T_DEVINO : + { + struct stat st1, st2 ; + if (stat(tree[tree[root].arg1].data, &st1) == -1) return 0 ; + if (stat(tree[tree[root].arg2].data, &st2) == -1) return 1 ; + return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino) ; + } + case T_TERM : + { + unsigned int fd ; + if (!uint0_scan(tree[tree[root].arg1].data, &fd)) + strerr_dief2x(100, tree[root].data, " requires an integer argument") ; + return isatty((int)fd) ; + } + case T_NONZERO : + return tree[tree[root].arg1].data[0] ; + case T_ZERO : + return !tree[tree[root].arg1].data[0] ; + case T_STREQUAL : + return !str_diff(tree[tree[root].arg1].data, tree[tree[root].arg2].data) ; + case T_STRNEQUAL : + return !!str_diff(tree[tree[root].arg1].data, tree[tree[root].arg2].data) ; + case T_STRLESSER : + return str_diff(tree[tree[root].arg1].data, tree[tree[root].arg2].data) < 0 ; + case T_STRLESSERE : + return str_diff(tree[tree[root].arg1].data, tree[tree[root].arg2].data) <= 0 ; + case T_STRGREATER : + return str_diff(tree[tree[root].arg1].data, tree[tree[root].arg2].data) > 0 ; + case T_STRGREATERE : + return str_diff(tree[tree[root].arg1].data, tree[tree[root].arg2].data) >= 0 ; + case T_NUMEQUAL : + { + int n1, n2 ; + if (!int_scan(tree[tree[root].arg1].data, &n1) + || !int_scan(tree[tree[root].arg2].data, &n2)) + goto errorint ; + return n1 == n2 ; + } + case T_NUMNEQUAL : + { + int n1, n2 ; + if (!int_scan(tree[tree[root].arg1].data, &n1) + || !int_scan(tree[tree[root].arg2].data, &n2)) + goto errorint ; + return n1 != n2 ; + } + case T_NUMGREATER : + { + int n1, n2 ; + if (!int_scan(tree[tree[root].arg1].data, &n1) + || !int_scan(tree[tree[root].arg2].data, &n2)) + goto errorint ; + return n1 > n2 ; + } + case T_NUMGREATERE : + { + int n1, n2 ; + if (!int_scan(tree[tree[root].arg1].data, &n1) + || !int_scan(tree[tree[root].arg2].data, &n2)) + goto errorint ; + return n1 >= n2 ; + } + case T_NUMLESSER : + { + int n1, n2 ; + if (!int_scan(tree[tree[root].arg1].data, &n1) + || !int_scan(tree[tree[root].arg2].data, &n2)) + goto errorint ; + return n1 < n2 ; + } + case T_NUMLESSERE : + { + int n1, n2 ; + if (!int_scan(tree[tree[root].arg1].data, &n1) + || !int_scan(tree[tree[root].arg2].data, &n2)) + goto errorint ; + return n1 <= n2 ; + } + default: + strerr_dief1x(111, "operation not implemented") ; + } + +errorint: + strerr_dief2x(100, tree[root].data, " requires integer arguments") ; +} + +int main (int argc, char const *const *argv) +{ + PROG = "s6-test" ; + if (argc <= 1) return 1 ; + { + struct node tree[argc + 2] ; + unsigned int n = lex(tree, argv+1) ; + if ((argv[0][0] == '[') && !argv[0][1]) + { + if (n && (!tree[n-1].type) && (tree[n-1].data[0] == ']') && !tree[n-1].data[1]) + n-- ; + else strerr_dief1x(100, "parse error: missing closing bracket") ; + } + return !run(tree, parse(tree, n)) ; + } +} diff --git a/src/skaembutils/s6-touch.c b/src/skaembutils/s6-touch.c new file mode 100644 index 0000000..b149835 --- /dev/null +++ b/src/skaembutils/s6-touch.c @@ -0,0 +1,20 @@ +/* ISC license. */ + +#include +#include + +#define USAGE "s6-touch file ..." + +int main (int argc, char const *const *argv) +{ + char const *const *p = argv + 1 ; + PROG = "s6-touch" ; + if (argc < 2) strerr_dieusage(100, USAGE) ; + for (; *p ; p++) + { + register int fd = open_append(*p) ; + if (fd < 0) strerr_diefu2sys(111, "open_append ", *p) ; + fd_close(fd) ; + } + return 0 ; +} diff --git a/src/skaembutils/s6-true.c b/src/skaembutils/s6-true.c new file mode 100644 index 0000000..65c3af4 --- /dev/null +++ b/src/skaembutils/s6-true.c @@ -0,0 +1,6 @@ +/* ISC license. */ + +int main () +{ + return 0 ; +} diff --git a/src/skaembutils/s6-uniquename.c b/src/skaembutils/s6-uniquename.c new file mode 100644 index 0000000..06418e5 --- /dev/null +++ b/src/skaembutils/s6-uniquename.c @@ -0,0 +1,40 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-uniquename [ -n randomlen ] prefix" +#define usage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv) +{ + stralloc sa = STRALLOC_ZERO ; + unsigned int n = 8 ; + PROG = "s6-uniquename" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "n:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'n' : if (!uint0_scan(l.arg, &n)) usage() ; break ; + default : usage() ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (argc < 1) usage() ; + if (!stralloc_cats(&sa, argv[0])) strerr_diefu1sys(111, "stralloc_cats") ; + if ((n ? random_sauniquename(&sa, n) : sauniquename(&sa)) < 0) + strerr_diefu1sys(111, "make unique name") ; + if (!stralloc_catb(&sa, "\n", 1)) strerr_diefu1sys(111, "stralloc_cats") ; + if (allwrite(1, sa.s, sa.len) < sa.len) strerr_diefu1sys(111, "write to stdout") ; + return 0 ; +} diff --git a/src/skaembutils/s6-unquote-filter.c b/src/skaembutils/s6-unquote-filter.c new file mode 100644 index 0000000..08477ef --- /dev/null +++ b/src/skaembutils/s6-unquote-filter.c @@ -0,0 +1,198 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-unquote-filter [ -q | -Q | -v | -w ] [ -d delim ]" + +static unsigned int strictness = 1 ; +static char const *delim = "\"" ; +static unsigned int delimlen = 1 ; + +static void fillfmt (char *fmt, char const *s, unsigned int len) +{ + register unsigned int n = len < 39 ? len+1 : 36 ; + byte_copy(fmt, n, s) ; + if (len >= 39) + { + byte_copy(fmt+n, 3, "...") ; + n += 3 ; + } + fmt[n] = 0 ; +} + +static int doit (char const *s, unsigned int len) +{ + if (delimlen) + { + if (!len) + { + switch (strictness) + { + case 1 : + case 2 : + strerr_warnw1x("empty line") ; + break ; + case 3 : + buffer_flush(buffer_1) ; + strerr_dief1x(100, "empty line") ; + default : break ; + } + return 1 ; + } + if (byte_chr(delim, delimlen, *s) >= delimlen) + { + switch (strictness) + { + case 0 : return 0 ; + case 1 : + { + strerr_warnw1x("invalid starting quote character") ; + return 0 ; + } + case 2 : + { + char fmt[40] ; + fillfmt(fmt, s, len) ; + strerr_warnw3x("invalid starting quote character", " in line: ", fmt) ; + return 0 ; + } + case 3 : + { + buffer_flush(buffer_1) ; + strerr_dief1x(100, "invalid starting quote character") ; + } + default : strerr_dief1x(101, "can't happen: unknown strictness") ; + } + } + } + { + unsigned int r, w ; + char d[len] ; + if (!string_unquote_withdelim(d, &w, s + !!delimlen, len - !!delimlen, &r, delim, delimlen)) + { + switch (strictness) + { + case 0 : return 0 ; + case 1 : + { + strerr_warnwu1sys("unquote") ; + return 0 ; + } + case 2 : + { + char fmt[40] ; + fillfmt(fmt, s, len) ; + strerr_warnwu3sys("unquote", " line: ", fmt) ; + return 0 ; + } + case 3 : + { + int e = errno ; + buffer_flush(buffer_1) ; + errno = e ; + strerr_diefu1sys(100, "unquote") ; + } + default : strerr_dief1x(101, "can't happen: unknown strictness") ; + } + } + if (delimlen) + { + if (r+1 == len) + { + switch (strictness) + { + case 0 : return 0 ; + case 1 : + { + strerr_warnwu2x("unquote", ": no ending quote character") ; + return 0 ; + } + case 2 : + { + char fmt[40] ; + fillfmt(fmt, s, len) ; + strerr_warnwu5x("unquote", ": no ending quote character", " in ", "line: ", fmt) ; + return 0 ; + } + case 3 : + { + int e = errno ; + buffer_flush(buffer_1) ; + errno = e ; + strerr_diefu2x(100, "unquote", ": no ending quote character") ; + } + default : strerr_dief1x(101, "can't happen: unknown strictness") ; + } + } + else if ((r+2 < len) && (strictness >= 2)) + { + char fmtnum[UINT_FMT] ; + char fmtden[UINT_FMT] ; + char fmt[40] ; + fillfmt(fmt, s, len) ; + fmtnum[uint_fmt(fmtnum, r+1)] = 0 ; + fmtden[uint_fmt(fmtden, len-1)] = 0 ; + strerr_warnw7x("found ending quote character at position ", fmtnum, "/", fmtden, ", ignoring remainder of ", "line: ", fmt) ; + } + } + if (buffer_put(buffer_1, d, w) < (int)w) + strerr_diefu1sys(111, "write to stdout") ; + } + return 1 ; +} + + +int main (int argc, char const *const *argv) +{ + stralloc src = STRALLOC_ZERO ; + PROG = "s6-unquote-filter" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "qQvwd:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'q': strictness = 0 ; break ; + case 'Q': strictness = 1 ; break ; + case 'v': strictness = 2 ; break ; + case 'w': strictness = 3 ; break ; + case 'd': delim = l.arg ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + delimlen = str_len(delim) ; + for (;;) + { + int r ; + src.len = 0 ; + r = skagetln(buffer_0f1, &src, '\n') ; + if (!r) break ; + if (r < 0) + { + if (errno != EPIPE) strerr_diefu1sys(111, "read from stdin") ; + } + else src.len-- ; + if (!doit(src.s, src.len)) + { + if (buffer_put(buffer_1, src.s, src.len) < (int)src.len) + strerr_diefu1sys(111, "write to stdout") ; + } + if (r > 0) + { + if (buffer_put(buffer_1, "\n", 1) < 1) + strerr_diefu1sys(111, "write to stdout") ; + } + } + return 0 ; +} diff --git a/src/skaembutils/s6-unquote.c b/src/skaembutils/s6-unquote.c new file mode 100644 index 0000000..37c3dfb --- /dev/null +++ b/src/skaembutils/s6-unquote.c @@ -0,0 +1,70 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-unquote [ -n ] [ -d delim ] string" + +int main (int argc, char const *const *argv) +{ + char const *delim = "\"" ; + unsigned int len, delimlen ; + int nl = 1 ; + char const *string ; + PROG = "s6-unquote" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "nd:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'n' : nl = 0 ; break ; + case 'd': delim = l.arg ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) strerr_dieusage(100, USAGE) ; + string = *argv ; + len = str_len(string) ; + delimlen = str_len(delim) ; + if (delimlen) + { + if (!len--) strerr_dief1x(100, "the empty string isn't a quoted string") ; + if (byte_chr(delim, delimlen, *string++) >= delimlen) + strerr_dief1x(100, "invalid starting quote character") ; + } + { + unsigned int r = 0, w = 0 ; + char buf[len+1] ; + if (!string_unquote_withdelim(buf, &w, string, len, &r, delim, delimlen)) + { + char fmt[UINT_FMT] ; + fmt[uint_fmt(fmt, r + !!delimlen)] = 0 ; + strerr_diefu2sys(100, "unquote at character ", fmt) ; + } + if (delimlen) + { + if (r == len) strerr_dief1x(100, "no ending quote character") ; + else if (r < len - 1) + { + char fmtnum[UINT_FMT] ; + char fmtden[UINT_FMT] ; + fmtnum[uint_fmt(fmtnum, r+1)] = 0 ; + fmtden[uint_fmt(fmtden, len)] = 0 ; + strerr_warnw5x("found ending quote character at position ", fmtnum, "/", fmtden, "; ignoring remainder") ; + } + } + if (nl) buf[w++] = '\n' ; + if (allwrite(1, buf, w) < w) + strerr_diefu1sys(111, "write to stdout") ; + } + return 0 ; +} diff --git a/src/skaembutils/s6-update-symlinks.c b/src/skaembutils/s6-update-symlinks.c new file mode 100644 index 0000000..ba89b06 --- /dev/null +++ b/src/skaembutils/s6-update-symlinks.c @@ -0,0 +1,367 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "s6-update-symlinks /destdir /srcdir [ /srcdir ... ]" + +#define MAGICNEW ":s6-update-symlinks-new" +#define MAGICOLD ":s6-update-symlinks-old" + +#define CONFLICT -2 +#define ERROR -1 +#define MODIFIED 0 +#define OVERRIDEN 1 + +static stralloc errdst = STRALLOC_ZERO ; +static stralloc errsrc = STRALLOC_ZERO ; + + +typedef struct stralloc3 stralloc3, *stralloc3_ref ; +struct stralloc3 +{ + stralloc dst ; + stralloc src ; + stralloc tmp ; +} ; + +#define STRALLOC3_ZERO { STRALLOC_ZERO, STRALLOC_ZERO, STRALLOC_ZERO } + + +static void cleanup (stralloc *sa, unsigned int pos) +{ + register int e = errno ; + rm_rf_in_tmp(sa, pos) ; + errno = e ; +} + + +static int makeuniquename (stralloc *sa, char const *path, char const *magic) +{ + unsigned int base = sa->len ; + int wasnull = !sa->s ; + if (!stralloc_cats(sa, path)) return 0 ; + if (!stralloc_cats(sa, magic)) goto err ; + if (random_sauniquename(sa, 8) == -1) goto err ; + if (!stralloc_0(sa)) goto err ; + return 1 ; + +err: + if (wasnull) stralloc_free(sa) ; else sa->len = base ; + return 0 ; +} + + +static int addlink (stralloc3 *blah, unsigned int dstpos, unsigned int srcpos) +{ + if (symlink(blah->src.s + srcpos, blah->dst.s + dstpos) >= 0) return MODIFIED ; + if (errno != EEXIST) return ERROR ; + + { + unsigned int dstbase = blah->dst.len ; + unsigned int srcbase = blah->src.len ; + unsigned int tmpbase = blah->tmp.len ; + unsigned int dststop ; + unsigned int srcstop ; + signed int diffsize = 0 ; + int collect = 1 ; + + { + register unsigned int n = str_len(blah->dst.s + dstpos) ; + if (!stralloc_readyplus(&blah->dst, n+1)) return ERROR ; + stralloc_catb(&blah->dst, blah->dst.s + dstpos, n) ; + } + stralloc_catb(&blah->dst, "/", 1) ; + dststop = blah->dst.len ; + + { + int r ; + DIR *dir = opendir(blah->dst.s + dstpos) ; + if (!dir) + { + blah->dst.len = dstbase ; + if (errno != ENOTDIR) return ERROR ; + if ((unlink(blah->dst.s + dstpos) == -1) + || (symlink(blah->src.s + srcpos, blah->dst.s + dstpos) == -1)) + return ERROR ; + return OVERRIDEN ; /* replaced a link to a normal file */ + } + r = sareadlink(&blah->src, blah->dst.s + dstpos) ; + if ((r == -1) && (errno != EINVAL)) + { + register int e = errno ; + blah->dst.len = dstbase ; + dir_close(dir) ; + errno = e ; + return ERROR ; + } + if (r < 0) + { + for (;;) + { + register direntry *d ; + errno = 0 ; + d = readdir(dir) ; + if (!d) break ; + if ((d->d_name[0] == '.') && (!d->d_name[1] || ((d->d_name[1] == '.') && !d->d_name[2]))) + continue ; + diffsize-- ; /* need to know the size for collect */ + } + if (errno) + { + register int e = errno ; + blah->src.len = srcbase ; + blah->dst.len = dstbase ; + dir_close(dir) ; + errno = e ; + return ERROR ; + } + } + else if ((unlink(blah->dst.s + dstpos) == -1) + || (mkdir(blah->dst.s + dstpos, 0777) == -1) + || !stralloc_catb(&blah->src, "/", 1)) + { + register int e = errno ; + blah->src.len = srcbase ; + blah->dst.len = dstbase ; + dir_close(dir) ; + errno = e ; + return ERROR ; + } + else /* expand */ + { + srcstop = blah->src.len ; + for (;;) + { + register direntry *d ; + errno = 0 ; + d = readdir(dir) ; + if (!d) break ; + if ((d->d_name[0] == '.') && (!d->d_name[1] || ((d->d_name[1] == '.') && !d->d_name[2]))) + continue ; + diffsize-- ; + blah->dst.len = dststop ; + blah->src.len = srcstop ; + if (!stralloc_cats(&blah->dst, d->d_name) || !stralloc_0(&blah->dst) + || !stralloc_cats(&blah->src, d->d_name) || !stralloc_0(&blah->src) + || (symlink(blah->src.s + srcbase, blah->dst.s + dstbase) == -1)) + { + register int e = errno ; + blah->src.len = srcbase ; + blah->dst.len = dstbase ; + dir_close(dir) ; + errno = e ; + return ERROR ; + } + } + if (errno) + { + register int e = errno ; + blah->src.len = srcbase ; + blah->dst.len = dstbase ; + dir_close(dir) ; + errno = e ; + return ERROR ; + } + } + dir_close(dir) ; + } + + blah->src.len = srcbase ; + { + register unsigned int n = str_len(blah->src.s + srcpos) ; + if (!stralloc_readyplus(&blah->src, n+1)) + { + blah->dst.len = dstbase ; + return ERROR ; + } + stralloc_catb(&blah->src, blah->src.s + srcpos, n) ; + } + stralloc_catb(&blah->src, "/", 1) ; + srcstop = blah->src.len ; + + + /* prepare tmp for recursion */ + + { + DIR *dir = opendir(blah->src.s + srcpos) ; + if (!dir) + { + blah->src.len = srcbase ; + blah->dst.len = dstbase ; + if (errno != ENOTDIR) return ERROR ; + errdst.len = errsrc.len = 0 ; + if (!stralloc_cats(&errdst, blah->dst.s + dstpos) || !stralloc_0(&errdst) + || !stralloc_cats(&errsrc, blah->src.s + srcpos) || !stralloc_0(&errsrc)) + return ERROR ; + return CONFLICT ; /* dst is a dir but src is not */ + } + for (;;) + { + register direntry *d ; + errno = 0 ; + d = readdir(dir) ; + if (!d) break ; + if ((d->d_name[0] == '.') && (!d->d_name[1] || ((d->d_name[1] == '.') && !d->d_name[2]))) + continue ; + if (!stralloc_cats(&blah->tmp, d->d_name) || !stralloc_0(&blah->tmp)) + { + register int e = errno ; + blah->tmp.len = tmpbase ; + blah->src.len = srcbase ; + blah->dst.len = dstbase ; + dir_close(dir) ; + errno = e ; + return ERROR ; + } + } + if (errno) + { + register int e = errno ; + blah->tmp.len = tmpbase ; + blah->src.len = srcbase ; + blah->dst.len = dstbase ; + dir_close(dir) ; + errno = e ; + return ERROR ; + } + dir_close(dir) ; + } + + + /* recurse */ + + { + unsigned int i = tmpbase ; + while (i < blah->tmp.len) + { + diffsize++ ; + blah->dst.len = dststop ; + blah->src.len = srcstop ; + { + register unsigned int n = str_len(blah->tmp.s + i) + 1 ; + if (!stralloc_catb(&blah->dst, blah->tmp.s + i, n) + || !stralloc_catb(&blah->src, blah->tmp.s + i, n)) + { + blah->tmp.len = tmpbase ; + blah->src.len = srcbase ; + blah->dst.len = dstbase ; + return ERROR ; + } + i += n ; + } + switch (addlink(blah, dstbase, srcbase)) + { + case ERROR : + blah->tmp.len = tmpbase ; + blah->src.len = srcbase ; + blah->dst.len = dstbase ; + return ERROR ; + case CONFLICT : + blah->tmp.len = tmpbase ; + blah->src.len = srcbase ; + blah->dst.len = dstbase ; + return CONFLICT ; + case MODIFIED : + collect = 0 ; + } + } + } + blah->tmp.len = tmpbase ; + blah->src.len = srcbase ; + blah->dst.len = dstbase ; + + + /* collect */ + + if (collect && !diffsize) + { + if (rm_rf_in_tmp(&blah->dst, dstpos) == -1) return ERROR ; + if (symlink(blah->src.s + srcpos, blah->dst.s + dstpos) == -1) return ERROR ; + return OVERRIDEN ; + } + } + return MODIFIED ; +} + +int main (int argc, char *const *argv) +{ + stralloc3 blah = STRALLOC3_ZERO ; + PROG = "s6-update-symlinks" ; + if (argc < 3) strerr_dieusage(100, USAGE) ; + { + register char *const *p = argv + 1 ; + for (; *p ; p++) if (**p != '/') strerr_dieusage(100, USAGE) ; + } + { + register unsigned int i = str_len(argv[1]) ; + while (i && (argv[1][i-1] == '/')) argv[1][--i] = 0 ; + if (!i) strerr_diefu1x(100, "replace root directory") ; + } + if (!makeuniquename(&blah.dst, argv[1], MAGICNEW)) + strerr_diefu2sys(111, "make random unique name based on ", argv[1]) ; + if ((unlink(blah.dst.s) == -1) && (errno != ENOENT)) + strerr_diefu2sys(111, "unlink ", blah.dst.s) ; + + { + char *const *p = argv + 2 ; + for (; *p ; p++) + { + register int r ; + blah.src.len = 0 ; + if (!stralloc_cats(&blah.src, *p) || !stralloc_0(&blah.src)) + strerr_diefu1sys(111, "make stralloc") ; + r = addlink(&blah, 0, 0) ; + if (r < 0) + { + stralloc_free(&blah.tmp) ; + stralloc_free(&blah.src) ; + cleanup(&blah.dst, 0) ; + stralloc_free(&blah.dst) ; + if (r == CONFLICT) + strerr_dief4x(100, "destination ", errdst.s, " conflicts with source ", errsrc.s) ; + else + strerr_dief2sys(111, "error processing ", *p) ; + } + } + } + stralloc_free(&blah.tmp) ; + + if (rename(blah.dst.s, argv[1]) == -1) /* be atomic if possible */ + { + blah.src.len = 0 ; + if (!makeuniquename(&blah.src, argv[1], MAGICOLD)) + { + cleanup(&blah.dst, 0) ; + strerr_diefu2sys(111, "make random unique name based on ", argv[1]) ; + } + + if (rename(argv[1], blah.src.s) == -1) + { + cleanup(&blah.dst, 0) ; + strerr_diefu4sys(111, "rename ", argv[1], " to ", blah.src.s) ; + } + /* XXX: unavoidable race condition here: argv[1] does not exist */ + if (rename(blah.dst.s, argv[1]) == -1) + { + rename(blah.src.s, argv[1]) ; + cleanup(&blah.dst, 0) ; + strerr_diefu4sys(111, "rename ", blah.dst.s, " to ", argv[1]) ; + } + stralloc_free(&blah.dst) ; + if (rm_rf_in_tmp(&blah.src, 0) == -1) + strerr_warnwu2sys("remove old directory ", blah.src.s) ; + stralloc_free(&blah.src) ; + } + + return 0 ; +} diff --git a/tools/gen-deps.sh b/tools/gen-deps.sh new file mode 100755 index 0000000..af31259 --- /dev/null +++ b/tools/gen-deps.sh @@ -0,0 +1,79 @@ +#!/bin/sh -e + +. package/info + +echo '#' +echo '# This file has been generated by tools/gen-deps.sh' +echo '#' +echo + +for dir in src/include/${package} src/* ; do + for file in $(ls -1 $dir | grep -- \\.h$) ; do + { + grep -F -- "#include <${package}/" < ${dir}/$file | cut -d'<' -f2 | cut -d'>' -f1 ; + grep -- '#include ".*\.h"' < ${dir}/$file | cut -d'"' -f2 + } | sort -u | { + deps= + while read dep ; do + if echo $dep | grep -q "^${package}/" ; then + deps="$deps src/include/$dep" + elif test -f "${dir}/$dep" ; then + deps="$deps ${dir}/$dep" + else + deps="$deps src/include-local/$dep" + fi + done + if test -n "$deps" ; then + echo "${dir}/${file}:${deps}" + fi + } + done +done + +for dir in src/* ; do + for file in $(ls -1 $dir | grep -- \\.c$) ; do + { + grep -F -- "#include <${package}/" < ${dir}/$file | cut -d'<' -f2 | cut -d'>' -f1 ; + grep -- '#include ".*\.h"' < ${dir}/$file | cut -d'"' -f2 + } | sort -u | { + deps=" ${dir}/$file" + while read dep ; do + if echo $dep | grep -q "^${package}/" ; then + deps="$deps src/include/$dep" + elif test -f "${dir}/$dep" ; then + deps="$deps ${dir}/$dep" + else + deps="$deps src/include-local/$dep" + fi + done + o=$(echo $file | sed s/\\.c$/.o/) + lo=$(echo $file | sed s/\\.c$/.lo/) + echo "${dir}/${o} ${dir}/${lo}:${deps}" + } + done +done +echo + +for dir in $(ls -1 src | grep -v ^include) ; do + for file in $(ls -1 src/$dir/deps-lib) ; do + deps= + while read dep ; do + deps="$deps src/$dir/$dep" + done < src/$dir/deps-lib/$file + echo "lib$file.a: $deps" + if test -x "src/$dir/deps-lib/$file" ; then + echo "lib${file}.so: $(echo "$deps" | sed 's/\.o/.lo/g')" + fi + done + + for file in $(ls -1 src/$dir/deps-exe) ; do + deps= + while read dep ; do + if echo $dep | grep -q -- \\.o$ ; then + dep="src/$dir/$dep" + fi + deps="$deps $dep" + done < src/$dir/deps-exe/$file + echo "$file: src/$dir/$file.o$deps" + done +done diff --git a/tools/install.sh b/tools/install.sh new file mode 100755 index 0000000..89f9428 --- /dev/null +++ b/tools/install.sh @@ -0,0 +1,64 @@ +#!/bin/sh + +usage() { + echo "usage: $0 [-D] [-l] [-m mode] src dst" 1>&2 + exit 1 +} + +mkdirp=false +symlink=false +mode=0755 + +while getopts Dlm: name ; do + case "$name" in + D) mkdirp=true ;; + l) symlink=true ;; + m) mode=$OPTARG ;; + ?) usage ;; + esac +done +shift $(($OPTIND - 1)) + +test "$#" -eq 2 || usage +src=$1 +dst=$2 +tmp="$dst.tmp.$$" + +case "$dst" in + */) echo "$0: $dst ends in /" 1>&2 ; exit 1 ;; +esac + +set -C +set -e + +if $mkdirp ; then + umask 022 + case "$2" in + */*) mkdir -p "${dst%/*}" ;; + esac +fi + +trap 'rm -f "$tmp"' EXIT INT QUIT TERM HUP + +umask 077 + +if $symlink ; then + ln -s "$src" "$tmp" +else + cat < "$1" > "$tmp" + chmod "$mode" "$tmp" +fi + +mv -f "$tmp" "$dst" +if test -d "$dst" ; then + rm -f "$dst/$(basename $tmp)" + if $symlink ; then + mkdir "$tmp" + ln -s "$src" "$tmp/$(basename $dst)" + mv -f "$tmp/$(basename $dst)" "${dst%/*}" + rmdir "$tmp" + else + echo "$0: $dst is a directory" 1>&2 + exit 1 + fi +fi -- cgit v1.2.3