From 5abe508bfef8372472d66adf69cf08e07125820c Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Tue, 21 Nov 2017 16:12:18 +0000 Subject: Initial commit --- .gitignore | 7 + AUTHORS | 3 + COPYING | 13 + INSTALL | 175 +++++++++++++ Makefile | 151 +++++++++++ README | 27 ++ README.macosx | 4 + README.solaris | 12 + configure | 461 +++++++++++++++++++++++++++++++++ doc/index.html | 134 ++++++++++ doc/skabus-dyntee-client.html | 57 ++++ doc/skabus-dyntee.html | 123 +++++++++ doc/skabus-dynteed.html | 154 +++++++++++ doc/upgrade.html | 28 ++ package/deps-build | 3 + package/deps.mak | 14 + package/info | 4 + package/modes | 3 + package/targets.mak | 8 + patch-for-solaris | 21 ++ src/include/skabus/skabus.h | 15 ++ src/misc/deps-exe/skabus-dyntee | 1 + src/misc/deps-exe/skabus-dyntee-client | 1 + src/misc/deps-exe/skabus-dynteed | 2 + src/misc/skabus-dyntee-client.c | 39 +++ src/misc/skabus-dyntee.c | 149 +++++++++++ src/misc/skabus-dynteed.c | 305 ++++++++++++++++++++++ tools/gen-deps.sh | 93 +++++++ tools/install.sh | 64 +++++ 29 files changed, 2071 insertions(+) create mode 100644 .gitignore create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 INSTALL create mode 100644 Makefile create mode 100644 README create mode 100644 README.macosx create mode 100644 README.solaris create mode 100755 configure create mode 100644 doc/index.html create mode 100644 doc/skabus-dyntee-client.html create mode 100644 doc/skabus-dyntee.html create mode 100644 doc/skabus-dynteed.html create mode 100644 doc/upgrade.html create mode 100644 package/deps-build create mode 100644 package/deps.mak create mode 100644 package/info create mode 100644 package/modes create mode 100644 package/targets.mak create mode 100755 patch-for-solaris create mode 100644 src/include/skabus/skabus.h create mode 100644 src/misc/deps-exe/skabus-dyntee create mode 100644 src/misc/deps-exe/skabus-dyntee-client create mode 100644 src/misc/deps-exe/skabus-dynteed create mode 100644 src/misc/skabus-dyntee-client.c create mode 100644 src/misc/skabus-dyntee.c create mode 100644 src/misc/skabus-dynteed.c create mode 100755 tools/gen-deps.sh create mode 100755 tools/install.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b01e94c --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.o +*.lo +/*.a.xyzzy +/*.so.xyzzy +/config.mak +/src/include/skabus/config.h +/skabus-* diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..2614d6f --- /dev/null +++ b/AUTHORS @@ -0,0 +1,3 @@ +Main author: + Laurent Bercot + diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..9e2739b --- /dev/null +++ b/COPYING @@ -0,0 +1,13 @@ +Copyright (c) 2017 Laurent Bercot + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..0fbb435 --- /dev/null +++ b/INSTALL @@ -0,0 +1,175 @@ +Build Instructions +------------------ + +* Requirements + ------------ + + - A POSIX-compliant C development environment + - GNU make version 3.81 or later + - skalibs version 2.6.1.0 or later: http://skarnet.org/software/skalibs/ + - execline version 2.3.0.3 or later: http://skarnet.org/software/execline/ + - s6 version 2.6.1.1 or later: http://skarnet.org/software/s6/ + + 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 and the static libraries in +/usr/lib/skabus. + + Please note that static libraries in /usr/lib/skabus *will not* +be found by a default linker invocation: you need -L/usr/lib/skabus. +Other skarnet.org software automatically handles that case if the +default configuration is used, but if you change the configuration, +remember to use the appropriate --with-lib configure option. + + You can strip the binaries and libraries 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, a few standard environment variables are recognized. + + If the CC environment variable is set, its value will override compiler +detection by configure. The --host=HOST option will still add a HOST- +prefix to the value of CC. + + The values of CFLAGS, CPPFLAGS and LDFLAGS will be appended to flags +auto-detected by configure. To entirely override the flags set by +configure instead, use make variables. + + +* Make variables + -------------- + + You can invoke make with a few variables for more configuration. + + CC, CFLAGS, CPPFLAGS, LDFLAGS, LDLIBS, AR, RANLIB, STRIP, INSTALL and +CROSS_COMPILE can all be overridden on the make command line. This is +an even bigger hammer than running ./configure with environment +variables, so it is advised to only do this when it is the only way of +obtaining the behaviour you want. + + DESTDIR can be given on the "make install" command line in order to +install to a staging directory. + + +* Shared libraries + ---------------- + + Software from skarnet.org is small enough that shared libraries are +generally not worth using. Static linking is simpler and incurs less +runtime overhead and less points of failure: so by default, shared +libraries are not built and binaries are linked against the static +versions of the skarnet.org libraries. Nevertheless, you can: + * build shared libraries: --enable-shared + * link binaries against shared libraries: --disable-allstatic + + +* 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 --host=HOST option to configure, HOST being the triplet +for your target. + * Make sure your cross-toolchain binaries (i.e. prefixed with HOST-) +are accessible via your PATH environment variable. + * 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. +If $package_home is the home of the package, defined as +DIR/package/$category/$package-$version with the variables +read from the package/info file, then: + + --dynlibdir is set to $package_home/library.so + --bindir is set to $package_home/command + --sbindir is also set to $package_home/command (slashpackage +differentiates root-only binaries by their Unix rights, not their +location in the filesystem) + --libexecdir is also set to $package_home/command (slashpackage +does not need a specific directory for internal binaries) + --libdir is set to $package_home/library + --includedir is set to $package_home/include + + --prefix is pretty much ignored when you use --enable-slashpackage. +You should probably not use both --enable-slashpackage and --prefix. + + 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. + + +* Absolute pathnames + ------------------ + + You may want to use fixed absolute pathnames even if you're not +following the slashpackage convention: for instance, the Nix packaging +system prefers calling binaries with immutable paths rather than rely on +PATH resolution. If you are in that case, use the --enable-absolute-paths +option to configure. This will ensure that programs calling binaries from +this package will call them with their full installation path (in bindir) +without relying on a PATH search. + + +* 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..610dbb6 --- /dev/null +++ b/Makefile @@ -0,0 +1,151 @@ +# +# This Makefile requires GNU make. +# +# Do not make changes here. +# Use the included .mak files. +# + +it: all + +make_need := 3.81 +ifeq "" "$(strip $(filter $(make_need), $(firstword $(sort $(make_need) $(MAKE_VERSION)))))" +fail := $(error Your make ($(MAKE_VERSION)) is too old. You need $(make_need) or newer) +endif + +CC = $(error Please use ./configure first) + +STATIC_LIBS := +SHARED_LIBS := +INTERNAL_LIBS := +EXTRA_TARGETS := +LIB_DEFS := + +define library_definition +LIB$(firstword $(subst =, ,$(1))) := lib$(lastword $(subst =, ,$(1))).$(if $(DO_ALLSTATIC),a,so).xyzzy +ifdef DO_SHARED +SHARED_LIBS += lib$(lastword $(subst =, ,$(1))).so.xyzzy +endif +ifdef DO_STATIC +STATIC_LIBS += lib$(lastword $(subst =, ,$(1))).a.xyzzy +endif +endef + +-include config.mak +include package/targets.mak + +$(foreach var,$(LIB_DEFS),$(eval $(call library_definition,$(var)))) + +include package/deps.mak + +version_m := $(basename $(version)) +version_M := $(basename $(version_m)) +version_l := $(basename $(version_M)) +CPPFLAGS_ALL := $(CPPFLAGS_AUTO) $(CPPFLAGS) +CFLAGS_ALL := $(CFLAGS_AUTO) $(CFLAGS) +ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),) +CFLAGS_SHARED := -fPIC +else +CFLAGS_SHARED := +endif +LDFLAGS_ALL := $(LDFLAGS_AUTO) $(LDFLAGS) +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) +ALL_LIBS := $(SHARED_LIBS) $(STATIC_LIBS) $(INTERNAL_LIBS) +ALL_INCLUDES := $(wildcard src/include/$(package)/*.h) + +all: $(ALL_LIBS) $(ALL_BINS) $(ALL_INCLUDES) + +clean: + @exec rm -f $(ALL_LIBS) $(ALL_BINS) $(wildcard src/*/*.o src/*/*.lo) $(EXTRA_TARGETS) + +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 $(STATIC_LIBS)),) + exec $(STRIP) -x -R .note -R .comment -R .note.GNU-stack $(STATIC_LIBS) +endif +ifneq ($(strip $(ALL_BINS)$(SHARED_LIBS)),) + exec $(STRIP) -R .note -R .comment -R .note.GNU-stack $(ALL_BINS) $(SHARED_LIBS) +endif + +install: install-dynlib install-libexec install-bin install-lib install-include +install-dynlib: $(SHARED_LIBS:lib%.so.xyzzy=$(DESTDIR)$(dynlibdir)/lib%.so) +install-libexec: $(LIBEXEC_TARGETS:%=$(DESTDIR)$(libexecdir)/%) +install-bin: $(BIN_TARGETS:%=$(DESTDIR)$(bindir)/%) +install-lib: $(STATIC_LIBS:lib%.a.xyzzy=$(DESTDIR)$(libdir)/lib%.a) +install-include: $(ALL_INCLUDES:src/include/$(package)/%.h=$(DESTDIR)$(includedir)/$(package)/%.h) +install-data: $(ALL_DATA:src/etc/%=$(DESTDIR)$(datadir)/%) + +ifneq ($(exthome),) + +$(DESTDIR)$(exthome): $(DESTDIR)$(home) + exec $(INSTALL) -l $(notdir $(home)) $(DESTDIR)$(exthome) + +update: $(DESTDIR)$(exthome) + +global-links: $(DESTDIR)$(exthome) $(SHARED_LIBS:lib%.so.xyzzy=$(DESTDIR)$(sproot)/library.so/lib%.so.$(version_M)) $(BIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%) + +$(DESTDIR)$(sproot)/command/%: $(DESTDIR)$(home)/command/% + exec $(INSTALL) -D -l ..$(subst $(sproot),,$(exthome))/command/$( + + Please use the mailing-list for +questions about skabus. diff --git a/README.macosx b/README.macosx new file mode 100644 index 0000000..d71a096 --- /dev/null +++ b/README.macosx @@ -0,0 +1,4 @@ + + This package will compile and run on Darwin (MacOS X), but the building of +shared libraries is not supported. + Make sure you use the --disable-shared option to configure. 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..de87b55 --- /dev/null +++ b/configure @@ -0,0 +1,461 @@ +#!/bin/sh + +. package/info + +usage () { +cat </dev/null 2>&1 && { echo "$1" ; return 0 ; } +$1 +EOF + echo "$1" | sed -e "s/'/'\\\\''/g" -e "1s/^/'/" -e "\$s/\$/'/" -e "s#^'\([-[:alnum:]_,./:]*\)=\(.*\)\$#\1='\2#" -e "s|\*/|* /|g" +} + +fail () { + echo "$*" + exit 1 +} + +fnmatch () { + eval "case \"\$2\" in $1) return 0 ;; *) return 1 ;; esac" +} + +cmdexists () { + type "$1" >/dev/null 2>&1 +} + +trycc () { + test -z "$CC_AUTO" && cmdexists "$1" && CC_AUTO="$*" +} + +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 $CPPFLAGS $CPPFLAGS_POST $CFLAGS_AUTO $CFLAGS $CFLAGS_POST "$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 $CFLAGS $CFLAGS_POST $LDFLAGS_AUTO $LDFLAGS $LDFLAGS_POST -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 + +CC_AUTO= +CPPFLAGS_AUTO="-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -iquote src/include-local -Isrc/include" +CPPFLAGS_POST="$CPPFLAGS" +CPPFLAGS= +CFLAGS_AUTO="-pipe -Wall" +CFLAGS_POST="$CFLAGS" +CFLAGS=-O2 +LDFLAGS_AUTO= +LDFLAGS_POST="$LDFLAGS" +LDFLAGS= +LDFLAGS_NOSHARED= +LDFLAGS_SHARED=-shared +prefix= +exec_prefix='$prefix' +dynlibdir='$prefix/lib' +libexecdir='$exec_prefix/libexec' +bindir='$exec_prefix/bin' +libdir='$prefix/lib/$package' +includedir='$prefix/include' +sysdeps='$prefix/lib/skalibs/sysdeps' +manualsysdeps=false +shared=false +static=true +allpic=detect +slashpackage=false +abspath=false +sproot= +home= +exthome= +allstatic=true +evenmorestatic=false +addincpath='' +addlibspath='' +addlibdpath='' +vpaths='' +vpathd='' +build= + +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#*=} ;; + --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 ; evenmorestatic=false ;; + --enable-static-libc|--enable-static-libc=yes) allstatic=true ; evenmorestatic=true ;; + --disable-static-libc|--enable-static-libc=no) evenmorestatic=false ;; + --enable-all-pic|--enable-all-pic=yes) allpic=true ;; + --disable-all-pic|--enable-all-pic=no) allpic=false ;; + --enable-slashpackage=*) sproot=${arg#*=} ; slashpackage=true ; ;; + --enable-slashpackage) sproot= ; slashpackage=true ;; + --disable-slashpackage) sproot= ; slashpackage=false ;; + --enable-absolute-paths|--enable-absolute-paths=yes) abspath=true ;; + --disable-absolute-paths|--enable-absolute-paths=no) abspath=false ;; + --enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;; + --host=*|--target=*) target=${arg#*=} ;; + --build=*) build=${arg#*=} ;; + -* ) echo "$0: unknown option $arg" ;; + *=*) ;; + *) target=$arg ;; + esac +done + +# Add /usr in the default default case +if test -z "$prefix" ; then + if test "$libdir" = '$prefix/lib/$package' ; then + libdir=/usr/lib/$package + fi + if test "$includedir" = '$prefix/include' ; then + includedir=/usr/include + fi + if test "$sysdeps" = '$prefix/lib/skalibs/sysdeps' ; then + sysdeps=/usr/lib/skalibs/sysdeps + fi +fi + +# Expand installation directories +stripdir prefix +for i in exec_prefix dynlibdir libexecdir bindir libdir includedir sysdeps sproot ; 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 + extbinprefix=${exthome}/command + dynlibdir=${home}/library.so + bindir=${home}/command + libdir=${home}/library + libexecdir=$bindir + includedir=${home}/include + while read dep ; do + addincpath="$addincpath -I${sproot}${dep}/include" + vpaths="$vpaths ${sproot}${dep}/library" + addlibspath="$addlibspath -L${sproot}${dep}/library" + vpathd="$vpathd ${sproot}${dep}/library.so" + addlibdpath="$addlibdpath -L${sproot}${dep}/library.so" + done < package/deps-build +fi + +# Find a C compiler to use +if test -n "$target" && test x${build} != x${target} ; then + cross=${target}- +else + cross= +fi +echo "checking for C compiler..." +trycc ${cross}${CC} +trycc ${cross}gcc +trycc ${cross}clang +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 $CPPFLAGS $CPPFLAGS_POST $CFLAGS_AUTO $CFLAGS $CFLAGS_POST -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..." +if test -z "$target" ; then + if test -n "$build" ; then + target=$build ; + else + target=$($CC_AUTO -dumpmachine 2>/dev/null) || target=unknown + fi +fi +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 + +if test $allpic = detect ; then + echo "Checking whether we need to build everything as PIC..." + if $CC_AUTO $CPPFLAGS_AUTO $CPPFLAGS $CPPFLAGS_POST $CFLAGS_AUTO $CFLAGS $CFLAGS_POST -dM -E - < /dev/null | grep -qF __PIE__ ; then + allpic=true + echo " ... yes" + else + allpic=false + echo " ... no" + fi +fi +if $allpic ; then + tryflag CFLAGS_AUTO -fPIC +fi + +spawn_lib=$(cat $sysdeps/spawn.lib) +socket_lib=$(cat $sysdeps/socket.lib) +sysclock_lib=$(cat $sysdeps/sysclock.lib) +tainnow_lib=$(cat $sysdeps/tainnow.lib) +timer_lib=$(cat $sysdeps/timer.lib) +util_lib=$(cat $sysdeps/util.lib) + +tryflag CFLAGS_AUTO -std=c99 +tryflag CFLAGS -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 -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 CFLAGS_AUTO -ffunction-sections +tryflag CFLAGS_AUTO -fdata-sections + +tryldflag LDFLAGS_AUTO -Wl,--sort-section=alignment +tryldflag LDFLAGS_AUTO -Wl,--sort-common + +CPPFLAGS_AUTO="${CPPFLAGS_AUTO}${addincpath}" + +if $evenmorestatic ; then + LDFLAGS_NOSHARED=-static +fi + +if $shared ; then + tryldflag LDFLAGS -Wl,--hash-style=both +fi + +LDFLAGS_SHARED="${LDFLAGS_SHARED}${addlibdpath}" + +if $allstatic ; then + LDFLAGS_NOSHARED="${LDFLAGS_NOSHARED}${addlibspath}" + tryldflag LDFLAGS_NOSHARED -Wl,--gc-sections +else + LDFLAGS_NOSHARED="${LDFLAGS_NOSHARED}${addlibdpath}" +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 + +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 +libdir := $libdir +includedir := $includedir +sysdeps := $sysdeps +slashpackage := $slashpackage +sproot := $sproot +version := $version +home := $home +exthome := $exthome +SPAWN_LIB := ${spawn_lib} +SOCKET_LIB := ${socket_lib} +SYSCLOCK_LIB := ${sysclock_lib} +TAINNOW_LIB := ${tainnow_lib} +TIMER_LIB := ${timer_lib} +UTIL_LIB := ${util_lib} + +CC := ${CC_AUTO##${cross}} +CPPFLAGS_AUTO := $CPPFLAGS_AUTO +CPPFLAGS := $CPPFLAGS $CPPFLAGS_POST +CFLAGS_AUTO := $CFLAGS_AUTO +CFLAGS := $CFLAGS $CFLAGS_POST +LDFLAGS_AUTO := $LDFLAGS_AUTO +LDFLAGS := $LDFLAGS $LDFLAGS_POST +LDFLAGS_SHARED := $LDFLAGS_SHARED +LDFLAGS_NOSHARED := $LDFLAGS_NOSHARED +CROSS_COMPILE := $cross + +vpath lib%.a$vpaths +vpath lib%.so$vpathd +EOF +if $allstatic ; then + echo ".LIBPATTERNS := lib%.a" + echo "DO_ALLSTATIC := 1" +else + echo ".LIBPATTERNS := lib%.so" +fi +if $static ; then + echo "DO_STATIC := 1" +else + echo "DO_STATIC :=" +fi +if $shared ; then + echo "DO_SHARED := 1" +else + echo "DO_SHARED :=" +fi +if $allpic ; then + echo "STATIC_LIBS_ARE_PIC := 1" +else + echo "STATIC_LIBS_ARE_PIC :=" +fi + +exec 1>&3 3>&- +echo " ... done." + +echo "creating src/include/${package}/config.h..." +mkdir -p -m 0755 src/include/${package} +exec 3>&1 1> src/include/${package}/config.h +cat <&3 3>&- +echo " ... done." diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000..140f1e5 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,134 @@ + + + + + + skabus - a Unix bus system + + + + + + +

+Software
+skarnet.org +

+ +

skabus

+ +

What is it ?

+ +

+ skabus is a suite of programs and libraries for Unix systems +that aim to implement a bus, i.e. a many-to-many interprocess +communication mechanism. +

+ +

+ It is very much a work in progress, and won't be complete for a long time. +For now, it looks like a random collection of tools, even though there is +a consistent vision behind them. +

+ +
+ + +
  • An overview of skabus
  • + + +
    +--> + +

    Installation

    + +

    Requirements

    + +
      +
    • A POSIX-compliant system with a standard C development environment
    • +
    • GNU make, version 3.81 or later
    • +
    • skalibs version +2.6.1.0 or later
    • +
    • execline version +2.3.0.3 or later
    • +
    • s6 version +2.6.1.1 or later
    • + +
    + +

    Licensing

    + +

    + skabus is free software. It is available under the +ISC license. +

    + +

    Download

    + +
      +
    • The current released version of skabus is 0.0.1.0.
    • +
    • Alternatively, you can checkout a copy of the skabus git repository: +
       git clone git://git.skarnet.org/skabus 
    • +
    + +

    Compilation

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

    Upgrade notes

    + +
      +
    • This page lists the differences to be aware of between +the previous versions of skabus and the current one.
    • +
    + +
    + +

    Reference

    + +

    Commands

    + +

    + All these commands exit 111 if they encounter a temporary error or +hardware error, and +100 if they encounter a permanent error - such as a misuse. Short-lived +commands exit 0 on success. Other exit codes are documented in the +relevant page. +

    + +

    Publication/subscription

    + + + +
    + + +

    Related resources

    +
    + +

    skabus discussion

    + +
      +
    • skabus is discussed on the +skaware mailing-list.
    • +
    + +

    Similar work

    + +
      +
    • D-Bus is +the most widely used Linux bus. It's also a horrible, inefficient mess.
    • +
    • ubus is +OpenWrt's micro-bus architecture.
    • +
    + + + diff --git a/doc/skabus-dyntee-client.html b/doc/skabus-dyntee-client.html new file mode 100644 index 0000000..1f54a8b --- /dev/null +++ b/doc/skabus-dyntee-client.html @@ -0,0 +1,57 @@ + + + + + + skabus: the skabus-dyntee-client program + + + + + + +

    +skabus
    +Software
    +skarnet.org +

    + +

    The skabus-dyntee-client program

    + +

    +skabus-dyntee-client is a client for the +skabus-dyntee server. +It connects to a Unix domain socket where a +skabus-dyntee instance is listening, +then executes into a program with the data stream from skabus-dyntee +on its standard input. +

    + +

    Interface

    + +
    +     skabus-dyntee-client path prog...
    +
    + +
      +
    • skabus-dyntee-client connects to the Unix domain socket at path. +It assumes the other end of the socket is a skabus-dyntee +(or skabus-dynteed, which is the same) instance.
    • +
    • It executes into the prog... command line with the +socket as prog's standard input.
    • +
    + +

    Notes

    + +
      +
    • It is possible for prog to immediately get EOF on its +standard input. This likely means that the server has denied the +connection (skabus-dyntee-client did not run with an authorized uid +or gid). But it could also mean that the stream ended right after +the client connected.
    • +
    • The socket is shut down for writing, so prog can +only read on its stdin; attempts to write will always fail.
    • +
    + + + diff --git a/doc/skabus-dyntee.html b/doc/skabus-dyntee.html new file mode 100644 index 0000000..57b34f3 --- /dev/null +++ b/doc/skabus-dyntee.html @@ -0,0 +1,123 @@ + + + + + + skabus: the skabus-dyntee program + + + + + + +

    +skabus
    +Software
    +skarnet.org +

    + +

    The skabus-dyntee program

    + +

    +skabus-dyntee is a dynamic tee, which is the +simplest publisher daemon possible. +It listens on a Unix domain socket, accepts client connections, and +publishes to its clients everything it reads on its standard +input, as a byte stream. It only writes to clients and never reads +from them. +

    + +

    Interface

    + +
    +     skabus-dyntee [ -1 ] [ -D | -d ] [ -c maxconn ] [ -b backlog ] [ -G gidlist ] [ -g gid ] [ -u uid ] [ -U ] [ -t clienttimeout ] [ -T lameducktimeout ] [ -i rulesdir | -x rulesfile ] path
    +
    + +
      +
    • skabus-dyntee binds to the Unix domain socket at path.
    • +
    • If applicable, it drops root privileges.
    • +
    • It listens to its socket and accepts client connections.
    • +
    • Whenever it has data available on its standard input, it reads +that data and writes it to every client it has. It duplicates its +stdin stream to all its clients, hence the name dynamic tee.
    • +
    • When it reads EOF on its stdin, or when it receives a SIGTERM, +it waits for its clients to read their pending data, then exits 0.
    • +
    + +

    + skabus-dyntee is just a wrapper that binds to its socket and +drops privileges before executing into +skabus-dynteed. For details of +the daemon's operation, see the +skabus-dynteed documentation. +

    + +

    Options

    + +
      +
    • -1 : write a newline to stdout, before +closing it, right after binding and listening to the Unix socket. +If stdout is suitably redirected, this can be used by monitoring +programs to check when the server is ready to accept connections.
    • +
    • -d : allow instant rebinding to the same path +even if it has been used not long ago - this is the SO_REUSEADDR flag to +setsockopt() +and is generally used with server programs. This is the default. Note that +path will be deleted if it already exists at program start time.
    • +
    • -D : disallow instant rebinding to the same path.
    • +
    • -c maxconn : accept at most +maxconn concurrent client connections. Default is 40. It is +impossible to set it higher than the value of the SKABUS_DYNTEE_MAX macro, +which is 1000. +
    • -b backlog : set a maximum of +backlog backlog connections on the socket. Extra +connection attempts will rejected by the kernel.
    • +
    • -G gidlist : change skabus-dyntee's +supplementary group list to gidlist after binding the socket. +This is only valid when run as root. gidlist must be a +comma-separated list of numerical group IDs.
    • +
    • -g gid : change skabus-dyntee's groupid +to gid after binding the socket. This is only valid when run +as root.
    • +
    • -u uid : change skabus-dyntee's userid +to uid after binding the socket. This is only valid when run +as root.
    • +
    • -U : change skabus-dyntee's user id, group id and +supplementary group list +according to the values of the UID, GID and GIDLIST environment variables +after binding the socket. This is only valid when run as root. +This can be used with the +s6-envuidgid +program to easily script a service that binds to a privileged socket +then drops its privileges to those of a named non-root account.
    • +
    • -t clienttimeout : disconnect a client +that has not read its data after clienttimeout milliseconds. +By default, clienttimeout is 0, which means infinite.
    • +
    • -T lameducktimeout : after +skabus-dyntee has been told to exit, clients will have +lameducktimeout milliseconds to read their pending data, +after which skabus-dyntee will exit anyway. +By default, lameducktimeout is 0, which means infinite.
    • +
    • -x rulesfile : read access rights +configuration from CDB file rulesfile.
    • +
    • -i rulesdir : read access rights +configuration from the filesystem in directory rulesdir.
    • +
    + +

    Notes

    + +
      +
    • skabus-dyntee does not interpret its options itself. It just +dispatches them to the appropriate program on the command line that +it builds.
    • +
    • From the user's point of view, skabus-dyntee behaves like a +long-lived process, even if the long-lived process itself is called +skabus-dynteed. Every operational detail +of skabus-dynteed applies to skabus-dyntee as well; in particular, +make sure to properly +configure the clients' +access rights.
    • +
    + + + diff --git a/doc/skabus-dynteed.html b/doc/skabus-dynteed.html new file mode 100644 index 0000000..7573f3b --- /dev/null +++ b/doc/skabus-dynteed.html @@ -0,0 +1,154 @@ + + + + + + skabus: the skabus-dynteed program + + + + + + +

    +skabus
    +Software
    +skarnet.org +

    + +

    The skabus-dynteed program

    + +

    +skabus-dynteed is the serving part of the +skabus-dyntee program. +It assumes that one of its file descriptors (3 or above) is a +bound, listening, non-blocking domain socket; +it accepts connections from clients connecting to that socket, +and copies its stdin stream to all its clients. +

    + +

    Interface

    + +
    +     skabus-dynteed [ -1 ] [ -c maxconn ] [ -t clienttimeout ] [ -T lameducktimeout ] [ -i rulesdir | -x rulesfile ]
    +
    + +
      +
    • skabus-dynteed accepts connections from clients to an already +bound and listening SOCK_STREAM Unix domain socket, by default on +its file descriptor 3.
    • +
    • It runs until it receives a SIGTERM or until it reads EOF +on its stdin. In that case, it stops accepting new client connections, +and exits 0 when all clients have read their pending data.
    • +
    • Client connections last as long as the client wants to, unless an +error occurs, or unless the server is told to exit - in which cases +skabus-dynteed forcibly disconnects the client.
    • +
    • Clients cannot write anything to skabus-dynteed. They can only +read a stream of bytes on their socket, which is a copy of what +skabus-dynteed reads on its standard input.
    • +
    + +

    Options

    + +
      +
    • -1 : write a newline to stdout, and close stdout, +right before entering the client-accepting loop. +If stdout is suitably redirected, this can be used by monitoring +programs to check when the server is accepting connections. See +this page +for more information on readiness notification.
    • +
    • -c maxconn : accept at most +maxconn concurrent connections. Default is 40. It is +impossible to set it higher than the value of the SKABUS_DYNTEE_MAX macro, +i.e. 1000.
    • +
    • -t clienttimeout : disconnect a client +if it has not read its pending data after clienttimeout milliseconds. +By default, clienttimeout is 0, which means infinite.
    • +
    • -T lameducktimeout : give clients +lameducktimeout milliseconds to read their pending data when +skabus-dynteed is going to exit. +By default, lameducktimeout is 0, which means infinite.
    • +
    • -x rulesfile : read access rights +configuration from +CDB +file rulesfile.
    • +
    • -i rulesdir : read access rights +configuration from the filesystem in directory rulesdir.
    • +
    + +

    Signals

    + +
      +
    • SIGTERM: enter lameduck mode, then exit when all clients have +read their pending data (or lameducktimeout milliseconds have +elapsed).
    • +
    • SIGHUP: reopen rulesfile, if skabus-dynteed has been run +with the -x option. It is not necessary to send skabus-dynteed +a SIGHUP when the -i option is used instead: configuration +changes in the filesystem are automatically picked up.
    • +
    + + +

    Configuration

    +
    + +

    +skabus-dynteed (or its wrapper skabus-dyntee) +can be instructed not to accept every client. This is achieved +via a series of rules, or ruleset, stored in either a +rulesfile in the +CDB format, +and given to skabus-dynteed with the -x option, +or in a rulesdir, i.e. a directory in the filesystem following a +certain format, and given to skabus-dynteed with the -i option. +If neither the -i nor the -x option has been provided, +skabus-dynteed will accept connections from any client. +

    + +

    + Rulesets can be converted between the rulesdir and +rulesfile formats with the +s6-accessrules-cdb-from-fs and +s6-accessrules-fs-from-cdb +conversion tools. +

    + +

    Rules format

    + +

    + The rules file, or rules directory, follows the +s6 accessrules format for uid and +gid checking. For every connecting client, skabus-dynteed matches the uid +and gid of the client against the provided ruleset, and determines whether +the client is authorized or not to connect. +The right to connect is given if an +allow file is found in one of the subdirectories checked by +s6_accessrules_keycheck_uidgid. +For instance, to allow everyone to connect, touch +rulesdir/uid/default/allow. +

    + +

    + If a rulesfile or rulesdir has been provided to +skabus-dynteed, and the client's uid and gid match no rule in the +ruleset, then the connection is denied. +

    + +

    Notes

    + +
      +
    • skabus-dynteed is meant to be execve'd into by a program that gets +the listening socket. That program is normally +s6-ipcserver-socketbinder, +which creates the socket itself; but it can be a different one if the +socket is to be obtained by another means, for instance if it has +been retrieved from a fd-holding daemon.
    • +
    • Clients can plug into the data stream at any time. The data stream +should have a format making it easy for clients to synchronize with it.
    • +
    • The simplest way of connecting to a skabus-dynteed instance and +reading the data stream is via the +skabus-dyntee-client program.
    • +
    + + + diff --git a/doc/upgrade.html b/doc/upgrade.html new file mode 100644 index 0000000..0827f95 --- /dev/null +++ b/doc/upgrade.html @@ -0,0 +1,28 @@ + + + + + + skabus: how to upgrade + + + + + + +

    +skabus
    +Software
    +skarnet.org +

    + +

    What has changed in skabus

    + +

    in 0.0.1.0

    + +
      +
    • Initial release.
    • +
    + + + diff --git a/package/deps-build b/package/deps-build new file mode 100644 index 0000000..d63229b --- /dev/null +++ b/package/deps-build @@ -0,0 +1,3 @@ +/package/prog/skalibs +/package/admin/execline +/package/admin/s6 diff --git a/package/deps.mak b/package/deps.mak new file mode 100644 index 0000000..098b243 --- /dev/null +++ b/package/deps.mak @@ -0,0 +1,14 @@ +# +# This file has been generated by tools/gen-deps.sh +# + +src/misc/skabus-dyntee-client.o src/misc/skabus-dyntee-client.lo: src/misc/skabus-dyntee-client.c +src/misc/skabus-dyntee.o src/misc/skabus-dyntee.lo: src/misc/skabus-dyntee.c src/include/skabus/config.h +src/misc/skabus-dynteed.o src/misc/skabus-dynteed.lo: src/misc/skabus-dynteed.c + +skabus-dyntee: EXTRA_LIBS := +skabus-dyntee: src/misc/skabus-dyntee.o -lskarnet +skabus-dyntee-client: EXTRA_LIBS := +skabus-dyntee-client: src/misc/skabus-dyntee-client.o -lskarnet +skabus-dynteed: EXTRA_LIBS := +skabus-dynteed: src/misc/skabus-dynteed.o -ls6 -lskarnet diff --git a/package/info b/package/info new file mode 100644 index 0000000..5fefced --- /dev/null +++ b/package/info @@ -0,0 +1,4 @@ +package=skabus +version=0.0.1.0 +category=admin +package_macro_name=SKABUS diff --git a/package/modes b/package/modes new file mode 100644 index 0000000..5002c47 --- /dev/null +++ b/package/modes @@ -0,0 +1,3 @@ +skabus-dyntee 0755 +skabus-dynteed 0755 +skabus-dyntee-client 0755 diff --git a/package/targets.mak b/package/targets.mak new file mode 100644 index 0000000..e0b6e6b --- /dev/null +++ b/package/targets.mak @@ -0,0 +1,8 @@ +BIN_TARGETS := \ +skabus-dyntee \ +skabus-dynteed \ +skabus-dyntee-client + +LIBEXEC_TARGETS := + +LIB_DEFS := diff --git a/patch-for-solaris b/patch-for-solaris new file mode 100755 index 0000000..2d1296b --- /dev/null +++ b/patch-for-solaris @@ -0,0 +1,21 @@ +#!/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 +} + +# Solaris doesn't understand POSIX.1-2008 either. +sed -e 's/XOPEN_SOURCE=700/XOPEN_SOURCE=600/' < configure > configure.tmp +mv -f configure.tmp configure + +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/include/skabus/skabus.h b/src/include/skabus/skabus.h new file mode 100644 index 0000000..51b161f --- /dev/null +++ b/src/include/skabus/skabus.h @@ -0,0 +1,15 @@ +/* ISC license. */ + +#ifndef SKABUS_H +#define SKABUS_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/misc/deps-exe/skabus-dyntee b/src/misc/deps-exe/skabus-dyntee new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/misc/deps-exe/skabus-dyntee @@ -0,0 +1 @@ +-lskarnet diff --git a/src/misc/deps-exe/skabus-dyntee-client b/src/misc/deps-exe/skabus-dyntee-client new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/misc/deps-exe/skabus-dyntee-client @@ -0,0 +1 @@ +-lskarnet diff --git a/src/misc/deps-exe/skabus-dynteed b/src/misc/deps-exe/skabus-dynteed new file mode 100644 index 0000000..83cec1e --- /dev/null +++ b/src/misc/deps-exe/skabus-dynteed @@ -0,0 +1,2 @@ +-ls6 +-lskarnet diff --git a/src/misc/skabus-dyntee-client.c b/src/misc/skabus-dyntee-client.c new file mode 100644 index 0000000..b73980d --- /dev/null +++ b/src/misc/skabus-dyntee-client.c @@ -0,0 +1,39 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include + +#define USAGE "skabus-dyntee-client path prog..." +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv, char const *const *envp) +{ + PROG = "skabus-dyntee-client" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "", &l) ; + if (opt == -1) break ; + switch (opt) + { + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + if (argc < 2) dieusage() ; + } + + { + int fd = ipc_stream_b() ; + if (fd < 0) strerr_diefu1sys(111, "create socket") ; + if (!ipc_connect(fd, argv[0])) strerr_diefu2sys(111, "connect to ", argv[0]) ; + if (shutdown(fd, SHUT_WR) < 0) strerr_diefu1sys(111, "shutdown socket for writing") ; + if (fd_move(0, fd) < 0) strerr_diefu1sys(111, "move socket fd to stdin") ; + } + xpathexec_run(argv[1], argv+1, envp) ; +} diff --git a/src/misc/skabus-dyntee.c b/src/misc/skabus-dyntee.c new file mode 100644 index 0000000..f0832c4 --- /dev/null +++ b/src/misc/skabus-dyntee.c @@ -0,0 +1,149 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "skabus-dyntee [ -d | -D ] [ -1 ] [ -c maxconn ] [ -b backlog ] [ -G gid,gid,... ] [ -g gid ] [ -u uid ] [ -U ] [ -t timeout ] [ -T lameducktimeout ] [ -i rulesdir | -x rulesfile ] socketpath" +#define dieusage() strerr_dieusage(100, USAGE) + +int main (int argc, char const *const *argv, char const *const *envp) +{ + int flag1 = 0 ; + int flagU = 0 ; + int flagreuse = 1 ; + uid_t uid = 0 ; + gid_t gid = 0 ; + gid_t gids[NGROUPS_MAX] ; + size_t gidn = (size_t)-1 ; + unsigned int maxconn = 0 ; + unsigned int backlog = (unsigned int)-1 ; + unsigned int timeout = 0 ; + unsigned int ltimeout = 0 ; + char const *rulesdir = 0 ; + char const *rulesfile = 0 ; + PROG = "skabus-dyntee" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + register int opt = subgetopt_r(argc, argv, "Dd1Uc:b:u:g:G:t:T:i:x:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'D' : flagreuse = 0 ; break ; + case 'd' : flagreuse = 1 ; break ; + case '1' : flag1 = 1 ; break ; + case 'c' : if (!uint0_scan(l.arg, &maxconn)) dieusage() ; if (!maxconn) maxconn = 1 ; break ; + case 'b' : if (!uint0_scan(l.arg, &backlog)) dieusage() ; break ; + case 'u' : if (!uid0_scan(l.arg, &uid)) dieusage() ; break ; + case 'g' : if (!gid0_scan(l.arg, &gid)) dieusage() ; break ; + case 'G' : if (!gid_scanlist(gids, NGROUPS_MAX, l.arg, &gidn) && *l.arg) dieusage() ; break ; + case 'U' : flagU = 1 ; uid = 0 ; gid = 0 ; gidn = (unsigned int)-1 ; break ; + case 't' : if (!uint0_scan(l.arg, &timeout)) dieusage() ; break ; + case 'T' : if (!uint0_scan(l.arg, <imeout)) dieusage() ; break ; + case 'i' : rulesdir = l.arg ; rulesfile = 0 ; break ; + case 'x' : rulesfile = l.arg ; rulesdir = 0 ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + if (!argc) dieusage() ; + } + + { + size_t pos = 0 ; + unsigned int m = 0 ; + int fdin = dup(0) ; + char const *newargv[31] ; + char fmt[UINT_FMT * 5 + UID_FMT + GID_FMT * (1 + NGROUPS_MAX)] ; + if (fdin < 0) strerr_diefu1sys(111, "dup(0)") ; + if (fdin < 3) strerr_dief1x(100, "invalid standard file descriptors") ; + pos += uint_fmt(fmt + pos, fdin) ; + fmt[pos++] = 0 ; + newargv[m++] = S6_EXTBINPREFIX "s6-ipcserver-socketbinder" ; + if (!flagreuse) newargv[m++] = "-D" ; + if (backlog != (unsigned int)-1) + { + newargv[m++] = "-b" ; + newargv[m++] = fmt + pos ; + pos += uint_fmt(fmt + pos, backlog) ; + fmt[pos++] = 0 ; + } + newargv[m++] = "--" ; + newargv[m++] = argv[0] ; + if (flagU || uid || gid || gidn != (size_t)-1) + { + newargv[m++] = S6_EXTBINPREFIX "s6-applyuidgid" ; + if (flagU) newargv[m++] = "-Uz" ; + if (uid) + { + newargv[m++] = "-u" ; + newargv[m++] = fmt + pos ; + pos += uid_fmt(fmt + pos, uid) ; + fmt[pos++] = 0 ; + } + if (gid) + { + newargv[m++] = "-g" ; + newargv[m++] = fmt + pos ; + pos += gid_fmt(fmt + pos, gid) ; + fmt[pos++] = 0 ; + } + if (gidn != (size_t)-1) + { + newargv[m++] = "-G" ; + newargv[m++] = fmt + pos ; + pos += gid_fmtlist(fmt + pos, gids, gidn) ; + fmt[pos++] = 0 ; + } + newargv[m++] = "--" ; + } + newargv[m++] = EXECLINE_EXTBINPREFIX "fdswap" ; + newargv[m++] = "0" ; + newargv[m++] = fmt ; + newargv[m++] = SKABUS_BINPREFIX "skabus-dynteed" ; + newargv[m++] = "-d" ; + newargv[m++] = fmt ; + if (flag1) newargv[m++] = "-1" ; + if (maxconn) + { + newargv[m++] = "-c" ; + newargv[m++] = fmt + pos ; + pos += uint_fmt(fmt + pos, maxconn) ; + fmt[pos++] = 0 ; + } + if (timeout) + { + newargv[m++] = "-t" ; + newargv[m++] = fmt + pos ; + pos += uint_fmt(fmt + pos, timeout) ; + fmt[pos++] = 0 ; + } + if (ltimeout) + { + newargv[m++] = "-T" ; + newargv[m++] = fmt + pos ; + pos += uint_fmt(fmt + pos, ltimeout) ; + fmt[pos++] = 0 ; + } + if (rulesdir) + { + newargv[m++] = "-i" ; + newargv[m++] = rulesdir ; + } + else if (rulesfile) + { + newargv[m++] = "-x" ; + newargv[m++] = rulesfile ; + } + newargv[m++] = 0 ; + xpathexec_run(newargv[0], newargv, envp) ; + } +} diff --git a/src/misc/skabus-dynteed.c b/src/misc/skabus-dynteed.c new file mode 100644 index 0000000..8b0e292 --- /dev/null +++ b/src/misc/skabus-dynteed.c @@ -0,0 +1,305 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include /* shutdown */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "skabus-dynteed [ -d fdsocket ] [ -c maxconn ] [ -1 ] [ -t timeout ] [ -T lameducktimeout ] [ -i rulesdir | -x rulesfile ]" +#define dieusage() strerr_dieusage(100, USAGE) ; +#define dienomem() strerr_diefu1sys(111, "stralloc_catb") ; +#define die() strerr_dief1sys(101, "unexpected error") ; + +#define SKABUS_DYNTEE_MAX 1000 + +static int cont = 1 ; +static tain_t lameduckdeadline ; + +static unsigned int rulestype = 0 ; +static char const *rules = 0 ; +static int cdbfd = -1 ; +static struct cdb cdbmap = CDB_ZERO ; + +typedef struct client_s client_t, *client_t_ref ; +struct client_s +{ + unsigned int xindex ; + tain_t deadline ; + bufalloc ba ; +} ; + +static void client_free (client_t *c) +{ + fd_close(bufalloc_fd(&c->ba)) ; + bufalloc_free(&c->ba) ; +} + +static void handle_signals (void) +{ + for (;;) switch (selfpipe_read()) + { + case -1 : strerr_diefu1sys(111, "selfpipe_read()") ; + case 0 : return ; + case SIGTERM : + { + if (cont) + { + cont = 0 ; + tain_add_g(&lameduckdeadline, &lameduckdeadline) ; + } + break ; + } + case SIGHUP : + { + int fd ; + struct cdb c = CDB_ZERO ; + if (rulestype != 2) break ; + fd = open_readb(rules) ; + if (fd < 0) break ; + if (cdb_init(&c, fd) < 0) + { + fd_close(fd) ; + break ; + } + cdb_free(&cdbmap) ; + fd_close(cdbfd) ; + cdbfd = fd ; + cdbmap = c ; + } + break ; + default : break ; + } +} + +static inline int new_connection (int fd) +{ + s6_accessrules_params_t params = S6_ACCESSRULES_PARAMS_ZERO ; + uid_t uid ; + gid_t gid ; + if (!rulestype) return 1 ; + if (getpeereid(fd, &uid, &gid) < 0) + { + strerr_warnwu1sys("getpeereid") ; + return 0 ; + } + if ((rulestype == 1 ? s6_accessrules_uidgid_fs(uid, gid, rules, ¶ms) : s6_accessrules_uidgid_cdb(uid, gid, &cdbmap, ¶ms)) != S6_ACCESSRULES_ALLOW) + return 0 ; + s6_accessrules_params_free(¶ms) ; + return 1 ; +} + +int main (int argc, char const *const *argv, char const *const *envp) +{ + tain_t readtto ; + int spfd ; + int flag1 = 0 ; + unsigned int maxconn = 40 ; + unsigned int fdsocket = 3 ; + PROG = "skabus-dynteed" ; + + { + subgetopt_t l = SUBGETOPT_ZERO ; + unsigned int t = 0, T = 0 ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "d:1c:i:x:t:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'd' : if (!uint0_scan(l.arg, &fdsocket)) dieusage() ; break ; + case '1' : flag1 = 1 ; break ; + case 'i' : rules = l.arg ; rulestype = 1 ; break ; + case 'x' : rules = l.arg ; rulestype = 2 ; break ; + case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ; + case 'T' : if (!uint0_scan(l.arg, &T)) dieusage() ; break ; + case 'c' : if (!uint0_scan(l.arg, &maxconn)) dieusage() ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + if (t) tain_from_millisecs(&readtto, t) ; + else readtto = tain_infinite_relative ; + if (T) tain_from_millisecs(&lameduckdeadline, T) ; + else lameduckdeadline = tain_infinite_relative ; + } + if (maxconn > SKABUS_DYNTEE_MAX) maxconn = SKABUS_DYNTEE_MAX ; + if (!maxconn) maxconn = 1 ; + { + struct stat st ; + if (fstat(fdsocket, &st) < 0) strerr_diefu1sys(111, "fstat socket descriptor") ; + if (!S_ISSOCK(st.st_mode)) strerr_dief1x(100, "descriptor is not a socket") ; + } + if (flag1) + { + if (fcntl(1, F_GETFD) < 0) + strerr_dief1sys(100, "called with option -1 but stdout said") ; + } + else close(1) ; + if (ndelay_on(0) < 0) strerr_diefu1sys(111, "set stdin non-blocking") ; + spfd = selfpipe_init() ; + if (spfd < 0) strerr_diefu1sys(111, "selfpipe_init") ; + if (sig_ignore(SIGPIPE) < 0) strerr_diefu1sys(111, "ignore SIGPIPE") ; + { + sigset_t set ; + sigemptyset(&set) ; + sigaddset(&set, SIGTERM) ; + sigaddset(&set, SIGHUP) ; + if (selfpipe_trapset(&set) < 0) strerr_diefu1sys(111, "trap signals") ; + } + + if (rulestype == 2) + { + cdbfd = open_readb(rules) ; + if (cdbfd < 0) strerr_diefu3sys(111, "open ", rules, " for reading") ; + if (cdb_init(&cdbmap, cdbfd) < 0) + strerr_diefu2sys(111, "cdb_init ", rules) ; + } + + { + unsigned int numconn = 0 ; + client_t clients[maxconn] ; + + if (flag1) + { + fd_write(1, "\n", 1) ; + fd_close(1) ; + } + tain_now_g() ; + + for (;;) + { + tain_t deadline ; + int r = 2 ; + iopause_fd x[2 + cont + numconn] ; + x[0].fd = spfd ; + x[0].events = IOPAUSE_READ ; + x[1].fd = fdsocket ; + x[1].events = (cont && (numconn < maxconn)) ? IOPAUSE_READ : 0 ; + if (cont) + { + tain_add_g(&deadline, &tain_infinite_relative) ; + x[2].fd = 0 ; + x[2].events = IOPAUSE_READ ; + r++ ; + } + else deadline = lameduckdeadline ; + for (unsigned int i = 0 ; i < numconn ; i++) if (bufalloc_len(&clients[i].ba)) + { + if (tain_less(&clients[i].deadline, &deadline)) deadline = clients[i].deadline ; + x[r].fd = bufalloc_fd(&clients[i].ba) ; + x[r].events = IOPAUSE_WRITE ; + clients[i].xindex = r++ ; + } + + r = iopause_g(x, r, &deadline) ; + if (r < 0) strerr_diefu1sys(111, "iopause") ; + + if (!r) + { + for (unsigned int i = 0 ; i < numconn ; i++) + { + if (bufalloc_len(&clients[i].ba) && !tain_future(&clients[i].deadline)) + { + client_free(clients + i) ; + clients[i--] = clients[--numconn] ; + } + } + if (!(cont || (numconn && tain_future(&lameduckdeadline)))) break ; + continue ; + } + + if (x[0].revents & IOPAUSE_READ) handle_signals() ; + + for (unsigned int i = 0 ; i < numconn ; i++) + { + if (x[clients[i].xindex].revents & (IOPAUSE_WRITE | IOPAUSE_EXCEPT)) + { + if (!bufalloc_flush(&clients[i].ba) && !error_isagain(errno)) + { + client_free(clients + i) ; + clients[i--] = clients[--numconn] ; + } + } + } + + if (cont && x[1].revents & IOPAUSE_READ) + { + int fd = ipc_accept_nb(fdsocket, 0, 0, 0) ; + if (fd < 0) + { + if (!error_isagain(errno)) strerr_diefu1sys(111, "accept") ; + } + else if (!new_connection(fd)) fd_close(fd) ; + else if (shutdown(fd, SHUT_RD) < 0) + { + fd_close(fd) ; + strerr_warnwu1sys("shutdown client connection for reading - aborting it") ; + } + else + { + bufalloc_init(&clients[numconn].ba, &fd_write, fd) ; + tain_copynow(&clients[numconn].deadline) ; + numconn++ ; + } + } + + if (cont && x[2].revents & IOPAUSE_READ) + { + ssize_t r = sanitize_read(buffer_fill(buffer_0)) ; + if (r < 0) + { + fd_close(0) ; + cont = 0 ; + tain_add_g(&lameduckdeadline, &lameduckdeadline) ; + if (errno != EPIPE) strerr_warnwu1sys("read from stdin") ; + } + if (r > 0) + { + struct iovec v[2] ; + buffer_rpeek(buffer_0, v) ; + for (unsigned int i = 0 ; i < numconn ; i++) + { + if (!bufalloc_putv(&clients[i].ba, v, 2)) dienomem() ; + if (!tain_future(&clients[i].deadline)) tain_add_g(&clients[i].deadline, &readtto) ; + } + buffer_rseek(buffer_0, siovec_len(v, 2)) ; + } + } + + if (!cont) + { + for (unsigned int i = 0 ; i < numconn ; i++) + { + if (!bufalloc_len(&clients[i].ba)) + { + client_free(clients + i) ; + clients[i--] = clients[--numconn] ; + } + } + if (!numconn) break ; + } + } + } + return 0 ; +} diff --git a/tools/gen-deps.sh b/tools/gen-deps.sh new file mode 100755 index 0000000..6383ac2 --- /dev/null +++ b/tools/gen-deps.sh @@ -0,0 +1,93 @@ +#!/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= + libs= + while read dep ; do + if echo $dep | grep -q -e ^-l -e '^\${.*_LIB}' ; then + libs="$libs $dep" + else + deps="$deps src/$dir/$dep" + fi + done < src/$dir/deps-lib/$file + echo 'ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)' + echo "lib${file}.a.xyzzy:$deps" + echo else + echo "lib${file}.a.xyzzy:$(echo "$deps" | sed 's/\.o/.lo/g')" + echo endif + echo "lib${file}.so.xyzzy: EXTRA_LIBS :=$libs" + echo "lib${file}.so.xyzzy:$(echo "$deps" | sed 's/\.o/.lo/g')" + done + + for file in $(ls -1 src/$dir/deps-exe) ; do + deps= + libs= + while read dep ; do + if echo $dep | grep -q -- \\.o$ ; then + dep="src/$dir/$dep" + fi + if echo $dep | grep -q -- '^\${.*_LIB}' ; then + libs="$libs $dep" + else + deps="$deps $dep" + fi + done < src/$dir/deps-exe/$file + echo "$file: EXTRA_LIBS :=$libs" + echo "$file: src/$dir/$file.o$deps" + done +done diff --git a/tools/install.sh b/tools/install.sh new file mode 100755 index 0000000..89f9428 --- /dev/null +++ b/tools/install.sh @@ -0,0 +1,64 @@ +#!/bin/sh + +usage() { + echo "usage: $0 [-D] [-l] [-m mode] src dst" 1>&2 + exit 1 +} + +mkdirp=false +symlink=false +mode=0755 + +while getopts Dlm: name ; do + case "$name" in + D) mkdirp=true ;; + l) symlink=true ;; + m) mode=$OPTARG ;; + ?) usage ;; + esac +done +shift $(($OPTIND - 1)) + +test "$#" -eq 2 || usage +src=$1 +dst=$2 +tmp="$dst.tmp.$$" + +case "$dst" in + */) echo "$0: $dst ends in /" 1>&2 ; exit 1 ;; +esac + +set -C +set -e + +if $mkdirp ; then + umask 022 + case "$2" in + */*) mkdir -p "${dst%/*}" ;; + esac +fi + +trap 'rm -f "$tmp"' EXIT INT QUIT TERM HUP + +umask 077 + +if $symlink ; then + ln -s "$src" "$tmp" +else + cat < "$1" > "$tmp" + chmod "$mode" "$tmp" +fi + +mv -f "$tmp" "$dst" +if test -d "$dst" ; then + rm -f "$dst/$(basename $tmp)" + if $symlink ; then + mkdir "$tmp" + ln -s "$src" "$tmp/$(basename $dst)" + mv -f "$tmp/$(basename $dst)" "${dst%/*}" + rmdir "$tmp" + else + echo "$0: $dst is a directory" 1>&2 + exit 1 + fi +fi -- cgit v1.3.1