diff options
136 files changed, 6723 insertions, 0 deletions
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 <ska-skaware@skarnet.org> + +Thanks to: + Dan J. Bernstein <djb@cr.yp.to> + Jean Marot <jean.marot@salle-s.org> + Jorge Almeida <jalmeida@math.ist.utl.pt> + Vallo Kallaste <kalts@estpak.ee> 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 <ska-skaware@skarnet.org> + +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/$(<F) $@ + +$(DESTDIR)$(sproot)/library.so/lib%.so: $(DESTDIR)$(dynlibdir)/lib%.so + exec $(INSTALL) -D -l ..$(exthome)/library.so/$(<F) $@ + +.PHONY: update global-links + +endif + +$(DESTDIR)$(dynlibdir)/lib%.so: lib%.so + $(INSTALL) -D -m 755 $< $@.$(version) && \ + $(INSTALL) -l $<.$(version) $@.$(version_m) && \ + $(INSTALL) -l $<.$(version_m) $@.$(version_M) && \ + $(INSTALL) -l $<.$(version_M) $@.$(version_l) && \ + exec $(INSTALL) -l $<.$(version_l) $@ + +$(DESTDIR)$(libexecdir)/% $(DESTDIR)$(bindir)/% $(DESTDIR)$(sbindir)/%: % package/modes + exec $(INSTALL) -D -m 600 $< $@ + grep -- ^$(@F) < package/modes | { read name mode owner && \ + if [ x$$owner != x ] ; then chown -- $$owner $@ ; fi && \ + chmod $$mode $@ ; } + +$(DESTDIR)$(libdir)/lib%.a: lib%.a + $(INSTALL) -D -m 644 $< $@ + +$(DESTDIR)$(includedir)/$(package)/%.h: src/include/$(package)/%.h + exec $(INSTALL) -D -m 644 $< $@ + +%.o: %.c + exec $(REALCC) $(CPPFLAGS_ALL) $(CFLAGS_ALL) -c -o $@ $< + +%.lo: %.c + exec $(REALCC) $(CPPFLAGS_ALL) $(CFLAGS_ALL) $(CFLAGS_SHARED) -c -o $@ $< + +$(ALL_BINS): + exec $(REALCC) -o $@ $(CFLAGS_ALL) $(LDFLAGS_ALL) $(LDFLAGS_NOSHARED) $^ $(LDLIBS_ALL) + +lib%.a: + exec $(AR) rc $@ $^ + exec $(RANLIB) $@ + +lib%.so: + exec $(REALCC) -o $@ $(CFLAGS_ALL) $(CFLAGS_SHARED) $(LDFLAGS_ALL) $(LDFLAGS_SHARED) -Wl,-soname,$@.$(version_l) $^ + +.PHONY: it all clean distclean tgz strip install install-dynlib install-bin install-sbin install-lib install-include + +.DELETE_ON_ERROR: diff --git a/README b/README new file mode 100644 index 0000000..49d52da --- /dev/null +++ b/README @@ -0,0 +1,25 @@ +s6-portable-utils - tiny general Unix utilities +----------------------------------------------- + +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. + + See http://skarnet.org/software/s6-portable-utils/ for details. + + +* Installation + ------------ + + See the INSTALL file. + + +* Contact information + ------------------- + + Laurent Bercot <ska-skaware at skarnet.org> + + Please use the <skaware at list.skarnet.org> 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 <<EOF +Usage: $0 [OPTION]... [VAR=VALUE]... [TARGET] + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +System types: + --target=TARGET configure to run on target TARGET [detected] + --host=TARGET same as --target + +Installation directories: + --prefix=PREFIX main installation prefix [/] + --exec-prefix=EPREFIX installation prefix for executable files [PREFIX] + +Fine tuning of the installation directories: + --dynlibdir=DIR shared library files [PREFIX/lib] + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR admin executables [EPREFIX/sbin] + --libexecdir=DIR package-scoped executables [EPREFIX/libexec] + --libdir=DIR static library files [PREFIX/lib] + --includedir=DIR include files for the C compiler [PREFIX/include] + +Dependencies: + --with-sysdeps=DIR use sysdeps in DIR [/usr/lib/skalibs/sysdeps] + --with-include=DIR add DIR to the list of searched directories for headers + --with-lib=DIR add DIR to the list of searched directories for static libraries + --with-dynlib=DIR add DIR to the list of searched directories for shared libraries + +Optional features: + --disable-allstatic do not prefer linking against static libraries [enabled] + --enable-static-libc make entirely static binaries [disabled] + --enable-slashpackage[=ROOT] assume /package installation at ROOT [disabled] + --enable-cross=PREFIX prefix toolchain executable names with PREFIX [none] + +EOF +exit 0 +} + + +# Helper functions + +# If your system does not have printf, you can comment this, but it is +# generally not a good idea to use echo. +# See http://www.etalabs.net/sh_tricks.html +echo () { + IFS=" " + printf %s\\n "$*" +} + +quote () { + tr '\n' ' ' <<EOF | grep '^[-[:alnum:]_=,./:]* $' >/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 <<EOF +/* ISC license. */ + +/* Generated by: $cmdline */ + +#ifndef ${package_macro_name}_CONFIG_H +#define ${package_macro_name}_CONFIG_H + +#define ${package_macro_name}_VERSION "$version" +EOF +if $slashpackage ; then + echo "#define ${package_macro_name}_BINPREFIX \"$binprefix\"" + echo "#define ${package_macro_name}_EXTBINPREFIX \"$extbinprefix\"" + echo "#define ${package_macro_name}_LIBEXECPREFIX \"$binprefix\"" +else + echo "#define ${package_macro_name}_BINPREFIX \"\"" + echo "#define ${package_macro_name}_EXTBINPREFIX \"\"" + echo "#define ${package_macro_name}_LIBEXECPREFIX \"$libexecdir\"" +fi +echo +echo "#endif" +exec 1>&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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils - skarnet.org's tiny general Unix utilities</title> + <meta name="Description" content="s6-portable-utils - skarnet.org's tiny general Unix utilities" /> + <meta name="Keywords" content="s6 unix administration root skarnet portable utilities tiny coreutils" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> s6-portable-utils </h1> + +<ul> +<li><a href="install.html">How to install s6-portable-utils</a></li> +<li><a href="upgrade.html">Upgrading from previous versions of s6-portable-utils</a></li> +</ul> + +<h2> What is it ? </h2> + +<p> + s6-portable-utils is a set of tiny general Unix utilities, often +performing well-known tasks such as <em>cut</em> and <em>grep</em>, +but optimized for simplicity and small size. They were designed +for embedded systems and other constrained environments, but they +work everywhere. +</p> + +<p> + Other set of small utilities are usually system-specific; for +instance, the (otherwise excellent) +<a href="http://busybox.net/">BusyBox</a> project only works on Linux. +</p> + +<p> + Some of s6-portable-utils' programs are a conformant implementation +of a POSIX utility as determined by the +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/nfindex.html">Single +Unix Specification, version 4</a>; the relevant documentation pages mentions +this. +However, none of the s6-portable-utils programs supports internationalization. +</p> + +<p> +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 +<a href="s6-uniquename.html"><tt>s6-uniquename</tt></a>. +</p> + +<hr /> + +<h2> Installation </h2> + +<h3> Requirements </h3> + +<ul> + <li> A POSIX-compliant system with a standard C development environment </li> + <li> GNU make, version 3.81 or later </li> + <li> <a href="http://skarnet.org/software/skalibs/">skalibs</a> version +2.0.0.0 or later </li> +</ul> + +<h3> Licensing </h3> + +<p> + s6-portable-utils is free software. It is available under the +<a href="http://opensource.org/licenses/ISC">ISC license</a>. +</p> + +<h3> Download </h3> + +<ul> + <li> The current released version of s6-portable-utils is +<a href="s6-portable-utils-2.0.0.0.tar.gz">2.0.0.0</a>. </li> + <li> Alternatively, you can checkout a copy of the s6-portable-utils git repository: +<pre> git clone git://git.skarnet.org/s6-portable-utils </pre> </li> +</ul> + +<h3> Compilation </h3> + +<ul> + <li> See the enclosed INSTALL file for installation details. </li> +</ul> + +<h3> Upgrade notes </h3> + +<ul> + <li> <a href="upgrade.html">This page</a> lists the differences to be aware of between +the previous versions of s6-portable-utils and the current one. </li> +</ul> + +<hr /> + +<h2> Reference </h2> + +<h3> Commands </h3> + +<p> + All these commands exit 111 if they encounter a temporary error, and +100 if they encounter a permanent error - such as a misuse. +</p> + +<ul> + <li> The <a href="s6-basename.html"><tt>s6-basename</tt></a> program </li> + <li> The <a href="s6-cat.html"><tt>s6-cat</tt></a> program </li> + <li> The <a href="s6-chmod.html"><tt>s6-chmod</tt></a> program </li> + <li> The <a href="s6-chown.html"><tt>s6-chown</tt></a> program </li> + <li> The <a href="s6-clock.html"><tt>s6-clock</tt></a> program </li> + <li> The <a href="s6-cut.html"><tt>s6-cut</tt></a> program </li> + <li> The <a href="s6-dirname.html"><tt>s6-dirname</tt></a> program </li> + <li> The <a href="s6-echo.html"><tt>s6-echo</tt></a> program </li> + <li> The <a href="s6-env.html"><tt>s6-env</tt></a> program </li> + <li> The <a href="s6-expr.html"><tt>s6-expr</tt></a> program </li> + <li> The <a href="s6-false.html"><tt>s6-false</tt></a> program </li> + <li> The <a href="s6-format-filter.html"><tt>s6-format-filter</tt></a> program </li> + <li> The <a href="s6-grep.html"><tt>s6-grep</tt></a> program </li> + <li> The <a href="s6-head.html"><tt>s6-head</tt></a> program </li> + <li> The <a href="s6-linkname.html"><tt>s6-linkname</tt></a> program </li> + <li> The <a href="s6-ln.html"><tt>s6-ln</tt></a> program </li> + <li> The <a href="s6-ls.html"><tt>s6-ls</tt></a> program </li> + <li> The <a href="s6-maximumtime.html"><tt>s6-maximumtime</tt></a> program </li> + <li> The <a href="s6-mkdir.html"><tt>s6-mkdir</tt></a> program </li> + <li> The <a href="s6-mkfifo.html"><tt>s6-mkfifo</tt></a> program </li> + <li> The <a href="s6-nice.html"><tt>s6-nice</tt></a> program </li> + <li> The <a href="s6-nuke.html"><tt>s6-nuke</tt></a> program </li> + <li> The <a href="s6-pause.html"><tt>s6-pause</tt></a> program </li> + <li> The <a href="s6-printenv.html"><tt>s6-printenv</tt></a> program </li> + <li> The <a href="s6-quote-filter.html"><tt>s6-quote-filter</tt></a> program </li> + <li> The <a href="s6-quote.html"><tt>s6-quote</tt></a> program </li> + <li> The <a href="s6-rename.html"><tt>s6-rename</tt></a> program </li> + <li> The <a href="s6-rmrf.html"><tt>s6-rmrf</tt></a> program </li> + <li> The <a href="s6-sleep.html"><tt>s6-sleep</tt></a> program </li> + <li> The <a href="s6-sort.html"><tt>s6-sort</tt></a> program </li> + <li> The <a href="s6-sync.html"><tt>s6-sync</tt></a> program </li> + <li> The <a href="s6-tail.html"><tt>s6-tail</tt></a> program </li> + <li> The <a href="s6-test.html"><tt>s6-test</tt></a> program </li> + <li> The <a href="s6-touch.html"><tt>s6-touch</tt></a> program </li> + <li> The <a href="s6-true.html"><tt>s6-true</tt></a> program </li> + <li> The <a href="s6-uniquename.html"><tt>s6-uniquename</tt></a> program </li> + <li> The <a href="s6-unquote-filter.html"><tt>s6-unquote-filter</tt></a> program </li> + <li> The <a href="s6-unquote.html"><tt>s6-unquote</tt></a> program </li> + <li> The <a href="s6-update-symlinks.html"><tt>s6-update-symlinks</tt></a> program </li> +</ul> + +<h2> Related resources </h2> + +<ul> + <li> <tt>s6-portable-utils</tt> is discussed on the +<a href="http://skarnet.org/lists.html#skaware">skaware</a> mailing-list. </li> + </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-basename program</title> + <meta name="Description" content="s6-portable-utils: the s6-basename program" /> + <meta name="Keywords" content="s6-portable-utils command s6-basename basename" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-basename</tt> program </h1> + +<p> + s6-basename prints the basename of a pathname. +</p> + +<h2> Interface </h2> + +<pre> + s6-basename [ -n ] <em>path</em> [ <em>suffix</em> ] +</pre> + +<p> + s6-basename acts as the generic +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/basename.html">basename</a> utility. +</p> + +<h2> Extra options </h2> + +<ul> + <li> <tt>-n</tt> : do not print a trailing newline after the output. </li> +</ul> + +<h2> Posixness </h2> + +<p> + s6-basename <strong>is</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/basename.html">basename</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-cat program</title> + <meta name="Description" content="s6-portable-utils: the s6-cat program" /> + <meta name="Keywords" content="s6-portable-utils command s6-cat cat" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-cat</tt> program </h1> + +<p> + s6-cat copies stdin to stdout. +</p> + +<h2> Interface </h2> + +<pre> + s6-cat +</pre> + +<p> + s6-cat transfers data from stdin to stdout, until it receives EOF or +gets killed. +</p> + +<h2> Notes </h2> + +<p> + On systems that support it (as of 2.0.0.0, only Linux 2.6.17 or later), +s6-cat performs zero-copy transfer. +</p> + +<h2> Posixness </h2> + +<p> + s6-cat <strong>is not</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cat.html">cat</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-chmod program</title> + <meta name="Description" content="s6-portable-utils: the s6-chmod program" /> + <meta name="Keywords" content="s6-portable-utils command s6-chmod chmod" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-chmod</tt> program </h1> + +<p> + s6-chmod changes the permissions of a file. +</p> + +<h2> Interface </h2> + +<pre> + s6-chmod perms file +</pre> + +<p> + s6-chmod changes <em>file</em>'s permissions to <em>perms</em>, which +must be an absolute octal number such as 0755 for +<tt>rwxr-xr-x</tt> or 2700 for <tt>rwx--S---</tt>. +</p> + +<h2> Posixness </h2> + +<p> + s6-chmod <strong>is not</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chmod.html">chmod</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-chown program</title> + <meta name="Description" content="s6-portable-utils: the s6-chown program" /> + <meta name="Keywords" content="s6-portable-utils command s6-chown chown" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-chown</tt> program </h1> + +<p> + s6-chown changes the owner and/or group of a file. +</p> + +<h2> Interface </h2> + +<pre> + s6-chown [ -U ] [ -u uid ] [ -g gid ] file +</pre> + +<ul> + <li> s6-chown changes <em>file</em>'s owner to (numeric) <em>uid</em> and group +to (numeric) <em>gid</em>. </li> + <li> If <em>uid</em> isn't provided, the owner remains the same; if <em>gid</em> +isn't provided, the group remains the same. </li> + <li> The <tt>-U</tt> option sets <em>uid</em> to the value of the UID +environment variable and <em>gid</em> to the value of the GID environment variable. +This makes s6-chown easily usable with +<a href="http://www.skarnet.org/software/s6/s6-envuidgid.html">s6-envuidgid</a>: +<tt> s6-envuidgid account s6-chown -U file </tt> changes <em>file</em>'s uid and +gid to <em>account</em>'s. </li> +</ul> + +<h2> Posixness </h2> + +<p> + s6-chown <strong>is not</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/chown.html">chown</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-clock program</title> + <meta name="Description" content="s6-portable-utils: the s6-clock program" /> + <meta name="Keywords" content="s6-portable-utils command s6-clock clock" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-clock</tt> program </h1> + +<p> + s6-clock gets or sets the system clock. +</p> + +<h2> Interface </h2> + +<pre> + s6-clock [ <em>label</em> ] +</pre> + +<p> + When called without an argument, s6-clock writes the current system +time, as a +<a href="http://skarnet.org/software/skalibs/libstddjb/tai.html#timestamp">TAI64N +timestamp</a>, to stdout. +</p> + +<p> + When given an argument <em>label</em>, which must be a +<a href="http://skarnet.org/software/skalibs/libstddjb/tai.html#timestamp">TAI64N +timestamp</a>, s6-clock sets the system time to this value. +</p> + +<h2> Notes </h2> + +<p> + 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 +<a href="http://skarnet.org/software/skalibs/">skalibs</a> has been built with +the right settings. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-cut program</title> + <meta name="Description" content="s6-portable-utils: the s6-cut program" /> + <meta name="Keywords" content="s6-portable-utils command s6-cut cut" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-cut</tt> program </h1> + +<p> + s6-cut prints selected portions of the lines of its input. +</p> + +<h2> Interface </h2> + +<pre> + s6-cut [ -b list | -c list | -f list ] [ -n ] [ -s ] [ file ... ] +</pre> + +<p> + s6-cut acts as the generic +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cut.html">cut</a> utility. +</p> + +<h2> Posixness </h2> + +<p> + s6-cut <strong>is</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cut.html">cut</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-dirname program</title> + <meta name="Description" content="s6-portable-utils: the s6-dirname program" /> + <meta name="Keywords" content="s6-portable-utils command s6-dirname dirname" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-dirname</tt> program </h1> + +<p> + s6-dirname prints the dirname of a path. +</p> + +<h2> Interface </h2> + +<pre> + s6-dirname [ -n ] path +</pre> + +<p> + s6-dirname acts as the generic +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/dirname.html">dirname</a> utility. +</p> + +<h2> Extra options </h2> + +<ul> + <li> <tt>-n</tt> : do not print a trailing newline after the output. </li> +</ul> + +<h2> Posixness </h2> + +<p> + s6-dirname <strong>is</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/dirname.html">dirname</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-echo program</title> + <meta name="Description" content="s6-portable-utils: the s6-echo program" /> + <meta name="Keywords" content="s6-portable-utils command s6-echo echo" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-echo</tt> program </h1> + +<p> + s6-echo writes its arguments to stdout. +</p> + +<h2> Interface </h2> + +<pre> + s6-echo [ -n ] [ -s sep ] <em>args...</em> +</pre> + +<p> + s6-echo writes its arguments <em>args</em> to stdout, separated with spaces. +</p> + +<h2> Options </h2> + +<ul> + <li> <tt>-n</tt> : do not output a trailing newline. </li> + <li> <tt>-s</tt> <em>sep</em> : separate arguments with the <em>sep</em> +character instead of a space. </li> +</ul> + +<h2> Posixness </h2> + +<p> + s6-echo <strong>is not</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html">echo</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-env program</title> + <meta name="Description" content="s6-portable-utils: the s6-env program" /> + <meta name="Keywords" content="s6-portable-utils command s6-env env" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-env</tt> program </h1> + +<p> +s6-env prints the current environment or modifies the environment +before running a program. +</p> + +<h2> Interface </h2> + +<pre> + s6-env [ -i ] [ <em>name</em>=<em>value</em>... ] [ <em>prog...</em> ] +</pre> + +<p> + s6-env acts as the generic +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/env.html">env</a> utility. +</p> + +<h2> Posixness </h2> + +<p> + s6-env <strong>is</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/env.html">env</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-expr program</title> + <meta name="Description" content="s6-portable-utils: the s6-expr program" /> + <meta name="Keywords" content="s6-portable-utils command s6-expr expr" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-expr</tt> program </h1> + +<p> + s6-expr evaluates an expression and writes the result to stdout. +</p> + +<h2> Interface </h2> + +<pre> + s6-expr <em>expression...</em> +</pre> + +<p> + s6-expr acts as the generic +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/expr.html">expr</a> utility, +except that the <strong>:</strong> operator (pattern matching) is not supported. +</p> + +<p> + s6-expr accepts an arbitrary number of arguments. +</p> + +<h2> Posixness </h2> + +<p> + s6-expr <strong>is not</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/expr.html">expr</a> +program; however, if you are never using the pattern matching functionality, s6-expr +scrupulously follows the rest of the specification. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-false program</title> + <meta name="Description" content="s6-portable-utils: the s6-false program" /> + <meta name="Keywords" content="s6-portable-utils command s6-false" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-false</tt> program </h1> + +<p> + s6-false returns 1. +</p> + +<h2> Interface </h2> + +<pre> + s6-false +</pre> + +<h2> Posixness </h2> + +<p> + s6-false <strong>is</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/false.html">false</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-format-filter program</title> + <meta name="Description" content="s6-portable-utils: the s6-format-filter program" /> + <meta name="Keywords" content="s6-portable-utils command s6-format filter printf format" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-format-filter</tt> program </h1> + +<p> +s6-format-filter processes lines according to its arguments, and +prints the result. +</p> + +<h2> Interface </h2> + +<pre> + s6-format-filter <em>format</em> [ <em>args...</em> ] +</pre> + +<ul> + <li> <em>format</em> is a format string that can contain the following special sequences: +<tt>%%</tt>, <tt>%s</tt>, and <tt>%0</tt> to <tt>%9</tt>. </li> + <li> For every line it reads on stdin, s6-format-filter prints <em>format</em> on +stdout, replacing <tt>%%</tt> with <tt>%</tt>, <tt>%0</tt> with the command name +(probably <tt>s6-format-filter</tt>), <tt>%1</tt> to <tt>%9</tt> with the first +to the ninth argument in <em>args</em>, and <tt>%s</tt> with the input line. </li> + <li> s6-format-filter exits 0 when it reads EOF. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-grep program</title> + <meta name="Description" content="s6-portable-utils: the s6-grep program" /> + <meta name="Keywords" content="s6-portable-utils command s6-grep grep" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-grep</tt> program </h1> + +<p> + s6-grep matches its input against a pattern. +</p> + +<h2> Interface </h2> + +<pre> + s6-grep [ -E | -F ] [ -i ] [ -c ] [ -n ] [ -q ] [ -v ] <em>pattern</em> +</pre> + +<ul> + <li> s6-grep compiles <em>pattern</em> as an +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03">Basic +Regular Expression</a> </li> + <li> It reads stdin and matches every line against this regexp </li> + <li> If the line matches, it prints it to stdout </li> + <li> It exits on EOF with code 0 if one or more lines matched and 1 +otherwise. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-F</tt> : <em>pattern</em> is not compiled as a BRE, but is +interpreted as a literal string. </li> + <li> <tt>-E</tt> : <em>pattern</em> is not compiled as a BRE, but as an +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_04">Extended +Regular Expression</a> (ERE). </li> + <li> <tt>-i</tt> : ignore case during the match </li> + <li> <tt>-c</tt> : do not write normal output; only write the number of +lines that have matched <em>pattern</em> after EOF is received </li> + <li> <tt>-n</tt> : precede every output line by its number and a colon. +The first input line has number 1. </li> + <li> <tt>-q</tt> : do not write anything to stdout </li> + <li> <tt>-v</tt> : invert the pattern matching (select lines that do not +match <em>pattern</em>). </li> +</ul> + +<h2> Posixness </h2> + +<p> + s6-grep <strong>is not</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html">grep</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-head program</title> + <meta name="Description" content="s6-portable-utils: the s6-head program" /> + <meta name="Keywords" content="s6-portable-utils command s6-head head" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-head</tt> program </h1> + +<p> + s6-head prints the first lines of its input files. +</p> + +<h2> Interface </h2> + +<pre> + s6-head [ -S ] [ -1..9 | -n <em>lines</em> | -c <em>chars</em> ] <em>file...</em> +</pre> + +<p> + s6-head acts as the generic +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/head.html">head</a> utility. +</p> + +<h2> Extra options </h2> + +<ul> + <li> <tt>-S</tt> : safe mode. s6-head stops reading its input files <em>right after</em> +getting all the lines it needs. The rest of the stream can then be handled by other +utilities without any data loss. </li> + <li> <tt>-1..9</tt> : equivalent to <tt>-n 1</tt> .. <tt>-n 9</tt>. </li> + <li> <tt>-c</tt> <em>chars</em> : cuts after <em>chars</em> characters instead +of <em>lines</em> lines. </li> +</ul> + +<h2> Posixness </h2> + +<p> + s6-head <strong>is</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/head.html">head</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-linkname program</title> + <meta name="Description" content="s6-portable-utils: the s6-linkname program" /> + <meta name="Keywords" content="s6-portable-utils command s6-linkname linkname readlink" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-linkname</tt> program </h1> + +<p> + s6-linkname gives the content of a symbolic link or resolves a path. +</p> + +<h2> Interface </h2> + +<pre> + s6-linkname [ -f ] <em>path</em> +</pre> + +<ul> + <li> If <em>path</em> is a symbolic link, s6-linkname prints its +content then exits 0. </li> + <li> Else it prints an error message and exits 111. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-f</tt> : s6-linkname fully resolves <em>path</em> then +prints the result on stdout. <em>path</em> does not have to be a symbolic +link. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-ln program</title> + <meta name="Description" content="s6-portable-utils: the s6-ln program" /> + <meta name="Keywords" content="s6-portable-utils command s6-ln ln link symbolic hard" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-ln</tt> program </h1> + +<p> + s6-ln creates a link to a file. +</p> + +<h2> Interface </h2> + +<pre> + s6-ln [ -s ] [ -f ] [ -L ] [ -P ] <em>old</em> <em>new</em> +</pre> + +<p> + s6-ln acts as the generic +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ln.html">ln</a> utility. +</p> + +<h2> Posixness </h2> + +<p> + s6-ln <strong>is</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ln.html">ln</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-ls program</title> + <meta name="Description" content="s6-portable-utils: the s6-ls program" /> + <meta name="Keywords" content="s6-portable-utils command s6-ls ls directory list" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-ls</tt> program </h1> + +<p> + s6-ls lists the contents of a directory. +</p> + +<h2> Interface </h2> + +<pre> + s6-ls [ -0 ] [ -a | -A ] [ -x <em>exclude</em> ] <em>dir</em> +</pre> + +<p> + s6-ls lists the contents of <em>dir</em>, one file per line. It +omits files starting with a dot. +</p> + +<h2> Options </h2> + +<ul> + <li> <tt>-0</tt> : separate file names with a null character +instead of a newline. </li> + <li> <tt>-a</tt> : do not omit files starting with a dot. Do +not list <tt>.</tt> or <tt>..</tt> though. </li> + <li> <tt>-A</tt> : do not omit files starting with a dot, even +<tt>.</tt> and <tt>..</tt> </li> + <li> <tt>-x</tt> <em>exclude</em> : if a file name is +<em>exclude</em>, do not print it. </li> +</ul> + +<h2> Posixness </h2> + +<p> + s6-ls <strong>is not</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html">ls</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-maximumtime program</title> + <meta name="Description" content="s6-portable-utils: the s6-maximumtime program" /> + <meta name="Keywords" content="s6-portable-utils command s6-maximumtime maximumtime timelimit time limit" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-maximumtime</tt> program </h1> + +<p> + s6-maximumtime executes a program with a time limit. +</p> + +<h2> Interface </h2> + +<pre> + s6-maximumtime [ -0 | -a | -b | -i | -k | -q | -t | -x | -1 | -2 ] <em>milli</em> <em>prog...</em> +</pre> + +<ul> + <li> s6-maximumtime forks and execs <em>prog...</em> as a child. </li> + <li> If <em>milli</em> milliseconds elapse before <em>prog</em> exits, +s6-maximumtime sends it a signal and exits 99 with a message. </li> + <li> Else s6-maximumtime exits with the same exit code as <em>prog</em>. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-0</tt> : on timeout, do not send any signal, just exit </li> + <li> <tt>-a</tt> : on timeout, send a SIGALRM </li> + <li> <tt>-b</tt> : on timeout, send a SIGABRT </li> + <li> <tt>-i</tt> : on timeout, send a SIGINT </li> + <li> <tt>-k</tt> : on timeout, send a SIGKILL </li> + <li> <tt>-q</tt> : on timeout, send a SIGQUIT </li> + <li> <tt>-t</tt> : on timeout, send a SIGTERM - this is the default </li> + <li> <tt>-x</tt> : on timeout, send a SIGXCPU </li> + <li> <tt>-1</tt> : on timeout, send a SIGUSR1 </li> + <li> <tt>-2</tt> : on timeout, send a SIGUSR2 </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-mkdir program</title> + <meta name="Description" content="s6-portable-utils: the s6-mkdir program" /> + <meta name="Keywords" content="s6-portable-utils command s6-mkdir mkdir" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-mkdir</tt> program </h1> + +<p> + s6-mkdir creates directories. +</p> + +<h2> Interface </h2> + +<pre> + s6-mkdir [ -p ] [ -v ] [ -m <em>mode</em> ] [ <em>dir...</em> ] +</pre> + +<p> + s6-mkdir acts as the generic +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/mkdir.html">mkdir</a> utility. +</p> + +<h2> Extra options </h2> + +<ul> + <li> <tt>-v</tt> : write what it does to stderr. </li> +</ul> + +<h2> Posixness </h2> + +<p> + s6-mkdir <strong>is</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/mkdir.html">mkdir</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-mkfifo program</title> + <meta name="Description" content="s6-portable-utils: the s6-mkfifo program" /> + <meta name="Keywords" content="s6-portable-utils command s6-mkfifo mkfifo" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-mkfifo</tt> program </h1> + +<p> + s6-mkfifo creates FIFOs, a.k.a. named pipes. +</p> + +<h2> Interface </h2> + +<pre> + s6-mkfifo [ -m mode ] [ <em>fifo...</em> ] +</pre> + +<p> + s6-mkfifo acts as the generic +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/mkfifo.html">mkfifo</a> utility. +</p> + +<h2> Posixness </h2> + +<p> + s6-mkfifo <strong>is</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/mkfifo.html">mkfifo</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-nice program</title> + <meta name="Description" content="s6-portable-utils: the s6-nice program" /> + <meta name="Keywords" content="s6-portable-utils command s6-nice nice" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">www.skarnet.org</a> +</p> + +<h1> The <tt>s6-nice</tt> program </h1> + +<p> + s6-nice executes into a program with an altered nice value. +</p> + +<h2> Interface </h2> + +<pre> + s6-nice [ -I | -i ] [ -n <em>value</em> ] [ <em>prog...</em> ] +</pre> + +<p> + s6-nice acts as the generic +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/nice.html">nice</a> utility. +</p> + +<h2> Extra options </h2> + +<ul> + <li> <tt>-I</tt> : loose. If the nice value cannot be set to <em>value</em>, +print a warning message and exec into <em>prog...</em> anyway. This is the default. </li> + <li> <tt>-i</tt> : strict. If the nice value cannot be set to <em>value</em>, +exit 111 with an error message. +</ul> + +<h2> Posixness </h2> + +<p> + s6-nice <strong>is</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/nice.html">nice</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-nuke program</title> + <meta name="Description" content="s6-portable-utils: the s6-nuke program" /> + <meta name="Keywords" content="s6-portable-utils command s6-nuke signal kill" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-nuke</tt> program </h1> + +<p> + s6-nuke sends signals to every process it is allowed to send. +</p> + +<h2> Interface </h2> + +<pre> + s6-nuke [ -h | -t | -k ] +</pre> + +<ul> + <li> 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. </li> + <li> 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. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-h</tt> : send a SIGHUP </li> + <li> <tt>-t</tt> : send a SIGTERM then a SIGCONT </li> + <li> <tt>-k</tt> : send a SIGKILL </li> +</ul> + +<h2> Usage notes </h2> + +<p> + s6-nuke can be used during the shutdown procedure of a system, which is +described +<a href="http://skarnet.org/software/s6/s6-svscan-1.html#stage3">here</a>. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-pause program</title> + <meta name="Description" content="s6-portable-utils: the s6-pause program" /> + <meta name="Keywords" content="s6-portable-utils command s6-pause pause" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-pause</tt> program </h1> + +<p> + s6-pause blocks until it is killed. +</p> + +<h2> Interface </h2> + +<pre> + s6-pause +</pre> + +<h2> Usage notes </h2> + +<p> + 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. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-printenv program</title> + <meta name="Description" content="s6-portable-utils: the s6-printenv program" /> + <meta name="Keywords" content="s6-portable-utils command s6-printenv environment variables" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-printenv</tt> program </h1> + +<p> + s6-printenv prints its environment variables. +</p> + +<h2> Interface </h2> + +<pre> + s6-printenv [ -n ] [ -0 | -d <em>delim</em> ] +</pre> + +<p> + s6-printenv prints its environment on stdout, like +<a href="s6-env.html">s6-env</a>. +</p> + +<h2> Options </h2> + +<ul> + <li> <tt>-0</tt> : separate file names with a null character +instead of a newline. </li> + <li> <tt>-d</tt> <em>delim</em> : separate file names with the +first character of <em>delim</em> instead of a newline </li> + <li> <tt>-n</tt> : omit the last delimiter character </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-quote-filter program</title> + <meta name="Description" content="s6-portable-utils: the s6-quote-filter program" /> + <meta name="Keywords" content="s6-portable-utils command s6-quote-filter quote" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-quote-filter</tt> program </h1> + +<p> + s6-quote-filter acts as a filter, quoting lines it reads on stdin +and writing the quoted lines to stdout. +</p> + +<h2> Interface </h2> + +<pre> + s6-quote-filter [ -u ] [ -d <em>delim</em> ] +</pre> + +<ul> + <li> s6-quote reads lines on stdin; it quotes every line, putting it inside double quotes +and escaping all dubious characters </li> + <li> It writes the quoted strings to stdout </li> + <li> It exits 0 on EOF </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-u</tt> : do not put read lines inside double quotes, only escape +characters if needed </li> + <li> <tt>-d</tt> <em>delim</em> : use the first character of <em>delim</em> +as a quote character, instead of double quotes </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> Quoted strings are guaranteed to be pure printable ASCII, without control characters. </li> + <li> Quoted strings can be unquoted via the <a href="s6-unquote.html">s6-unquote</a> or +<a href="s6-unquote-filter.html">s6-unquote-filter</a> programs. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-quote program</title> + <meta name="Description" content="s6-portable-utils: the s6-quote program" /> + <meta name="Keywords" content="s6-portable-utils command s6-quote quote" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-quote</tt> program </h1> + +<p> + s6-quote quotes a string and writes it to stdout. +</p> + +<h2> Interface </h2> + +<pre> + s6-quote [ -n ] [ -u ] [ -d <em>delim</em> ] <em>string</em> +</pre> + +<ul> + <li> s6-quote quotes <em>string</em>, putting it inside double quotes +and escaping all dubious characters </li> + <li> It writes the quoted string to stdout and exits 0 </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-n</tt> : do not print a trailing newline </li> + <li> <tt>-u</tt> : do not put <em>string</em> inside double quotes, only escape +characters if needed </li> + <li> <tt>-d</tt> <em>delim</em> : use the first character of <em>delim</em> +as a quote character, instead of double quotes </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> Quoted strings are guaranteed to be pure printable ASCII, without control characters. </li> + <li> Quoted strings can be unquoted via the <a href="s6-unquote.html">s6-unquote</a> or +<a href="s6-unquote-filter.html">s6-unquote-filter</a> programs. </li> + <li> Quoted strings are suitable for interpretation by +<a href="http://skarnet.org/software/execline/execlineb.html">execlineb</a>. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-rename program</title> + <meta name="Description" content="s6-portable-utils: the s6-rename program" /> + <meta name="Keywords" content="s6-portable-utils command s6-rename rename atomic" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-rename</tt> program </h1> + +<p> + s6-rename atomically renames a file. +</p> + +<h2> Interface </h2> + +<pre> + s6-rename <em>old</em> <em>new</em> +</pre> + +<p> + s6-rename atomically renames <em>old</em> to <em>new</em>. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-rmrf program</title> + <meta name="Description" content="s6-portable-utils: the s6-rmrf program" /> + <meta name="Keywords" content="s6-portable-utils command s6-rmrf rm remove delete" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-rmrf</tt> program </h1> + +<p> + s6-rmrf removes a file or directory tree entirely. +</p> + +<h2> Interface </h2> + +<pre> + s6-rmrf <em>subtree</em> +</pre> + +<p> + s6-rmrf removes the <em>subtree</em> file hierarchy. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-sleep program</title> + <meta name="Description" content="s6-portable-utils: the s6-sleep program" /> + <meta name="Keywords" content="s6-portable-utils command s6-sleep sleep" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-sleep</tt> program </h1> + +<p> + s6-sleep sleeps for a given time. +</p> + +<h2> Interface </h2> + +<pre> + s6-sleep [ -m ] <em>time</em> +</pre> + +<p> + s6-sleep acts as the generic +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sleep.html">sleep</a> utility. +It ignores non-lethal signals. +</p> + +<h2> Extra options </h2> + +<ul> + <li> <tt>-m</tt> : Interpret <em>time</em> as milliseconds instead of seconds. </li> +</ul> + +<h2> Posixness </h2> + +<p> + s6-sleep <strong>is</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sleep.html">sleep</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-sort program</title> + <meta name="Description" content="s6-portable-utils: the s6-sort program" /> + <meta name="Keywords" content="s6-portable-utils command s6-sort sort" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-sort</tt> program </h1> + +<p> + s6-sort sorts its input. +</p> + +<h2> Interface </h2> + +<pre> + s6-sort [ -b ] [ -c ] [ -f ] [ -r ] [ -u ] [ -0 ] +</pre> + +<ul> + <li> s6-sort reads its stdin until EOF </li> + <li> It sorts all the lines it read alphanumerically </li> + <li> It prints the sorted lines to stdout and exits 0 </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-b</tt> : ignore leading spaces and tabs at the beginning of each +line when sorting </li> + <li> <tt>-c</tt> : suppresses normal output, just returns 0 if the output +would have been the same as the input and 1 otherwise </li> + <li> <tt>-f</tt> : ignore case when sorting </li> + <li> <tt>-r</tt> : reverse sort </li> + <li> <tt>-u</tt> : suppresses duplicate lines </li> + <li> <tt>-0</tt> : input and output lines are separated by null characters +instead of newlines </li> +</ul> + +<h2> Posixness </h2> + +<p> + s6-sort <strong>is not</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sort.html">sort</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-sync program</title> + <meta name="Description" content="s6-portable-utils: the s6-sync program" /> + <meta name="Keywords" content="s6-portable-utils command s6-sync sync filesystem" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-sync</tt> program </h1> + +<p> + s6-sync flushes all the dirty system buffers, and blocks until they're +clean. +</p> + +<h2> Interface </h2> + +<pre> + s6-sync +</pre> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-tail program</title> + <meta name="Description" content="s6-portable-utils: the s6-tail program" /> + <meta name="Keywords" content="s6-portable-utils command s6-tail tail" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-tail</tt> program </h1> + +<p> + s6-tail prints a file or its stdin after a certain number of bytes or lines. +</p> + +<h2> Interface </h2> + +<pre> + s6-tail [ -n <em>lines</em> | -c <em>chars</em> ] [ <em>file</em> ] +</pre> + +<p> + s6-tail acts as the generic +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/tail.html">tail</a> utility, +except that the <strong>-f</strong> option is not supported. +</p> + +<h2> Posixness </h2> + +<p> + s6-tail <strong>is not</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/tail.html">tail</a> +program; however, if you are never using the <tt>-f</tt> functionality, s6-tail +scrupulously follows the rest of the specification. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-test program</title> + <meta name="Description" content="s6-portable-utils: the s6-test program" /> + <meta name="Keywords" content="s6-portable-utils command s6-test test" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-test</tt> program </h1> + +<p> + s6-test evaluates an expression and indicates the result via its +exit status. +</p> + +<h2> Interface </h2> + +<pre> + s6-test <em>expression...</em> +</pre> + +<p> + s6-test acts as the generic +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html">test</a> 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. +</p> + +<p> + s6-test accepts an arbitrary number of arguments. +</p> + +<h2> Posixness </h2> + +<p> + s6-test <strong>is not</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html">test</a> +program; however, if your arguments never start with a backslash, it exhibits the +exact same behaviour. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-touch program</title> + <meta name="Description" content="s6-portable-utils: the s6-touch program" /> + <meta name="Keywords" content="s6-portable-utils command s6-touch touch" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-touch</tt> program </h1> + +<p> + s6-touch changes the modification and access times of a file, creating it if it does +not exist. +</p> + +<h2> Interface </h2> + +<pre> + s6-touch <em>file...</em> +</pre> + +<p> + s6-touch touches every <em>file</em> in the list by opening them for appending +then closing them. +</p> + +<h2> Posixness </h2> + +<p> + s6-touch <strong>is not</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/touch.html">touch</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-true program</title> + <meta name="Description" content="s6-portable-utils: the s6-true program" /> + <meta name="Keywords" content="s6-portable-utils command s6-true" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-true</tt> program </h1> + +<p> + s6-true returns 0. +</p> + +<h2> Interface </h2> + +<pre> + s6-true +</pre> + +<h2> Posixness </h2> + +<p> + s6-true <strong>is</strong> suitable as a Single Unix +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/false.html">true</a> +program. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-uniquename program</title> + <meta name="Description" content="s6-portable-utils: the s6-uniquename program" /> + <meta name="Keywords" content="s6-portable-utils command s6-uniquename uniquename random" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-uniquename</tt> program </h1> + +<p> + s6-uniquename creates a guaranteed unique file name and prints it to stdout. +</p> + +<h2> Interface </h2> + +<pre> + s6-uniquename [ -n <em>randomlen</em> ] <em>prefix</em> +</pre> + +<ul> + <li> s6-uniquename creates a unique filename starting with <em>prefix</em> +involving a TAI64N timestamp, the machine's FQDN and the process' PID. </li> + <li> It prints it to stdout and exits 0. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-n</tt> <em>randomlen</em> : for added security, also +add a random readable string of <em>randomlen</em> characters to the +created pathname. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-unquote-filter program</title> + <meta name="Description" content="s6-portable-utils: the s6-unquote-filter program" /> + <meta name="Keywords" content="s6-portable-utils command s6-unquote-filter unquote filter" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-unquote-filter</tt> program </h1> + +<p> + s6-unquote acts as a filter, reading quoted strings on stdin, +unquoting them and writing the results to stdout. +</p> + +<h2> Interface </h2> + +<pre> + s6-unquote-filter [ -q | -Q | -v | -w ] [ -d <em>delim</em> ] +</pre> + +<ul> + <li> s6-unquote-filter reads lines on stdin. It exits 0 on EOF. </li> + <li> It expects read lines to follow the +syntax of <a href="s6-quote.html">s6-quote</a>'s output strings </li> + <li> 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. </li> + <li> If it is successful at unquoting, it prints the resulting +lines to stdout. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-d</tt> <em>delim</em> : 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 <em>delim</em> +is the empty string, s6-unquote-filter interprets <em>string</em> as +non-delimited, only escaped (i.e. for instance the result of some +<tt>s6-quote-filter -u</tt> operation). </li> + <li> <tt>-q</tt> : loose/quiet mode. s6-unquote-filter will +silently accommodate errors. </li> + <li> <tt>-Q</tt> : normal mode. This is the default. s6-unquote-filter +will warn on errors. </li> + <li> <tt>-v</tt> : strict/verbose mode. s6-unquote-filter will +warn loudly on errors, with many details. </li> + <li> <tt>-w</tt> : very strict mode. s6-unquote-filter will complain +and die on the first unquoting error it encounters. </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> Quoted strings can be produced via the <a href="s6-quote.html">s6-quote</a> or +<a href="s6-quote-filter.html">s6-quote-filter</a> programs. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-unquote program</title> + <meta name="Description" content="s6-portable-utils: the s6-unquote program" /> + <meta name="Keywords" content="s6-portable-utils command s6-unquote quote" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-unquote</tt> program </h1> + +<p> + s6-unquote unquotes a quoted string and writes it to stdout. +</p> + +<h2> Interface </h2> + +<pre> + s6-unquote [ -n ] [ -d <em>delim</em> ] <em>string</em> +</pre> + +<ul> + <li> s6-unquote unquotes <em>string</em>, which must follow the +syntax of <a href="s6-quote.html">s6-quote</a>'s output strings </li> + <li> It prints various warning or error messages to stderr if it +cannot unquote <em>string</em> properly </li> + <li> If successful, it prints the result to stdout and exits 0 </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-n</tt> : do not print a trailing newline. </li> + <li> <tt>-d</tt> <em>delim</em> : 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 <em>delim</em> +is the empty string, s6-unquote interprets <em>string</em> as +non-delimited, only escaped (i.e. the result of some +<tt>s6-quote -u</tt> operation). </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> Quoted strings can be produced via the <a href="s6-quote.html">s6-quote</a> or +<a href="s6-quote-filter.html">s6-quote-filter</a> programs. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: the s6-update-symlinks program</title> + <meta name="Description" content="s6-portable-utils: the s6-update-symlinks program" /> + <meta name="Keywords" content="s6-portable-utils command s6-update-symlinks update-symlinks symlinks" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>s6-update-symlinks</tt> program </h1> + +<p> + <tt>s6-update-symlinks</tt> 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. +</p> + +<p> +<tt>s6-update-symlinks</tt> is useful when one wants to combine +a logical package system, like Dan Bernstein's +<a href="http://cr.yp.to/slashpackage.html"><tt>/package</tt></a> and +<a href="http://cr.yp.to/slashcommand.html"><tt>/command</tt></a>, with +physical filesystem constraints, like <tt>/</tt>, <tt>/usr</tt> and +<tt>/usr/local</tt> on separate filesystems. +</p> + +<h2> Interface </h2> + +<pre> + s6-update-symlinks <em>d</em> <em>src1</em> <em>src2</em> ... +</pre> + +<ul> + <li> <em>d</em> is the destination directory. It will be created if it doesn't +exist. </li> + <li> <em>src1</em>, <em>src2</em>, ... are the directory containing the files +to be linked.</li> + <li> <em>d</em> and <em>srcn</em> <strong>must</strong> be +<strong>absolute</strong> paths, else s6-update-symlinks refuses to run. Using +relative paths doesn't make sense here, anyway. </li> + <li> If <em>src2</em> is empty, then <em>d</em> becomes a link to <em>src1</em>. </li> + <li> If <em>src1</em> is empty or entirely overridden by <em>src2</em>, then +<em>d</em> becomes a link to <em>src2</em>.</li> + <li> If <em>src1/file</em> exists but not <em>src2/file</em>, then <em>d</em> +becomes a real directory and <em>d/file</em> a link to <em>src1/file</em>. +Then if <em>src2/file2</em> exists, <em>d/file2</em> links to it. </li> + <li> And so on with other <em>src</em> directories, and subdirs. </li> + <li> If <tt>s6-update-symlinks</tt> 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. </li> +</ul> + +<h2> Examples </h2> + +<ul> + <li> +<tt>s6-update-symlinks /command /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin</tt> +<br> makes all files under <tt>/bin</tt>, ..., <tt>/usr/local/sbin</tt> +available under <tt>/command</tt>. 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". + </li> + <li> +<tt>s6-update-symlinks /package /initrd/package /slash/package /usr/package /usr/local/package</tt> +<br /> builds a <tt>/package</tt> hierarchy with what it finds in the listed +directories. This allows oddities like, for instance, having the daemontools +sources in <tt>/usr/package/admin/daemontools/src</tt>, and the daemontools +binaries in <tt>/initrd/package/admin/daemontools/bin</tt>, but accessing +both through <tt>/package/admin/daemontools/</tt>. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-portable-utils: how to upgrade</title> + <meta name="Description" content="s6-portable-utils: how to upgrade" /> + <meta name="Keywords" content="s6-portable-utils installation upgrade" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-portable-utils</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> How to upgrade s6-portable-utils </h1> + +<h2> to 2.0.0.0 </h2> + +<ul> + <li> The build system has completely changed. It is now a standard +<tt>./configure && make && sudo make install</tt> +build system. See the enclosed INSTALL file for details. </li> + <li> slashpackage is not activated by default. </li> + <li> shared libraries are not used by default. </li> + <li> skalibs dependency bumped to 2.0.0.0 </li> +</ul> + +</body> +</html> 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 --- /dev/null +++ b/src/skaembutils/deps-exe/s6-false 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 --- /dev/null +++ b/src/skaembutils/deps-exe/s6-pause 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 --- /dev/null +++ b/src/skaembutils/deps-exe/s6-sync 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 --- /dev/null +++ b/src/skaembutils/deps-exe/s6-true 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 <skalibs/sgetopt.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/bytestr.h> +#include <skalibs/strerr2.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> + +#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 <errno.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> + +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 <sys/types.h> +#include <sys/stat.h> +#include <skalibs/uint.h> +#include <skalibs/strerr2.h> + +#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 <sys/types.h> +#include <unistd.h> +#include <skalibs/sgetopt.h> +#include <skalibs/uint.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> + +#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 <skalibs/allreadwrite.h> +#include <skalibs/strerr2.h> +#include <skalibs/tai.h> + +#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 <errno.h> +#include <stdlib.h> +#include <skalibs/sgetopt.h> +#include <skalibs/bytestr.h> +#include <skalibs/uint.h> +#include <skalibs/diuint.h> +#include <skalibs/buffer.h> +#include <skalibs/strerr2.h> +#include <skalibs/stralloc.h> +#include <skalibs/genalloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/skamisc.h> + +#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 <skalibs/sgetopt.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/bytestr.h> +#include <skalibs/strerr2.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> + +#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 <skalibs/sgetopt.h> +#include <skalibs/buffer.h> +#include <skalibs/strerr2.h> + +#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 <errno.h> +#include <skalibs/sgetopt.h> +#include <skalibs/bytestr.h> +#include <skalibs/strerr2.h> +#include <skalibs/env.h> +#include <skalibs/djbunix.h> +#include <s6-portable-utils/config.h> + +#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 <unistd.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/bytestr.h> +#include <skalibs/uint.h> +#include <skalibs/fmtscan.h> +#include <skalibs/strerr2.h> + +#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 <errno.h> +#include <skalibs/strerr2.h> +#include <skalibs/buffer.h> +#include <skalibs/stralloc.h> +#include <skalibs/skamisc.h> + +#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 <errno.h> +#include <regex.h> +#include <string.h> +#include <skalibs/bytestr.h> +#include <skalibs/sgetopt.h> +#include <skalibs/buffer.h> +#include <skalibs/uint.h> +#include <skalibs/strerr2.h> +#include <skalibs/stralloc.h> +#include <skalibs/skamisc.h> + +#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 <errno.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/sgetopt.h> +#include <skalibs/bytestr.h> +#include <skalibs/uint.h> +#include <skalibs/buffer.h> +#include <skalibs/siovec.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> + +#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 <skalibs/bytestr.h> +#include <skalibs/buffer.h> +#include <skalibs/sgetopt.h> +#include <skalibs/strerr2.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> + +#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 <skalibs/sysdeps.h> + +#ifdef SKALIBS_HASLINKAT +#include <skalibs/nonposix.h> +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <stdio.h> +#include <skalibs/sgetopt.h> +#include <skalibs/bytestr.h> +#include <skalibs/strerr2.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/random.h> +#include <skalibs/skamisc.h> + +#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 <skalibs/sgetopt.h> +#include <skalibs/bytestr.h> +#include <skalibs/direntry.h> +#include <skalibs/buffer.h> +#include <skalibs/strerr2.h> + +#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 <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <errno.h> +#include <unistd.h> +#include <skalibs/sgetopt.h> +#include <skalibs/uint.h> +#include <skalibs/error.h> +#include <skalibs/sig.h> +#include <skalibs/tai.h> +#include <skalibs/iopause.h> +#include <skalibs/selfpipe.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> + +#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 <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> +#include <skalibs/sgetopt.h> +#include <skalibs/bytestr.h> +#include <skalibs/uint.h> +#include <skalibs/buffer.h> +#include <skalibs/strerr2.h> + +#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 <sys/types.h> +#include <sys/stat.h> +#include <skalibs/sgetopt.h> +#include <skalibs/uint.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> + +#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 <unistd.h> +#include <errno.h> +#include <skalibs/sgetopt.h> +#include <skalibs/uint.h> +#include <skalibs/fmtscan.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> + +#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 <sys/types.h> +#include <signal.h> +#include <errno.h> +#include <skalibs/sgetopt.h> +#include <skalibs/strerr2.h> +#include <skalibs/sig.h> + +#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 <unistd.h> + +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 <skalibs/bytestr.h> +#include <skalibs/sgetopt.h> +#include <skalibs/buffer.h> +#include <skalibs/strerr2.h> +#include <skalibs/netstring.h> + +#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 <errno.h> +#include <skalibs/sgetopt.h> +#include <skalibs/strerr2.h> +#include <skalibs/buffer.h> +#include <skalibs/stralloc.h> +#include <skalibs/skamisc.h> + +#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 <skalibs/sgetopt.h> +#include <skalibs/strerr2.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/stralloc.h> +#include <skalibs/skamisc.h> + +#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 <unistd.h> +#include <stdio.h> +#include <skalibs/strerr2.h> + +#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 <skalibs/strerr2.h> +#include <skalibs/djbunix.h> + +#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 <unistd.h> +#include <skalibs/sgetopt.h> +#include <skalibs/strerr2.h> +#include <skalibs/uint.h> +#include <skalibs/tai.h> +#include <skalibs/djbunix.h> +#include <skalibs/iopause.h> + +#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 <stdlib.h> +#include <errno.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/sgetopt.h> +#include <skalibs/bytestr.h> +#include <skalibs/buffer.h> +#include <skalibs/strerr2.h> +#include <skalibs/stralloc.h> +#include <skalibs/genalloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/skamisc.h> + +#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 <unistd.h> + +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 <errno.h> +#include <skalibs/sgetopt.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/bytestr.h> +#include <skalibs/uint.h> +#include <skalibs/buffer.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> +#include <skalibs/skamisc.h> +#include <skalibs/siovec.h> + +#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 <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <skalibs/uint.h> +#include <skalibs/bytestr.h> +#include <skalibs/fmtscan.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> + +#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 <skalibs/strerr2.h> +#include <skalibs/djbunix.h> + +#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 <skalibs/allreadwrite.h> +#include <skalibs/sgetopt.h> +#include <skalibs/uint.h> +#include <skalibs/strerr2.h> +#include <skalibs/stralloc.h> +#include <skalibs/skamisc.h> +#include <skalibs/random.h> + +#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 <errno.h> +#include <skalibs/sgetopt.h> +#include <skalibs/bytestr.h> +#include <skalibs/uint.h> +#include <skalibs/strerr2.h> +#include <skalibs/buffer.h> +#include <skalibs/stralloc.h> +#include <skalibs/skamisc.h> + +#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 <skalibs/sgetopt.h> +#include <skalibs/bytestr.h> +#include <skalibs/uint.h> +#include <skalibs/strerr2.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/skamisc.h> + +#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 <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> +#include <stdio.h> +#include <skalibs/bytestr.h> +#include <skalibs/direntry.h> +#include <skalibs/strerr2.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/random.h> + +#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 |