diff options
29 files changed, 2766 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9ac94b8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.o +*.lo +/config.mak +/src/include/s6-frontend/config.h +/s6-frontend-* diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..7a708a1 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Main author: + Laurent Bercot <ska-skaware@skarnet.org> diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..361dcb6 --- /dev/null +++ b/COPYING @@ -0,0 +1,13 @@ +Copyright (c) 2018 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..6442173 --- /dev/null +++ b/INSTALL @@ -0,0 +1,174 @@ +Build Instructions +------------------ + +* Requirements + ------------ + + - A POSIX compatible system with a standard C development environment + - GNU make version 3.81 or later + - skalibs version 2.9.1.0 or later: https://skarnet.org/software/skalibs/ + - execline version 2.6.0.0 or later: https://skarnet.org/software/execline/ + - s6 version 2.9.0.1 or later: https://skarnet.org/software/s6/ + - s6-rc version 0.5.1.1 or later: https://skarnet.org/software/s6-rc/ + - s6-linux-init version 1.0.3.1 or later: https://skarnet.org/software/s6-linux-init/ + + +* Standard usage + -------------- + + ./configure && make && sudo make install + + will work for most users. + It will install the binaries in /bin. + + 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. + + --enable-alias-daemontools will build some daemontools emulation +binaries and, at installation time, ensure daemontools binary names +(such as "envdir" or "svc") point to them. + + --enable-alias-runit will build some runit emulation binaries and, +at installation time, ensure runit binary names (such as "sv" or +"chpst") point to them. + + +* 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: https://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/$(<F) $@ + +$(DESTDIR)$(sproot)/library.so/lib%.so.$(version_M): $(DESTDIR)$(dynlibdir)/lib%.so.$(version_M) + exec $(INSTALL) -D -l ..$(subst $(sproot),,$(exthome))/library.so/$(<F) $@ + +.PHONY: update global-links + +endif + +$(DESTDIR)$(datadir)/%: src/etc/% + exec $(INSTALL) -D -m 644 $< $@ + +$(DESTDIR)$(dynlibdir)/lib%.so: lib%.so.xyzzy + $(INSTALL) -D -m 755 $< $@.$(version) && \ + $(INSTALL) -l $(@F).$(version) $@.$(version_m) && \ + $(INSTALL) -l $(@F).$(version_m) $@.$(version_M) && \ + exec $(INSTALL) -l $(@F).$(version_M) $@ + +$(DESTDIR)$(libexecdir)/% $(DESTDIR)$(bindir)/%: % 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.xyzzy + exec $(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) $^ $(EXTRA_LIBS) $(LDLIBS) + +lib%.a.xyzzy: + exec $(AR) rc $@ $^ + exec $(RANLIB) $@ + +lib%.so.xyzzy: + exec $(REALCC) -o $@ $(CFLAGS_ALL) $(CFLAGS_SHARED) $(LDFLAGS_ALL) $(LDFLAGS_SHARED) -Wl,-soname,$(patsubst lib%.so.xyzzy,lib%.so.$(version_M),$@) $^ $(EXTRA_LIBS) $(LDLIBS) + +.PHONY: it all clean distclean tgz strip install install-dynlib install-bin install-lib install-include install-data + +.DELETE_ON_ERROR: diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..b662d60 --- /dev/null +++ b/NEWS @@ -0,0 +1,6 @@ +Changelog for s6-frontend + +In 0.0.1.0 +---------- + + - Initial release. diff --git a/README b/README new file mode 100644 index 0000000..0d975bb --- /dev/null +++ b/README @@ -0,0 +1,25 @@ +s6-frontend - a s6-based init system with a friendly UI +------------------------------------------------------- + + s6-frontend is a set of programs providing interfaces +to the s6 family of programs (s6, s6-rc, s6-linux-init) +for users who are used to different systems. It also +comes with a full set of init scripts and can be used as +a turnkey init system. + + See https://skarnet.org/software/s6-frontend/ for details. + + +* Installation + ------------ + + See the INSTALL file. + + +* Contact information + ------------------- + + Laurent Bercot <ska-skaware at skarnet.org> + + Please use the <supervision at list.skarnet.org> mailing-list for +questions about s6-frontend. diff --git a/configure b/configure new file mode 100755 index 0000000..1abcd9c --- /dev/null +++ b/configure @@ -0,0 +1,509 @@ +#!/bin/sh + +cd `dirname "$0"` +. package/info + +usage () { +cat <<EOF +Usage: $0 [OPTION]... [TARGET] + +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=BINDIR user executables [EPREFIX/bin] + --libexecdir=DIR package-scoped executables [EPREFIX/libexec] + --libdir=DIR static library files [PREFIX/lib/$package] + --includedir=DIR C header files [PREFIX/include] + + If no --prefix option is given, by default libdir (but not dynlibdir) will be + /usr/lib/$package, and includedir will be /usr/include. + +Dependencies: + --with-sysdeps=DIR use sysdeps in DIR [PREFIX/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 + + If no --prefix option is given, by default sysdeps will be fetched from + /usr/lib/skalibs/sysdeps. + +Optional features: + --enable-shared build shared libraries [disabled] + --disable-static do not build static libraries [enabled] + --disable-allstatic do not prefer linking against static libraries [enabled] + --enable-static-libc make entirely static binaries [disabled] + --disable-all-pic do not build executables or static libs as PIC [enabled] + --enable-slashpackage[=ROOT] assume /package installation at ROOT [disabled] + --enable-absolute-paths do not rely on PATH to access this package's binaries, + hardcode absolute BINDIR/foobar paths instead [disabled] + --enable-nsss use the nsss library for user information [disabled] + --enable-aliases-daemontools build emulation of daemontools programs [disabled] + --enable-aliases-runit build emulation of runit programs [disabled] + +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="$*" +} + +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=true +slashpackage=false +abspath=false +usensss=false +sproot= +home= +exthome= +allstatic=true +evenmorestatic=false +addincpath='' +addlibspath='' +addlibdpath='' +vpaths='' +vpathd='' +build= +adaemontools=false +arunit=false + +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-nsss|--enable-nsss=yes) usensss=true ;; + --disable-nsss|--enable-nsss=no) usensss=false ;; + --enable-aliases-daemontools|--enable-aliases-daemontools=yes) adaemontools=true ;; + --disable-aliases-daemontools|--enable-aliases-daemontools=no) adaemontools=false ;; + --enable-aliases-runit|--enable-aliases-runit=yes) arunit=true ;; + --disable-aliases-runit|--enable-aliases-runit=no) arunit=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 condvar ; do + if test -n "$condvar" ; then + eval "cond=$condvar" + else + cond=true + fi + if $cond ; then + 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" + fi + 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 ${CC} +if test -n "$CC_AUTO" ; then + b=`basename "$CC"` + adjust_cross=false + if test "$b" != "$CC" ; then + adjust_cross=true + echo "$0: warning: compiler $CC is declared with its own path. If it's not accessible via PATH, you will need to pass AR, RANLIB and STRIP make variables to the make invocation." 1>&2 + fi + if test -n "$cross" ; then + if test "$b" = "${b##$cross}" ; then + echo "$0: warning: compiler $CC is declared as a cross-compiler for target $target but does not start with prefix ${cross}" 1>&2 + elif $adjust_cross ; then + cross=`dirname "$CC"`/"$cross" + fi + fi +fi +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 + +spawn_lib=$(cat $sysdeps/spawn.lib) +socket_lib=$(cat $sysdeps/socket.lib) +sysclock_lib=$(cat $sysdeps/sysclock.lib) +timer_lib=$(cat $sysdeps/timer.lib) +util_lib=$(cat $sysdeps/util.lib) + +if $allpic ; then + tryflag CPPFLAGS_AUTO -fPIC +fi +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} +TIMER_LIB := ${timer_lib} +UTIL_LIB := ${util_lib} + +CC := $CC_AUTO +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 +if $usensss ; then + echo "LIBNSSS := -lnsss" + echo "MAYBEPTHREAD_LIB := -lpthread" +else + echo "LIBNSSS :=" + echo "MAYBEPTHREAD_LIB :=" +fi +if $adaemontools ; then + echo "WRAP_DAEMONTOOLS := 1" +else + echo "WRAP_DAEMONTOOLS :=" +fi +if $arunit ; then + echo "WRAP_RUNIT := 1" +else + echo "WRAP_RUNIT :=" +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 <<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 \"$bindir/\"" + echo "#define ${package_macro_name}_EXTBINPREFIX \"$extbinprefix/\"" +elif $abspath ; then + echo "#define ${package_macro_name}_BINPREFIX \"$bindir/\"" + echo "#define ${package_macro_name}_EXTBINPREFIX \"$bindir/\"" +else + echo "#define ${package_macro_name}_BINPREFIX \"\"" + echo "#define ${package_macro_name}_EXTBINPREFIX \"\"" +fi +echo "#define ${package_macro_name}_LIBEXECPREFIX \"$libexecdir/\"" +echo +echo "#undef ${package_macro_name}_WRAP_DAEMONTOOLS" +if $adaemontools ; then + echo "#define ${package_macro_name}_WRAP_DAEMONTOOLS" +fi +echo "#undef ${package_macro_name}_WRAP_RUNIT" +if $arunit ; then + echo "#define ${package_macro_name}_WRAP_RUNIT" +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..bd6512c --- /dev/null +++ b/doc/index.html @@ -0,0 +1,149 @@ +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-frontend - a frontend to the s6 ecosystem</title> + <meta name="Description" content="s6-frontend - a frontend to the s6 ecosystem" /> + <meta name="Keywords" content="s6 s6-rc frontend administration root laurent bercot ska skarnet init" /> + <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="//skarnet.org/software/">Software</a><br /> +<a href="//skarnet.org/">skarnet.org</a> +</p> + +<h1> s6-frontend </h1> + +<h2> What is it ? </h2> + +<p> + <strong><em><red> s6-frontend is still in development. </red></em></strong> +</p> + +<p> + s6-frontend is a frontend to the s6 ecosystem. It is made of +several parts: +</p> + +<ul> + <li> A set of user-friendly commands, making it easier to manage a +s6-based system for people who are used to other tools. </li> + <li> An independent configuration file format, +and tools that automatically analyze a configuration written in that +format and transform it into a configuration suitable for booting a +system via +<a href="//skarnet.org/software/s6/">s6</a>, +<a href="//skarnet.org/software/s6-linux-init/">s6-linux-init</a> and +<a href="//skarnet.org/software/s6-rc/">s6-rc</a>. This should help +users who are not familiar with s6 and s6-rc directory-based configuration +but are used to, for instance, systemd unit files.</li> + <li> A prepackaged set of configuration files, implementing <em>policy</em>, +suitable for booting a large majority of Linux-based systems. This should +help distributions that want to switch to s6 but do not want to rewrite all +their init scripts in yet another format. </li> +</ul> + +<p> + These parts are all independent from one another. But when put all together, +they implement a powerful, fast, turnkey init system that is usable on +<em>any</em> distribution. +</p> + +<hr /> + +<ul> + <li> <a href="quickstart.html">Quickstart and FAQ</a> </li> +</ul> + +<hr /> +<h2> Installation </h2> + +<h3> Requirements </h3> + +<ul> + <li> A Linux-based system with a standard C development environment </li> + <li> GNU make, version 3.81 or later </li> + <li> <a href="//skarnet.org/software/skalibs/">skalibs</a> version +2.9.1.0 or later </li> + <li> <a href="//skarnet.org/software/execline/">execline</a> version +2.6.0.0 or later </li> + <li> <a href="//skarnet.org/software/s6/">s6</a> version +2.9.0.1 or later </li> + <li> <a href="//skarnet.org/software/s6-rc/">s6-rc</a> version +0.5.1.1 or later </li> + <li> <a href="//skarnet.org/software/s6-linux-init/">s6-linux-init</a> version +1.0.3.1 or later </li> +</ul> + +<p> + Those are all build-time dependencies as well as run-time dependencies. +skalibs is only a run-time dependency if you link the binaries against +the shared version of the skarnet library. +</p> + +<h3> Licensing </h3> + +<p> + s6-frontend 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-frontend is +<a href="s6-frontend-0.0.1.0.tar.gz">0.0.1.0</a>. <strong><red>(unavailable while in development)</red></strong> </li> + <li> Alternatively, you can checkout a copy of the +<a href="//git.skarnet.org/cgi-bin/cgit.cgi/s6-frontend/">s6-frontend +git repository</a>: +<pre> git clone git://git.skarnet.org/s6-frontend </pre> </li> + <li> There's also a +<a href="https://github.com/skarnet/s6-frontend">GitHub mirror</a> +of the s6-frontend git repository. </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-frontend 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-frontend-config-preprocess.html"><tt>s6-frontend-config-preprocess</tt></a> program </li> + <li> The <a href="s6-frontend-alias.html"><tt>s6-frontend-alias</tt></a> program </li> + <li> The <a href="s6-frontend-alias-chpst.html"><tt>s6-frontend-alias-chpst</tt></a> program </li> + <li> The <a href="s6-frontend-alias-sv.html"><tt>s6-frontend-alias-sv</tt></a> program </li> +</ul> + +<h2> Related resources </h2> + +<ul> + <li> <tt>s6-frontend</tt> is discussed on the +<a href="//skarnet.org/lists.html#supervision">supervision</a> mailing-list. </li> + <li> There is a <tt>#s6</tt> IRC channel on Freenode. Sometimes people +are there and even answer questions. </li> +</ul> + +</body> +</html> diff --git a/doc/quickstart.html b/doc/quickstart.html new file mode 100644 index 0000000..6c99510 --- /dev/null +++ b/doc/quickstart.html @@ -0,0 +1,26 @@ +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-frontend: quickstart and FAQ</title> + <meta name="Description" content="s6-frontend: quickstart and FAQ" /> + <meta name="Keywords" content="s6-frontend installation quickstart faq" /> + <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-frontend</a><br /> +<a href="//skarnet.org/software/">Software</a><br /> +<a href="//skarnet.org/">skarnet.org</a> +</p> + +<h1> Quickstart and FAQ for s6-frontend </h1> + +<p> + (To be written.) +</p> + +</body> +</html> diff --git a/doc/s6-frontend-alias.html b/doc/s6-frontend-alias.html new file mode 100644 index 0000000..4e824c9 --- /dev/null +++ b/doc/s6-frontend-alias.html @@ -0,0 +1,41 @@ +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-frontend: the s6-frontend-alias program</title> + <meta name="Description" content="s6-frontend: the s6-frontend-alias program" /> + <meta name="Keywords" content="s6 command s6-frontend-alias daemontools runit" /> + <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-frontend</a><br /> +<a href="//skarnet.org/software/">Software</a><br /> +<a href="//skarnet.org/">skarnet.org</a> +</p> + +<h1> The s6-frontend-alias program </h1> + +<p> +s6-frontend-alias +</p> + +<h2> Interface </h2> + +<pre> + s6-frontend-alias +</pre> + +<p> +</p> + +<h2> Options </h2> + +<ul> + <li> <tt>-v</tt> : verbose. </li> +</ul> + +</body> +</html> diff --git a/doc/s6-frontend-config-preprocess.html b/doc/s6-frontend-config-preprocess.html new file mode 100644 index 0000000..f58ff7c --- /dev/null +++ b/doc/s6-frontend-config-preprocess.html @@ -0,0 +1,87 @@ +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-frontend: the s6-frontend-config-preprocess program</title> + <meta name="Description" content="s6-frontend: the s6-frontend-config-preprocess program" /> + <meta name="Keywords" content="s6-frontend command s6 configuration unit file s6-frontend-config preprocess preprocessor" /> + <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6</a><br /> +<a href="//skarnet.org/software/">Software</a><br /> +<a href="//skarnet.org/">skarnet.org</a> +</p> + +<h1> The s6-frontend-config-preprocess program </h1> + +<p> + <tt>s6-frontend-config-preprocess</tt> reads a s6-frontend configuration +file and executes all its inclusion directives, also preprocessing the +included files. It streams the result to stdout, which is a complete +configuration file without inclusions. +</p> + +<h2> Interface </h2> + +<pre> + s6-frontend-config-preprocess <em>file</em> +</pre> + +<p> + <tt>s6-frontend-config-preprocess reads <em>file</em> and prints it +to stdout. It removes lines starting with <tt>!!</tt>. +</p> + +<p> + When it finds a <tt>!include</tt> or <tt>!includeonce</tt> directive +in <em>file</em>, it replaces it with the contents of the included +file - recursively preprocessed. +</p> + +<p> + When it finds a <tt>!includedir</tt> or <tt>!includedironce</tt> +directive in <em>file</em>, it replaces it with the recursively +preprocessed contents of every file present in the included +directory. The files are sorted alphabetically according to the +C locale. +</p> + +<p> + <tt>!includeonce</tt> and <tt>!includedironce</tt> only print +a file (resp. a directory) the first time they encounter it, and +silently ignore subsequent instances. <tt>!include</tt> and +<tt>!includedir</tt> directives will happily include the same +files several times. +</p> + +<p> + To avoid loops, a nesting limit exists. <tt>s6-frontend-config-preprocess</tt> +will fail if there are too many nested inclusions. +</p> + +<h2> Exit codes </h2> + +<ul> + <li> 0: success </li> + <li> 1: syntax error in a configuration file </li> + <li> 2: other error in a configuration file </li> + <li> 3: too many nested inclusions </li> + <li> 100: usage error </li> + <li> 111: system call failed </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> <tt>s6-frontend-config-preprocess</tt> is not meant to be +called directly by the user. It is normally invoked by +<a href="s6-frontend-config-parse.html">s6-frontend-config-parse</a>. +However, the binary is made available for debugging purposes. </li> +</ul> + +</body> +</html> diff --git a/doc/upgrade.html b/doc/upgrade.html new file mode 100644 index 0000000..24f7bfb --- /dev/null +++ b/doc/upgrade.html @@ -0,0 +1,28 @@ +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>s6-frontend: how to upgrade</title> + <meta name="Description" content="s6-frontend: how to upgrade" /> + <meta name="Keywords" content="s6-frontend installation upgrade" /> + <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">s6-frontend</a><br /> +<a href="//skarnet.org/software/">Software</a><br /> +<a href="//skarnet.org/">skarnet.org</a> +</p> + +<h1> What has changed in s6-frontend </h1> + +<h2> in 0.0.1.0 </h2> + +<ul> + <li> Initial release. </li> +</ul> + +</body> +</html> diff --git a/package/deps-build b/package/deps-build new file mode 100644 index 0000000..cc1abb1 --- /dev/null +++ b/package/deps-build @@ -0,0 +1,4 @@ +/package/prog/skalibs +/package/admin/execline +/package/admin/s6 +/package/admin/s6-rc diff --git a/package/deps.mak b/package/deps.mak new file mode 100644 index 0000000..ec41fd5 --- /dev/null +++ b/package/deps.mak @@ -0,0 +1,17 @@ +# +# This file has been generated by tools/gen-deps.sh +# + +src/alias/s6-frontend-alias-chpst.o src/alias/s6-frontend-alias-chpst.lo: src/alias/s6-frontend-alias-chpst.c +src/alias/s6-frontend-alias-sv.o src/alias/s6-frontend-alias-sv.lo: src/alias/s6-frontend-alias-sv.c +src/alias/s6-frontend-alias.o src/alias/s6-frontend-alias.lo: src/alias/s6-frontend-alias.c src/include/s6-frontend/config.h +src/config/s6-frontend-config-preprocess.o src/config/s6-frontend-config-preprocess.lo: src/config/s6-frontend-config-preprocess.c + +s6-frontend-alias: EXTRA_LIBS := -lskarnet +s6-frontend-alias: src/alias/s6-frontend-alias.o +s6-frontend-alias-chpst: EXTRA_LIBS := -lskarnet +s6-frontend-alias-chpst: src/alias/s6-frontend-alias-chpst.o +s6-frontend-alias-sv: EXTRA_LIBS := -ls6 -lskarnet ${SPAWN_LIB} +s6-frontend-alias-sv: src/alias/s6-frontend-alias-sv.o +s6-frontend-config-preprocess: EXTRA_LIBS := -lskarnet +s6-frontend-config-preprocess: src/config/s6-frontend-config-preprocess.o diff --git a/package/info b/package/info new file mode 100644 index 0000000..f0b5985 --- /dev/null +++ b/package/info @@ -0,0 +1,4 @@ +package=s6-frontend +version=0.0.1.0 +category=admin +package_macro_name=S6_FRONTEND diff --git a/package/modes b/package/modes new file mode 100644 index 0000000..8e2e6cf --- /dev/null +++ b/package/modes @@ -0,0 +1,4 @@ +s6-frontend-config-preprocess 0755 +s6-frontend-alias 0755 +s6-frontend-alias-sv 0755 +s6-frontend-alias-chpst 0755 diff --git a/package/targets.mak b/package/targets.mak new file mode 100644 index 0000000..5767606 --- /dev/null +++ b/package/targets.mak @@ -0,0 +1,75 @@ +BIN_TARGETS := \ +s6-frontend-config-preprocess + +LIBEXEC_TARGETS := + +WRAP_ANY := + +ifdef WRAP_DAEMONTOOLS + +DAEMONTOOLS_TARGETS := \ +envdir \ +envuidgid \ +fghack \ +multilog \ +pgrphack \ +readproctitle \ +setlock \ +setuidgid \ +softlimit \ +supervise \ +svc \ +svok \ +svscan \ +svscanboot \ +svstat \ +tai64n \ +tai64nlocal + +install-bin: $(DAEMONTOOLS_TARGETS:%=$(DESTDIR)$(bindir)/%) + +ifneq ($(exthome),) +global-links: $(DAEMONTOOLS_TARGETS:%=$(DESTDIR)$(sproot)/command/%) +endif + +WRAP_ANY := 1 + +endif + +ifdef WRAP_RUNIT + +RUNIT_TARGETS := \ +runit \ +runit-init \ +runsv \ +runsvchdir \ +runsvdir \ +svlogd \ +utmpset + +RUNIT_SPECIAL_TARGETS := chpst sv +BIN_TARGETS += s6-frontend-alias-sv s6-frontend-alias-chpst + +install-bin: $(RUNIT_TARGETS:%=$(DESTDIR)$(bindir)/%) $(RUNIT_SPECIAL_TARGETS:%=$(DESTDIR)$(bindir)/%) + +ifneq ($(exthome),) +global-links: $(RUNIT_TARGETS:%=$(DESTDIR)$(sproot)/command/%) $(RUNIT_SPECIAL_TARGETS:%=$(DESTDIR)$(sproot)/command/%) +endif + +WRAP_ANY := 1 + +$(DESTDIR)$(bindir)/chpst: $(DESTDIR)$(bindir)/s6-frontend-alias-chpst + exec $(INSTALL) -D -l s6-frontend-alias-chpst $@ +$(DESTDIR)$(bindir)/sv: $(DESTDIR)$(bindir)/s6-frontend-alias-sv + exec $(INSTALL) -D -l s6-frontend-alias-sv $@ + +endif + +ifdef WRAP_ANY + +BIN_TARGETS += s6-frontend-alias + +$(DAEMONTOOLS_TARGETS:%=$(DESTDIR)$(bindir)/%) $(RUNIT_TARGETS:%=$(DESTDIR)$(bindir)/%): $(DESTDIR)$(bindir)/s6-frontend-alias + exec $(INSTALL) -D -l s6-frontend-alias $@ + +endif diff --git a/src/alias/deps-exe/s6-frontend-alias b/src/alias/deps-exe/s6-frontend-alias new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/alias/deps-exe/s6-frontend-alias @@ -0,0 +1 @@ +-lskarnet diff --git a/src/alias/deps-exe/s6-frontend-alias-chpst b/src/alias/deps-exe/s6-frontend-alias-chpst new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/alias/deps-exe/s6-frontend-alias-chpst @@ -0,0 +1 @@ +-lskarnet diff --git a/src/alias/deps-exe/s6-frontend-alias-sv b/src/alias/deps-exe/s6-frontend-alias-sv new file mode 100644 index 0000000..b3e8440 --- /dev/null +++ b/src/alias/deps-exe/s6-frontend-alias-sv @@ -0,0 +1,3 @@ +-ls6 +-lskarnet +${SPAWN_LIB} diff --git a/src/alias/s6-frontend-alias-chpst.c b/src/alias/s6-frontend-alias-chpst.c new file mode 100644 index 0000000..860654e --- /dev/null +++ b/src/alias/s6-frontend-alias-chpst.c @@ -0,0 +1,347 @@ + /* ISC license. */ + +#include <string.h> +#include <stdint.h> +#include <stdlib.h> +#include <limits.h> +#include <errno.h> +#include <pwd.h> +#include <grp.h> + +#include <skalibs/uint64.h> +#include <skalibs/types.h> +#include <skalibs/bytestr.h> +#include <skalibs/sgetopt.h> +#include <skalibs/buffer.h> +#include <skalibs/strerr2.h> +#include <skalibs/stralloc.h> +#include <skalibs/genalloc.h> +#include <skalibs/env.h> +#include <skalibs/djbunix.h> + +#include <execline/config.h> + +#include <s6/config.h> + +#define USAGE "s6-frontend-alias-chpst [ -v ] [ -P ] [ -0 ] [ -1 ] [ -2 ] [ -u user ] [ -U user ] [ -b argv0 ] [ -e dir ] [ -n niceness ] [ -l lock | -L lock ] [ -m bytes ] [ -d bytes ] [ -o n ] [ -p n ] [ -f bytes ] [ -c bytes ] prog..." + +#define dienomem() strerr_diefu1sys(111, "stralloc_catb") +#define dieusage() strerr_dieusage(100, USAGE) + +static unsigned int verbosity = 0 ; + +static void printit (char const *const *argv) +{ + buffer_puts(buffer_2, PROG) ; + buffer_puts(buffer_2, ": info: executing the following command line:") ; + for (; *argv ; argv++) + { + buffer_puts(buffer_2, " ") ; + buffer_puts(buffer_2, *argv) ; + } + buffer_putsflush(buffer_2, "\n") ; +} + +static inline size_t parseuggnum (char const *s, uint32_t *flags, uid_t *uid, gid_t *gid, gid_t *tab) +{ + size_t n = 0 ; + size_t pos = uid_scan(s, uid) ; + if (!pos) dieusage() ; + if (!s[pos]) return 0 ; + if (s[pos] != ':') dieusage() ; + s += pos+1 ; + pos = gid_scan(s, gid) ; + if (!pos) dieusage() ; + *flags |= 32768 ; + if (!s[pos]) return 0 ; + if (s[pos] != ':') dieusage() ; + s += pos+1 ; + if (!gid_scanlist(tab, NGROUPS_MAX, s, &n)) dieusage() ; + return n ; +} + +static struct passwd *do_getpwnam (char const *s) +{ + struct passwd *pw = getpwnam(s) ; + if (!pw) + { + if (errno) strerr_diefu1sys(111, "read user database") ; + else strerr_dief2x(100, "user not found in user database: ", s) ; + } + return pw ; +} + +static struct group *do_getgrnam (char const *s) +{ + struct group *gr = getgrnam(s) ; + if (!gr) + { + if (errno) strerr_diefu1sys(111, "read group database") ; + else strerr_dief2x(100, "group not found in group database: ", s) ; + } + return gr ; +} + +static inline size_t parseuggsym (char const *s, uint32_t *flags, uid_t *uid, gid_t *gid, gid_t *tab) +{ + size_t n = 0 ; + struct passwd *pw ; + struct group *gr ; + size_t pos = str_chr(s, ':') ; + *flags |= 32768 ; + errno = 0 ; + if (!s[pos]) pw = do_getpwnam(s) ; + else + { + char tmp[pos+1] ; + memcpy(tmp, s, pos) ; + tmp[pos] = 0 ; + pw = do_getpwnam(tmp) ; + } + *uid = pw->pw_uid ; + if (!s[pos]) + { + *gid = pw->pw_gid ; + return 0 ; + } + s += pos+1 ; + pos = str_chr(s, ':') ; + errno = 0 ; + if (!s[pos]) gr = do_getgrnam(s) ; + else + { + char tmp[pos+1] ; + memcpy(tmp, s, pos) ; + tmp[pos] = 0 ; + gr = do_getgrnam(tmp) ; + } + *gid = gr->gr_gid ; + if (!s[pos]) return 0 ; + s += pos+1 ; + while (*s) + { + if (n >= NGROUPS_MAX) + strerr_dief1x(100, "too many supplementary groups listed for the -u option") ; + pos = str_chr(s, ':') ; + errno = 0 ; + if (!s[pos]) gr = do_getgrnam(s) ; + else + { + char tmp[pos+1] ; + memcpy(tmp, s, pos) ; + tmp[pos] = 0 ; + gr = do_getgrnam(tmp) ; + } + tab[n++] = gr->gr_gid ; + s += s[pos] ? pos+1 : pos ; + } + return n ; +} + +int main (int argc, char const *const *argv, char const *const *envp) +{ + static char const *valopt[6] = { "-m", "-d", "-o", "-p", "-f", "-c" } ; + genalloc envdirs = GENALLOC_ZERO ; /* char const * */ + stralloc newroot = STRALLOC_ZERO ; + unsigned int newargc = 0 ; + char const *argv0 = 0 ; + char const *lockfile = 0 ; + char const *envug = 0 ; + uint32_t flags = 0 ; + int niceval = 0 ; + char valfmt[6][UINT64_FMT] ; + char nicefmt[INT_FMT] ; + char uidfmt[UID_FMT] ; + char gidfmt[GID_FMT] ; + char gidlistfmt[GID_FMT * NGROUPS_MAX] ; + PROG = "s6-frontend-alias-chpst" ; + + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "vP012u:U:b:e:/:n:l:L:m:d:o:p:f:c:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'v' : verbosity++ ; break ; + case '0' : flags |= 1 ; newargc += 2 ; break ; + case '1' : flags |= 2 ; newargc += 2 ; break ; + case '2' : flags |= 4 ; newargc += 2 ; break ; + case 'P' : flags |= 8 ; newargc += 2 ; break ; + case 'b' : argv0 = l.arg ; newargc += 4 ; break ; + case 'u' : + { + size_t n ; + uid_t uid ; + gid_t gid ; + gid_t tab[NGROUPS_MAX] ; + newargc += 6 ; + flags |= 16384 ; flags &= ~32768 ; + n = l.arg[0] == ':' ? + parseuggnum(l.arg + 1, &flags, &uid, &gid, tab) : + parseuggsym(l.arg, &flags, &uid, &gid, tab) ; + uidfmt[uid_fmt(uidfmt, uid)] = 0 ; + if (flags & 32768) + { + newargc += 2 ; + gidfmt[gid_fmt(gidfmt, gid)] = 0 ; + } + gidlistfmt[gid_fmtlist(gidlistfmt, tab, n)] = 0 ; + break ; + } + case 'U' : + envug = l.arg ; + newargc += 3 ; + if (envug[0] == ':') { flags |= 4096 ; envug++ ; newargc++ ; } else flags &= ~4096 ; + if (strchr(envug, ':')) { flags |= 8192 ; newargc++ ; } else flags &= ~8192 ; + break ; + case 'e' : + if (!genalloc_append(char const *, &envdirs, &l.arg)) dienomem() ; + newargc += 3 ; + break ; + case '/' : + newroot.len = 0 ; + if (sarealpath(&newroot, l.arg) < 0 || !stralloc_0(&newroot)) dienomem() ; + newargc += 2 ; + break ; + case 'n' : + if (!int0_scan(l.arg, &niceval)) dieusage() ; + newargc += 3 ; + break ; + case 'l' : lockfile = l.arg ; flags &= ~16 ; newargc += 4 ; break ; + case 'L' : lockfile = l.arg ; flags |= 16 ; newargc += 4 ; break ; + case 'm' : + case 'd' : + case 'o' : + case 'p' : + case 'f' : + case 'c' : + { + uint64_t val ; + size_t pos = byte_chr("mdopfc", 6, opt) ; + if (!uint640_scan(l.arg, &val)) dieusage() ; + valfmt[pos][uint64_fmt(valfmt[pos], val)] = 0 ; + flags |= 32 | (1 << (6 + pos)) ; + newargc += 2 ; + break ; + } + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + } + + if (flags & 32) newargc += 2 ; + newargc += argc ; + + { + unsigned int m = 0 ; + char const *newargv[newargc + 1] ; + + if (niceval) + { + nicefmt[int_fmt(nicefmt, niceval)] = 0 ; + newargv[m++] = "nice" ; + newargv[m++] = "-n" ; + newargv[m++] = nicefmt ; + newargv[m++] = "--" ; + } + + if (flags & 8) + { + newargv[m++] = S6_EXTBINPREFIX "s6-setsid" ; + newargv[m++] = "--" ; + } + + if (genalloc_len(char const *, &envdirs)) + { + for (size_t i = 0 ; i < genalloc_len(char const *, &envdirs) ; i++) + { + newargv[m++] = S6_EXTBINPREFIX "s6-envdir" ; + newargv[m++] = "--" ; + newargv[m++] = genalloc_s(char const *, &envdirs)[i] ; + } + } + + if (lockfile) + { + newargv[m++] = S6_EXTBINPREFIX "s6-setlock" ; + newargv[m++] = flags & 16 ? "-n" : "-N" ; + newargv[m++] = "--" ; + newargv[m++] = lockfile ; + } + + if (flags & 16384) + { + newargv[m++] = S6_EXTBINPREFIX "s6-applyuidgid" ; + newargv[m++] = "-u" ; + newargv[m++] = uidfmt ; + if (flags & 32768) + { + newargv[m++] = "-g" ; + newargv[m++] = gidfmt ; + } + newargv[m++] = "-G" ; + newargv[m++] = gidlistfmt ; + newargv[m++] = "--" ; + } + + if (envug) + { + newargv[m++] = S6_EXTBINPREFIX "s6-envuidgid" ; + if (flags & 4096) newargv[m++] = "-n" ; + if (flags & 8192) newargv[m++] = "-B" ; + newargv[m++] = "--" ; + newargv[m++] = envug ; + } + + if (flags & 32) + { + newargv[m++] = S6_EXTBINPREFIX "s6-softlimit" ; + for (unsigned int i = 0 ; i < 6 ; i++) if (flags & (1 << (i + 6))) + { + newargv[m++] = valopt[i] ; + newargv[m++] = valfmt[i] ; + } + newargv[m++] = "--" ; + } + + if (flags & 1) + { + newargv[m++] = EXECLINE_EXTBINPREFIX "fdclose" ; + newargv[m++] = "0" ; + } + + if (flags & 2) + { + newargv[m++] = EXECLINE_EXTBINPREFIX "fdclose" ; + newargv[m++] = "1" ; + } + + if (flags & 4) + { + newargv[m++] = EXECLINE_EXTBINPREFIX "fdclose" ; + newargv[m++] = "2" ; + } + + if (argv0) + { + newargv[m++] = EXECLINE_BINPREFIX "exec" ; + newargv[m++] = "-a" ; + newargv[m++] = argv0 ; + newargv[m++] = "--" ; + } + + if (newroot.s) + { + newargv[m++] = "chroot" ; + newargv[m++] = newroot.s ; + if (argv0) strerr_warnw1x("the -b option is ineffective when the -/ option is also given") ; + } + + for (int i = 0 ; i < argc+1 ; i++) newargv[m++] = argv[i] ; + if (verbosity) printit(newargv) ; + xpathexec0_run(newargv, envp) ; + } +} diff --git a/src/alias/s6-frontend-alias-sv.c b/src/alias/s6-frontend-alias-sv.c new file mode 100644 index 0000000..e6e0ec8 --- /dev/null +++ b/src/alias/s6-frontend-alias-sv.c @@ -0,0 +1,377 @@ + /* ISC license. */ + +#include <stdint.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/wait.h> + +#include <skalibs/uint32.h> +#include <skalibs/sgetopt.h> +#include <skalibs/strerr2.h> +#include <skalibs/djbunix.h> + +#include <s6/config.h> +#include <s6/s6-supervise.h> + +#define USAGE "s6-frontend-alias-sv [ -v ] [ -w sec ] command services..." +#define dieusage() strerr_dieusage(100, USAGE) +#define dienomem() strerr_diefu1sys(111, "stralloc_catb") + +typedef int execfunc_t (char const *, char const *const *) ; +typedef execfunc_t *execfunc_t_ref ; + +typedef struct info_s info_t, *info_t_ref ; +struct info_s +{ + char const *name ; + execfunc_t_ref f ; +} ; + +static int dowait = 0 ; +static uint32_t secs = 7 ; + +static void warnnolog (void) +{ + strerr_warnw1x("s6-svc only sends commands to a single service, even if it has a dedicated logger") ; +} + +static void warnnokill (void) +{ + strerr_warnw1x("s6-supervise pilots a kill signal via the timeout-kill file in the service directory") ; +} + +static int info_cmp (void const *a, void const *b) +{ + char const *name = a ; + info_t const *info = b ; + return strcmp(name, info->name) ; +} + +static int spawnit (char const *const *argv, char const *const *envp) +{ + int wstat ; + pid_t r ; + pid_t pid = child_spawn0(argv[0], argv, envp) ; + if (!pid) + { + strerr_warnwu2sys("spawn ", argv[0]) ; + return 1 ; + } + r = wait_pid(pid, &wstat) ; + if (r != pid) + { + strerr_warnwu2sys("wait for ", argv[0]) ; + return 1 ; + } + return !!WIFSIGNALED(wstat) || !!WEXITSTATUS(wstat) ; +} + +static int simple_svc (char const *dir, char const *options, char const *const *envp) +{ + char const *argv[5] = { S6_EXTBINPREFIX "s6-svc", options, "--", dir, 0 } ; + return spawnit(argv, envp) ; +} + +static int complex_svc (char const *dir, char const *order, char waitfor, char const *const *envp) +{ + char warg[4] = "-w?" ; + char fmt[2 + UINT32_FMT] = "-T" ; + char const *argv[7] = { S6_EXTBINPREFIX "s6-svc", warg, fmt, order, "--", dir, 0 } ; + fmt[2 + uint32_fmt(fmt + 2, 1000 * secs)] = 0 ; + warg[2] = waitfor ; + return spawnit(argv, envp) ; +} + +static int status (char const *dir, char const *const *envp) +{ + char const *argv[4] = { S6_EXTBINPREFIX "s6-svstat", "--", dir, 0 } ; + return spawnit(argv, envp) ; +} + +static int usr1_h (char const *dir, char const *const *envp) +{ + return simple_svc(dir, "-1", envp) ; +} + +static int usr2_h (char const *dir, char const *const *envp) +{ + return simple_svc(dir, "-2", envp) ; +} + +static int alarm_h (char const *dir, char const *const *envp) +{ + return simple_svc(dir, "-a", envp) ; +} + +static int cont_h (char const *dir, char const *const *envp) +{ + if (dowait) + { + complex_svc(dir, "-o", 'U', envp) ; + return status(dir, envp) ; + } + else return simple_svc(dir, "-c", envp) ; +} + +static int down (char const *dir, char const *const *envp) +{ + if (dowait) + { + complex_svc(dir, "-d", 'D', envp) ; + return status(dir, envp) ; + } + else return simple_svc(dir, "-d", envp) ; +} + +static int bail (char const *dir, char const *const *envp) +{ + warnnolog() ; + if (dowait) + { + complex_svc(dir, "-d", 'D', envp) ; + status(dir, envp) ; + } + return simple_svc(dir, "-xd", envp) ; +} + +static int hup_h (char const *dir, char const *const *envp) +{ + return simple_svc(dir, "-h", envp) ; +} + +static int int_h (char const *dir, char const *const *envp) +{ + return simple_svc(dir, "-i", envp) ; +} + +static int kill_h (char const *dir, char const *const *envp) +{ + return simple_svc(dir, "-k", envp) ; +} + +static int once (char const *dir, char const *const *envp) +{ + if (dowait) + { + complex_svc(dir, "-o", 'U', envp) ; + return status(dir, envp) ; + } + else return simple_svc(dir, "-o", envp) ; +} + +static int pause_h (char const *dir, char const *const *envp) +{ + return simple_svc(dir, "-p", envp) ; +} + +static int quit_h (char const *dir, char const *const *envp) +{ + return simple_svc(dir, "-q", envp) ; +} + +static int term_h (char const *dir, char const *const *envp) +{ + if (dowait) + { + complex_svc(dir, "-r", 'R', envp) ; + return status(dir, envp) ; + } + else return simple_svc(dir, "-t", envp) ; +} + +static int up (char const *dir, char const *const *envp) +{ + if (dowait) + { + complex_svc(dir, "-u", 'U', envp) ; + return status(dir, envp) ; + } + else return simple_svc(dir, "-u", envp) ; +} + +static int check (char const *dir, char const *const *envp) +{ + s6_svstatus_t svst ; + char warg[3] = "-?" ; + char fmt[2 + UINT32_FMT] = "-t" ; + char const *argv[6] = { S6_EXTBINPREFIX "s6-svwait", warg, fmt, "--", dir, 0 } ; + fmt[2 + uint32_fmt(fmt + 2, 1000 * secs)] = 0 ; + if (!s6_svstatus_read(dir, &svst)) return 1 ; + warg[1] = svst.flagwantup ? 'U' : 'D' ; + spawnit(argv, envp) ; + return status(dir, envp) ; +} + +static int lsb_reload (char const *dir, char const *const *envp) +{ + hup_h(dir, envp) ; + return status(dir, envp) ; +} + +static int lsb_restart (char const *dir, char const *const *envp) +{ + complex_svc(dir, "-ru", 'U', envp) ; + return status(dir, envp) ; +} + +static int lsb_start (char const *dir, char const *const *envp) +{ + complex_svc(dir, "-u", 'U', envp) ; + return status(dir, envp) ; +} + +static int lsb_stop (char const *dir, char const *const *envp) +{ + complex_svc(dir, "-d", 'D', envp) ; + return status(dir, envp) ; +} + +static int lsb_shutdown (char const *dir, char const *const *envp) +{ + warnnolog() ; + complex_svc(dir, "-d", 'D', envp) ; + status(dir, envp) ; + return simple_svc(dir, "-x", envp) ; +} + +static int lsb_forcereload (char const *dir, char const *const *envp) +{ + warnnokill() ; + return lsb_reload(dir, envp) ; +} + +static int lsb_forcerestart (char const *dir, char const *const *envp) +{ + warnnokill() ; + return lsb_restart(dir, envp) ; +} + +static int lsb_forcestop (char const *dir, char const *const *envp) +{ + warnnokill() ; + return lsb_stop(dir, envp) ; +} + +static int lsb_forceshutdown (char const *dir, char const *const *envp) +{ + warnnokill() ; + return lsb_shutdown(dir, envp) ; +} + +static int lsb_tryrestart (char const *dir, char const *const *envp) +{ + s6_svstatus_t svst ; + if (s6_svstatus_read(dir, &svst) && svst.flagwantup && svst.pid && !svst.flagfinishing) + complex_svc(dir, "-r", 'U', envp) ; + return status(dir, envp) ; +} + +static info_t const commands[] = +{ + { .name = "1", .f = &usr1_h }, + { .name = "2", .f = &usr2_h }, + { .name = "a", .f = &alarm_h }, + { .name = "alarm", .f = &alarm_h }, + { .name = "c", .f = &cont_h }, + { .name = "check", .f = &check }, + { .name = "cont", .f = &cont_h }, + { .name = "d", .f = &down }, + { .name = "down", .f = &down }, + { .name = "e", .f = &bail }, + { .name = "exit", .f = &bail }, + { .name = "force-reload", .f = &lsb_forcereload }, + { .name = "force-restart", .f = &lsb_forcerestart }, + { .name = "force-shutdown", .f = &lsb_forceshutdown }, + { .name = "force-stop", .f = &lsb_forcestop }, + { .name = "h", .f = &hup_h }, + { .name = "hup", .f = &hup_h }, + { .name = "i", .f = &int_h }, + { .name = "interrupt", .f = &int_h }, + { .name = "k", .f = &kill_h }, + { .name = "kill", .f = &kill_h }, + { .name = "o", .f = &once }, + { .name = "once", .f = &once }, + { .name = "p", .f = &pause_h }, + { .name = "pause", .f = &pause_h }, + { .name = "q", .f = &quit_h }, + { .name = "quit", .f = &quit_h }, + { .name = "reload", .f = &lsb_reload }, + { .name = "restart", .f = &lsb_restart }, + { .name = "s", .f = &status }, + { .name = "shutdown", .f = &lsb_shutdown }, + { .name = "start", .f = &lsb_start }, + { .name = "status", .f = &status }, + { .name = "stop", .f = &lsb_stop }, + { .name = "t", .f = &term_h }, + { .name = "term", .f = &term_h }, + { .name = "try-restart", .f = &lsb_tryrestart }, + { .name = "u", .f = &up }, + { .name = "up", .f = &up } +} ; + +int main (int argc, char const *const *argv, char const *const *envp) +{ + int e = 0 ; + info_t *p ; + char const *x = getenv("SVWAIT") ; + char const *scandir = getenv("SVDIR") ; + size_t scandirlen ; + PROG = "s6-frontend-alias-sv" ; + if (!scandir) scandir = "/run/service" ; /* TODO: infer from s6li config */ + scandirlen = strlen(scandir) ; + if (x) + { + if (!uint320_scan(x, &secs)) + strerr_warnw1x("invalid SVWAIT value") ; + } + + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "vw:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'v' : dowait = 1 ; break ; + case 'w' : if (!uint320_scan(l.arg, &secs)) dieusage() ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + } + + if (argc < 2) dieusage() ; + p = bsearch(argv[0], commands, sizeof(commands) / sizeof(info_t), sizeof(info_t), &info_cmp) ; + if (!p) strerr_dief2x(100, "unknown command: ", argv[0]) ; + + for (argv++ ; *argv ; argv++) + { + if ((argv[0][0] == '.' && (argv[0][1] == '/' || (argv[0][1] == '.' && argv[0][2] == '/'))) || argv[0][0] == '/') + e += (*p->f)(*argv, envp) ; + else + { + int what = 1 ; + struct stat st ; + size_t len = strlen(*argv) ; + char fn[scandirlen + len + 2] ; + memcpy(fn, scandir, scandirlen) ; + fn[scandirlen] = '/' ; + memcpy(fn + scandirlen + 1, *argv, len + 1) ; + if (stat(fn, &st) < 0) /* XXX: TOCTOU but we don't care */ + { + if (errno != ENOENT) + { + e++ ; + what = 0 ; + strerr_warnwu2sys("stat ", fn) ; + } + } + else if (S_ISDIR(st.st_mode)) what = 2 ; + if (what) e += (*p->f)(what > 1 ? fn : *argv, envp) ; + } + } + return e ; +} diff --git a/src/alias/s6-frontend-alias.c b/src/alias/s6-frontend-alias.c new file mode 100644 index 0000000..7467632 --- /dev/null +++ b/src/alias/s6-frontend-alias.c @@ -0,0 +1,235 @@ + /* ISC license. */ + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#include <skalibs/buffer.h> +#include <skalibs/sgetopt.h> +#include <skalibs/strerr2.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/skamisc.h> + +#include <s6/config.h> + +#include <s6-frontend/config.h> + +#define USAGE "s6-frontend-alias [ -v ] cmdname options..." +#define dienomem() strerr_diefu1sys(111, "stralloc_catb") +#define dieusage() strerr_dieusage(100, USAGE) + +static unsigned int verbosity = 0 ; + +typedef void execfunc_t (int, char const *const *, char const *const *) ; +typedef execfunc_t *execfunc_t_ref ; + +typedef struct info_s info_t, *info_t_ref ; +struct info_s +{ + char const *name ; + char const *cmd ; + execfunc_t_ref f ; +} ; + +static int info_cmp (void const *a, void const *b) +{ + char const *name = a ; + info_t const *info = b ; + return strcmp(name, info->name) ; +} + +#if defined(S6_FRONTEND_WRAP_DAEMONTOOLS) || defined (S6_FRONTEND_WRAP_RUNIT) +static void noboot (char const *name) +{ + strerr_dief3x(100, "s6 does not provide a ", name, " emulation. To boot on a s6 supervision tree, please consider the s6-linux-init package.") ; +} +#endif + +#ifdef S6_FRONTEND_WRAP_DAEMONTOOLS + +static void readproctitle (int argc, char const *const *argv, char const *const *envp) +{ + (void)argc ; + (void)argv ; + (void)envp ; + noboot("readproctitle") ; +} + +static void svscanboot (int argc, char const *const *argv, char const *const *envp) +{ + (void)argc ; + (void)argv ; + (void)envp ; + noboot("svscanboot") ; +} + +#endif + +#ifdef S6_FRONTEND_WRAP_RUNIT + +static void runit (int argc, char const *const *argv, char const *const *envp) +{ + (void)argc ; + (void)argv ; + (void)envp ; + noboot("runit") ; +} + +static void runit_init (int argc, char const *const *argv, char const *const *envp) +{ + (void)argc ; + (void)argv ; + (void)envp ; + noboot("runit-init") ; +} + +static void runsvchdir (int argc, char const *const *argv, char const *const *envp) +{ + (void)argc ; + (void)argv ; + (void)envp ; + strerr_dief1x(100, "s6 does not provide a runsvchdir emulation. To handle several different sets of services, please consider the s6-rc package.") ; +} + +static void runsvdir (int argc, char const *const *argv, char const *const *envp) +{ + char const *newargv[4] = { S6_EXTBINPREFIX "s6-svscan", "-St14000", 0, 0 } ; + int dosetsid = 0 ; + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "P", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'P' : dosetsid = 1 ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + if (dosetsid) + strerr_warnw1x("-P option ignored: s6-svscan does not run its supervisor processes (s6-supervise) in a new session. However, by default, it runs every service in a new session.") ; + if (argc >= 2) + strerr_warnw1x("s6-svscan does not support logging to a readproctitle process. To log the output of your supervision tree, please consider using the s6-linux-init package.") ; + newargv[2] = argv[0] ; + if (verbosity) + { + buffer_puts(buffer_2, PROG) ; + buffer_puts(buffer_2, ": info: executing command line:") ; + for (char const *const *p = argv ; *p ; p++) + { + buffer_puts(buffer_2, " ") ; + buffer_puts(buffer_2, *p) ; + } + buffer_putsflush(buffer_2, "\n") ; + } + xpathexec_run(newargv[0], newargv, envp) ; +} + +static void svlogd (int argc, char const *const *argv, char const *const *envp) +{ + (void)argc ; + (void)argv ; + (void)envp ; + strerr_dief1x(100, "the s6-log program is similar to svlogd, but uses a different filtering syntax and does not use a config file in the logdir. Please see https://skarnet.org/software/s6/s6-log.html") ; +} + +static void utmpset (int argc, char const *const *argv, char const *const *envp) +{ + (void)argc ; + (void)argv ; + (void)envp ; + strerr_dief1x(100, "s6 does not provide a utmpset emulation. To handle utmp records, please consider the s6-linux-init package, along with the utmps package if necessary.") ; +} + +#endif + +static info_t const aliases[] = +{ +#ifdef S6_FRONTEND_WRAP_RUNIT + { .name = "chpst", .cmd = S6_FRONTEND_BINPREFIX "s6-frontend-alias-chpst", .f = 0 }, +#endif +#ifdef S6_FRONTEND_WRAP_DAEMONTOOLS + { .name = "envdir", .cmd = S6_EXTBINPREFIX "s6-envdir", .f = 0 }, + { .name = "envuidgid", .cmd = S6_EXTBINPREFIX "s6-envuidgid", .f = 0 }, + { .name = "fghack", .cmd = S6_EXTBINPREFIX "s6-fghack", .f = 0 }, + { .name = "multilog", .cmd = S6_EXTBINPREFIX "s6-log", .f = 0 }, + { .name = "pgrphack", .cmd = S6_EXTBINPREFIX "s6-setsid", .f = 0 }, + { .name = "readproctitle", .cmd = 0, .f = &readproctitle }, +#endif +#ifdef S6_FRONTEND_WRAP_RUNIT + { .name = "runit", .cmd = 0, .f = &runit }, + { .name = "runit-init", .cmd = 0, .f = &runit_init }, + { .name = "runsv", .cmd = S6_EXTBINPREFIX "s6-supervise", .f = 0 }, + { .name = "runsvchdir", .cmd = 0, .f = &runsvchdir }, + { .name = "runsvdir", .cmd = 0, .f = &runsvdir }, +#endif +#ifdef S6_FRONTEND_WRAP_DAEMONTOOLS + { .name = "setlock", .cmd = S6_EXTBINPREFIX "s6-setlock", .f = 0 }, + { .name = "setuidgid", .cmd = S6_EXTBINPREFIX "s6-setuidgid", .f = 0 }, + { .name = "softlimit", .cmd = S6_EXTBINPREFIX "s6-softlimit", .f = 0 }, + { .name = "supervise", .cmd = S6_EXTBINPREFIX "s6-supervise", .f = 0 }, +#endif +#ifdef S6_FRONTEND_WRAP_RUNIT + { .name = "sv", .cmd = S6_FRONTEND_BINPREFIX "s6-frontend-alias-sv", .f = 0 }, +#endif +#ifdef S6_FRONTEND_WRAP_DAEMONTOOLS + { .name = "svc", .cmd = S6_EXTBINPREFIX "s6-svc", .f = 0 }, +#endif +#ifdef S6_FRONTEND_WRAP_RUNIT + { .name = "svlogd", .cmd = 0, .f = &svlogd }, +#endif +#ifdef S6_FRONTEND_WRAP_DAEMONTOOLS + { .name = "svok", .cmd = S6_EXTBINPREFIX "s6-svok", .f = 0 }, + { .name = "svscan", .cmd = S6_EXTBINPREFIX "s6-svscan", .f = 0 }, + { .name = "svscanboot", .cmd = 0, .f = &svscanboot }, + { .name = "svstat", .cmd = S6_EXTBINPREFIX "s6-svstat", .f = 0 }, + { .name = "tai64n", .cmd = S6_EXTBINPREFIX "s6-tai64n", .f = 0 }, + { .name = "tai64nlocal", .cmd = S6_EXTBINPREFIX "s6-tai64nlocal", .f = 0 }, +#endif +#ifdef S6_FRONTEND_WRAP_RUNIT + { .name = "utmpset", .cmd = 0, .f = &utmpset }, +#endif +} ; + +int main (int argc, char const **argv, char const *const *envp) +{ + char const *name = argv[0] ; + stralloc sa = STRALLOC_ZERO ; + info_t *p ; + PROG = "s6-frontend-alias" ; + + if (!sabasename(&sa, name, strlen(name)) || !stralloc_0(&sa)) dienomem() ; + if (!strcmp(sa.s, PROG)) + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "v", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'v' : verbosity++ ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + if (!argc) dieusage() ; + name = *argv ; + stralloc_free(&sa) ; + } + else name = sa.s ; + + p = bsearch(name, aliases, sizeof(aliases) / sizeof(info_t), sizeof(info_t), &info_cmp) ; + if (!p) strerr_dief2x(100, "unknown alias: ", name) ; + if (p->cmd) + { + argv[0] = p->cmd ; + if (verbosity) + strerr_warni4x("the s6 version of ", name, " is ", p->cmd) ; + xpathexec_run(argv[0], argv, envp) ; + } + else (*p->f)(argc, argv, envp) ; + strerr_dief1x(101, "can't happen: incorrect alias handler. Please submit a bug-report.") ; +} diff --git a/src/config/deps-exe/s6-frontend-config-preprocess b/src/config/deps-exe/s6-frontend-config-preprocess new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/config/deps-exe/s6-frontend-config-preprocess @@ -0,0 +1 @@ +-lskarnet diff --git a/src/config/s6-frontend-config-preprocess.c b/src/config/s6-frontend-config-preprocess.c new file mode 100644 index 0000000..db09e24 --- /dev/null +++ b/src/config/s6-frontend-config-preprocess.c @@ -0,0 +1,286 @@ +/* ISC license. */ + +#include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> + +#include <skalibs/uint64.h> +#include <skalibs/sgetopt.h> +#include <skalibs/buffer.h> +#include <skalibs/strerr2.h> +#include <skalibs/stralloc.h> +#include <skalibs/genalloc.h> +#include <skalibs/direntry.h> +#include <skalibs/djbunix.h> +#include <skalibs/skamisc.h> +#include <skalibs/avltree.h> + +#define USAGE "s6-frontend-config-preprocess file" +#define dieusage() strerr_dieusage(100, USAGE) +#define dienomem() strerr_diefu1sys(111, "stralloc_catb") ; +#define MAXDEPTH 100 + +static stralloc sa = STRALLOC_ZERO ; +static unsigned int depth = 0 ; + + + /* Name storage */ + +static stralloc namesa = STRALLOC_ZERO ; + +static void *name_dtok (uint32_t pos, void *aux) +{ + (void)aux ; + return namesa.s + pos ; +} + +static int name_cmp (void const *a, void const *b, void *aux) +{ + (void)aux ; + return strcmp((char const *)a, (char const *)b) ; +} + +static avltree namemap = AVLTREE_INIT(8, 3, 8, &name_dtok, &name_cmp, 0) ; + + + /* Directory sorting */ + +static char *dname_cmp_base ; +static int dname_cmp (void const *a, void const *b) +{ + return strcmp(dname_cmp_base + *(size_t *)a, dname_cmp_base + *(size_t *)b) ; +} + + + /* Recursive inclusion functions */ + +static int includefromhere (char const *, int) ; + +static inline void includecwd (int once) +{ + genalloc ga = GENALLOC_ZERO ; /* size_t */ + DIR *dir ; + size_t sabase = sa.len ; + if (sagetcwd(&sa) < 0 || !stralloc_0(&sa)) dienomem() ; + dir = opendir(".") ; + if (!dir) strerr_diefu2sys(111, "opendir ", sa.s + sabase) ; + + for (;;) + { + direntry *d ; + errno = 0 ; + d = readdir(dir) ; + if (!d) break ; + if (d->d_name[0] == '.') continue ; + if (!genalloc_catb(size_t, &ga, &sa.len, 1)) break ; + if (!stralloc_catb(&sa, d->d_name, strlen(d->d_name)+1)) break ; + } + dir_close(dir) ; + if (errno) strerr_diefu2sys(111, "readdir ", sa.s + sabase) ; + + dname_cmp_base = sa.s ; + qsort(genalloc_s(size_t, &ga), genalloc_len(size_t, &ga), sizeof(size_t), &dname_cmp) ; + + for (size_t i = 0 ; i < genalloc_len(size_t, &ga) ; i++) + if (!includefromhere(sa.s + genalloc_s(size_t, &ga)[i], once)) + strerr_dief4sys(1, "in ", sa.s + sabase, ": unable to include ", sa.s + genalloc_s(size_t, &ga)[i]) ; + + genalloc_free(size_t, &ga) ; + sa.len = sabase ; +} + +static int include (char const *file, int once) +{ + size_t sabase = sa.len ; + size_t filelen = strlen(file) ; + if (!sadirname(&sa, file, filelen) || !stralloc_0(&sa)) dienomem() ; + if (chdir(sa.s + sabase) < 0) return 0 ; + sa.len = sabase ; + if (!sabasename(&sa, file, filelen)) dienomem() ; + { + char fn[sa.len + 1 - sabase] ; + memcpy(fn, sa.s + sabase, sa.len - sabase) ; + fn[sa.len - sabase] = 0 ; + sa.len = sabase ; + return includefromhere(fn, once) ; + } +} + +static inline int idcmd (char const *s) +{ + static char const *commands[] = + { + "include", + "includeonce", + "includedir", + "includedironce", + 0 + } ; + for (char const **p = commands ; *p ; p++) + if (!strcmp(s, *p)) return p - commands ; + return -1 ; +} + +static inline unsigned char cclass (char c) +{ + static unsigned char const classtable[34] = "0444444443144344444444444444444432" ; + return (unsigned char)c < 34 ? classtable[(unsigned char)c] - '0' : 4 ; +} + +static int includefromhere (char const *file, int once) +{ + size_t sabase = sa.len ; + if (sarealpath(&sa, file) < 0 || !stralloc_0(&sa)) return 0 ; + + if (once) + { + uint32_t dummy ; + if (avltree_search(&namemap, sa.s + sabase, &dummy)) goto end ; + { + size_t cur = namesa.len ; + size_t filelen = strlen(file) ; + if (cur + filelen + 2 < cur || cur + filelen + 2 > UINT32_MAX) + strerr_dief3x(3, "in ", sa.s + sabase, ": too much nesting") ; + if (!stralloc_catb(&namesa, sa.s + sabase, sa.len - sabase)) dienomem() ; + if (!avltree_insert(&namemap, cur)) dienomem() ; + } + } + + if (depth++ > MAXDEPTH) + strerr_dief3x(3, "in ", sa.s + sabase, ": too much nesting") ; + + { + static unsigned char const table[8][5] = + { + { 0x08, 0x10, 0x02, 0x10, 0x10 }, + { 0x08, 0x10, 0x11, 0x11, 0x11 }, + { 0x08, 0x00, 0x03, 0x04, 0x25 }, + { 0x08, 0x00, 0x03, 0x03, 0x03 }, + { 0x09, 0x09, 0x09, 0x04, 0x25 }, + { 0x09, 0x09, 0x09, 0x46, 0x25 }, + { 0x0a, 0x0a, 0x07, 0x06, 0x27 }, + { 0x88, 0x80, 0x27, 0x27, 0x27 } + } ; + stralloc localsa = STRALLOC_ZERO ; + uint64_t line = 1 ; + size_t sacur = sa.len ; + int cmd = -1 ; + buffer b ; + char buf[4096] ; + unsigned char state = 0 ; + int fd = open_readb(file) ; + if (fd < 0) strerr_diefu2sys(111, "open ", sa.s + sabase) ; + buffer_init(&b, &buffer_read, fd, buf, 4096) ; + + if (buffer_put(buffer_1, "! 0 ", 4) < 4 + || buffer_put(buffer_1, sa.s + sabase, sacur - 1 - sabase) < sacur - 1 - sabase + || buffer_put(buffer_1, "\n", 1) < 1) + strerr_diefu1sys(111, "write to stdout") ; + + while (state < 8) + { + uint16_t what ; + char c = 0 ; + if (buffer_get(&b, &c, 1) < 0) + strerr_diefu2sys(111, "read from ", sa.s + sabase) ; + what = table[state][cclass((unsigned char)c)] ; + state = what & 0x000f ; + if (what & 0x0010) + if (buffer_put(buffer_1, &c, 1) < 1) + strerr_diefu1sys(111, "write to stdout") ; + if (what & 0x0020) + if (!stralloc_catb(&localsa, &c, 1)) dienomem() ; + if (what & 0x0040) + { + if (!stralloc_0(&localsa)) dienomem() ; + cmd = idcmd(localsa.s) ; + if (cmd < 0) + { + char fmt[UINT64_FMT] ; + fmt[uint64_fmt(fmt, line)] = 0 ; + strerr_dief6x(2, "in ", sa.s + sabase, " line ", fmt, ": unrecognized directive: ", localsa.s) ; + } + localsa.len = 0 ; + } + if (what & 0x0080) + { + int fdhere = open(".", O_RDONLY | O_DIRECTORY) ; + if (fdhere < 0) + strerr_dief3sys(111, "in ", sa.s + sabase, ": unable to open base directory: ") ; + if (!stralloc_0(&localsa)) dienomem() ; + if (cmd & 2) + { + if (chdir(localsa.s) < 0) + { + char fmt[UINT64_FMT] ; + fmt[uint64_fmt(fmt, line)] = 0 ; + strerr_dief6sys(111, "in ", sa.s + sabase, " line ", fmt, ": unable to chdir to ", localsa.s) ; + } + includecwd(cmd & 1) ; + } + else if (!include(localsa.s, cmd & 1)) + { + char fmt[UINT64_FMT] ; + fmt[uint64_fmt(fmt, line)] = 0 ; + strerr_dief6sys(111, "in ", sa.s + sabase, " line ", fmt, ": unable to include ", localsa.s) ; + } + if (fchdir(fdhere) < 0) + strerr_dief3sys(111, "in ", sa.s + sabase, ": unable to fchdir back") ; + fd_close(fdhere) ; + localsa.len = 0 ; + { + char fmt[UINT64_FMT] ; + size_t fmtlen = uint64_fmt(fmt, line) ; + fmt[fmtlen++] = ' ' ; + if (buffer_put(buffer_1, "! ", 2) < 2 + || buffer_put(buffer_1, fmt, fmtlen) < fmtlen + || buffer_put(buffer_1, sa.s + sabase, sacur - 1 - sabase) < sacur - 1 - sabase + || buffer_put(buffer_1, "\n", 1) < 1) + strerr_diefu1sys(111, "write to stdout") ; + } + } + if (c == '\n' && state <= 8) line++ ; + } + if (state > 8) + { + char fmt[UINT64_FMT] ; + fmt[uint64_fmt(fmt, line)] = 0 ; + strerr_dief5x(2, "in ", sa.s + sabase, " line ", fmt, ": syntax error: invalid ! line") ; + } + fd_close(fd) ; + stralloc_free(&localsa) ; + } + + depth-- ; + end: + sa.len = sabase ; + return 1 ; +} + +int main (int argc, char const *const *argv, char const *const *envp) +{ + PROG = "s6-frontend-config-preprocess" ; + { + 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) dieusage() ; + + if (!include(argv[0], 1)) strerr_diefu2sys(1, "preprocess ", argv[0]) ; + if (!buffer_flush(buffer_1)) + strerr_diefu1sys(111, "write to stdout") ; + return 0 ; +} diff --git a/src/config/s6-frontend-config-preprocess.txt b/src/config/s6-frontend-config-preprocess.txt new file mode 100644 index 0000000..e81c86e --- /dev/null +++ b/src/config/s6-frontend-config-preprocess.txt @@ -0,0 +1,38 @@ + + Automaton for the preprocessor: + + +class | 0 1 2 3 4 +st\ev | \0 \n ! space other + +START | print print print +0 | END START CMD NORMAL NORMAL + +NORMAL | print print print print +1 | END START NORMAL NORMAL NORMAL + +CMD | add +2 | END START IGNORE CMD1 CMD2 + +IGNORE | +3 | END START IGNORE IGNORE IGNORE + +CMD1 | add +4 | X X X CMD1 CMD2 + +CMD2 | idcmd add +5 | X X X ARG CMD2 + +ARG | add +6 | X X ARG1 ARG ARG1 + +ARG1 | proc proc add add add +7 | END START ARG1 ARG1 ARG1 + +states: 0-7 plus END and X -> 4 bits +actions: 4. -> 8 bits total, fits in a char. + +print 0x10 copies the character to stdout +add 0x20 adds the character to the processing string +idcmd 0x40 ids the processing string for an !include cmd +proc 0x80 gets the filename and procs the include diff --git a/tools/gen-deps.sh b/tools/gen-deps.sh new file mode 100755 index 0000000..27e5b3e --- /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 -e ^-l -e '^\${.*_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 |