From f588272b8055c615df73094d77ceb179a1182219 Mon Sep 17 00:00:00 2001
From: Laurent Bercot
Date: Wed, 17 Jun 2015 10:06:12 +0000
Subject: Initial commit
---
.gitignore | 5 +
AUTHORS | 2 +
COPYING | 13 ++
INSTALL | 153 +++++++++++++
Makefile | 131 +++++++++++
README | 22 ++
configure | 409 ++++++++++++++++++++++++++++++++++
doc/index.html | 123 ++++++++++
doc/s6-linux-init-maker.html | 276 +++++++++++++++++++++++
doc/upgrade.html | 28 +++
package/deps-build | 5 +
package/deps.mak | 8 +
package/info | 4 +
package/modes | 1 +
package/targets.mak | 6 +
src/init/deps-exe/s6-linux-init-maker | 1 +
src/init/s6-linux-init-maker.c | 377 +++++++++++++++++++++++++++++++
tools/gen-deps.sh | 83 +++++++
tools/install.sh | 64 ++++++
19 files changed, 1711 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 100755 configure
create mode 100644 doc/index.html
create mode 100644 doc/s6-linux-init-maker.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 100644 src/init/deps-exe/s6-linux-init-maker
create mode 100644 src/init/s6-linux-init-maker.c
create mode 100755 tools/gen-deps.sh
create mode 100755 tools/install.sh
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5c6415e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*.o
+*.a
+*.lo
+*.so
+*.so.*
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..7a708a1
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,2 @@
+Main author:
+ Laurent Bercot
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..463bc49
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,13 @@
+Copyright (c) 2015 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..3f7504b
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,153 @@
+Build Instructions
+------------------
+
+* Requirements
+ ------------
+
+ - A Linux-based system with a standard C development environment
+ - GNU make version 4.0 or later
+ - skalibs version 2.3.5.1 or later: http://skarnet.org/software/skalibs/
+ - execline version 2.1.2.2 or later: http://skarnet.org/software/execline/
+ - s6-portable-utils version 2.0.5.0 or later: http://skarnet.org/software/s6-portable-utils/
+ - s6-linux-utils version 2.0.2.0 or later: http://skarnet.org/software/s6-linux-utils/
+ - s6 version 2.1.4.0 or later: http://skarnet.org/software/s6/
+
+ Note that all those are build-time dependencies, and they are
+*also* run-time dependencies when you use the init binary created
+by s6-linux-init-maker.
+
+ This software is Linux-specific. It will run on a Linux kernel,
+version 2.6.32 or later. However, it should not be too hard to port to
+other Unix-like operating systems.
+
+
+* Standard usage
+ --------------
+
+ ./configure && make && sudo make install
+
+ will work for most users.
+ It will install the s6-linux-init-maker binary in /sbin.
+
+ 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, the standard environment variables are recognized.
+
+ The value of the CROSS_COMPILE environment variable will prefix the
+building tools' names. The --enable-cross option is preferred, see
+"Cross-compilation" below.
+
+ If the CC environment variable is set, its value will override compiler
+detection by configure.
+
+ The values of CFLAGS, CPPFLAGS and LDFLAGS will be appended to flags
+auto-detected by configure. To entirely override the flags set by
+configure, use make -e.
+
+ The value of LDLIBS will be appended by make to command lines that link
+an executable, even without the -e option.
+
+ The Makefile supports the DESTDIR convention for staging.
+
+
+* 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 --enable-cross=PREFIX option to configure, or simply
+--enable-cross if your default toolchain is a cross-compiling
+toolchain. And make sure to use the correct version of skalibs
+for your target, and the correct sysdeps directory, making use
+of the --with-include, --with-lib, --with-dynlib and --with-sysdeps
+options as necessary.
+
+
+* The slashpackage convention
+ ---------------------------
+
+ The slashpackage convention (http://cr.yp.to/slashpackage.html)
+is a package installation scheme that provides a few guarantees
+over other conventions such as the FHS, for instance fixed
+absolute pathnames. skarnet.org packages support it: use the
+--enable-slashpackage option to configure, or
+--enable-slashpackage=DIR for a prefixed DIR/package tree.
+This option will activate slashpackage support during the build
+and set slashpackage-compatible installation directories.
+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.
+
+
+* 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..b861d25
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,131 @@
+#
+# This Makefile requires GNU make.
+#
+# Do not make changes here.
+# Use the included .mak files.
+#
+
+it: all
+
+CC = $(error Please use ./configure first)
+
+STATIC_LIBS :=
+SHARED_LIBS :=
+INTERNAL_LIBS :=
+EXTRA_TARGETS :=
+
+-include config.mak
+include package/targets.mak
+include package/deps.mak
+
+version_m := $(basename $(version))
+version_M := $(basename $(version_m))
+version_l := $(basename $(version_M))
+CPPFLAGS_ALL := -iquote src/include-local -Isrc/include $(CPPFLAGS)
+CFLAGS_ALL := $(CFLAGS) -pipe -Wall
+CFLAGS_SHARED := -fPIC
+LDFLAGS_ALL := $(LDFLAGS)
+LDFLAGS_SHARED := -shared
+LDLIBS_ALL := $(LDLIBS)
+REALCC = $(CROSS_COMPILE)$(CC)
+AR := $(CROSS_COMPILE)ar
+RANLIB := $(CROSS_COMPILE)ranlib
+STRIP := $(CROSS_COMPILE)strip
+INSTALL := ./tools/install.sh
+
+ALL_BINS := $(LIBEXEC_TARGETS) $(BIN_TARGETS) $(SBIN_TARGETS)
+ALL_LIBS := $(SHARED_LIBS) $(STATIC_LIBS) $(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 $(ALL_LIBS)),)
+ exec ${STRIP} -x -R .note -R .comment -R .note.GNU-stack $(ALL_LIBS)
+endif
+ifneq ($(strip $(ALL_BINS)),)
+ exec ${STRIP} -R .note -R .comment -R .note.GNU-stack $(ALL_BINS)
+endif
+
+install: install-dynlib install-libexec install-bin install-sbin install-lib install-include
+install-dynlib: $(SHARED_LIBS:lib%.so=$(DESTDIR)$(dynlibdir)/lib%.so)
+install-libexec: $(LIBEXEC_TARGETS:%=$(DESTDIR)$(libexecdir)/%)
+install-bin: $(BIN_TARGETS:%=$(DESTDIR)$(bindir)/%)
+install-sbin: $(SBIN_TARGETS:%=$(DESTDIR)$(sbindir)/%)
+install-lib: $(STATIC_LIBS:lib%.a=$(DESTDIR)$(libdir)/lib%.a)
+install-include: $(ALL_INCLUDES:src/include/$(package)/%.h=$(DESTDIR)$(includedir)/$(package)/%.h)
+install-data: $(ALL_DATA:src/etc/%=$(DESTDIR)$(datadir)/%)
+
+ifneq ($(exthome),)
+
+update:
+ exec $(INSTALL) -l $(notdir $(home)) $(DESTDIR)$(exthome)
+
+global-links: $(DESTDIR)$(exthome) $(SHARED_LIBS:lib%.so=$(DESTDIR)$(sproot)/library.so/lib%.so) $(BIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%) $(SBIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%)
+
+$(DESTDIR)$(sproot)/command/%: $(DESTDIR)$(home)/command/%
+ exec $(INSTALL) -D -l ..$(subst $(sproot),,$(exthome))/command/$(
+
+ Please use the mailing-list for
+questions about s6-linux-init.
diff --git a/configure b/configure
new file mode 100755
index 0000000..5244a37
--- /dev/null
+++ b/configure
@@ -0,0 +1,409 @@
+#!/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=$1
+}
+
+stripdir () {
+ while eval "fnmatch '*/' \"\${$1}\"" ; do
+ eval "$1=\${$1%/}"
+ done
+}
+
+tryflag () {
+ echo "checking whether compiler accepts $2 ..."
+ echo "typedef int x;" > "$tmpc"
+ if $CC_AUTO $CPPFLAGS_AUTO $CFLAGS_AUTO "$2" -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then
+ echo " ... yes"
+ eval "$1=\"\${$1} \$2\""
+ eval "$1=\${$1# }"
+ return 0
+ else
+ echo " ... no"
+ return 1
+ fi
+}
+
+tryldflag () {
+ echo "checking whether linker accepts $2 ..."
+ echo "typedef int x;" > "$tmpc"
+ if $CC_AUTO $CFLAGS_AUTO $LDFLAGS_AUTO -nostdlib "$2" -o /dev/null "$tmpc" >/dev/null 2>&1 ; then
+ echo " ... yes"
+ eval "$1=\"\${$1} \$2\""
+ eval "$1=\${$1# }"
+ return 0
+ else
+ echo " ... no"
+ return 1
+ fi
+}
+
+
+# Actual script
+
+CC_AUTO="$CC"
+CFLAGS_AUTO="$CFLAGS"
+CPPFLAGS_AUTO="-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -O2 $CPPFLAGS"
+LDFLAGS_AUTO="$LDFLAGS"
+LDFLAGS_NOSHARED=
+prefix=
+exec_prefix='$prefix'
+dynlibdir='$prefix/lib'
+libexecdir='$exec_prefix/libexec'
+bindir='$exec_prefix/bin'
+sbindir='$exec_prefix/sbin'
+libdir='$prefix/lib/$package'
+includedir='$prefix/include'
+datadir='$prefix/etc'
+sysdeps='$prefix/lib/skalibs/sysdeps'
+manualsysdeps=false
+shared=false
+static=true
+slashpackage=false
+sproot=
+home=
+exthome=
+allstatic=true
+evenmorestatic=false
+addincpath=''
+addlibspath=''
+addlibdpath=''
+vpaths=''
+vpathd=''
+cross="$CROSS_COMPILE"
+
+for arg ; do
+ case "$arg" in
+ --help) usage ;;
+ --prefix=*) prefix=${arg#*=} ;;
+ --exec-prefix=*) exec_prefix=${arg#*=} ;;
+ --dynlibdir=*) dynlibdir=${arg#*=} ;;
+ --libexecdir=*) libexecdir=${arg#*=} ;;
+ --bindir=*) bindir=${arg#*=} ;;
+ --sbindir=*) sbindir=${arg#*=} ;;
+ --libdir=*) libdir=${arg#*=} ;;
+ --includedir=*) includedir=${arg#*=} ;;
+ --datadir=*) datadir=${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-slashpackage=*) sproot=${arg#*=} ; slashpackage=true ; ;;
+ --enable-slashpackage) sproot= ; slashpackage=true ;;
+ --disable-slashpackage) sproot= ; slashpackage=false ;;
+ --enable-cross=*) cross=${arg#*=} ;;
+ --enable-cross) cross= ;;
+ --disable-cross) cross= ;;
+ --enable-*|--disable-*|--with-*|--without-*|--*dir=*|--build=*) ;;
+ --host=*|--target=*) target=${arg#*=} ;;
+ -* ) echo "$0: unknown option $arg" ;;
+ *=*) ;;
+ *) target=$arg ;;
+ esac
+done
+
+# 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 sbindir libdir includedir datadir sysdeps sproot skalibs ; do
+ eval tmp=\${$i}
+ eval $i=$tmp
+ stripdir $i
+done
+
+# Get usable temp filenames
+i=0
+set -C
+while : ; do
+ i=$(($i+1))
+ tmpc="./tmp-configure-$$-$PPID-$i.c"
+ tmpe="./tmp-configure-$$-$PPID-$i.tmp"
+ 2>|/dev/null > "$tmpc" && break
+ 2>|/dev/null > "$tmpe" && break
+ test "$i" -gt 50 && fail "$0: cannot create temporary files"
+done
+set +C
+trap 'rm -f "$tmpc" "$tmpe"' EXIT ABRT INT QUIT TERM HUP
+
+# Set slashpackage values
+if $slashpackage ; then
+ home=${sproot}/package/${category}/${package}-${version}
+ exthome=${sproot}/package/${category}/${package}
+ if $manualsysdeps ; then
+ :
+ else
+ sysdeps=${sproot}/package/prog/skalibs/sysdeps
+ fi
+ binprefix=${home}/command
+ extbinprefix=${exthome}/command
+ dynlibdir=${home}/library.so
+ libexecdir=$binprefix
+ bindir=$binprefix
+ sbindir=$binprefix
+ libdir=${home}/library
+ includedir=${home}/include
+ while read dep ; do
+ addincpath="$addincpath -I${sproot}${dep}/include"
+ vpaths="$vpaths ${sproot}${dep}/library"
+ addlibspath="$addlibspath -L${sproot}${dep}/library"
+ if $allstatic ; then : ; else
+ vpathd="$vpathd ${sproot}${dep}/library.so"
+ addlibdpath="$addlibdpath -L${sproot}${dep}/library.so"
+ fi
+ done < package/deps-build
+fi
+
+# Find a C compiler to use
+echo "checking for C compiler..."
+trycc ${cross}gcc
+trycc ${cross}c99
+trycc ${cross}cc
+test -n "$CC_AUTO" || { echo "$0: cannot find a C compiler" ; exit 1 ; }
+echo " ... $CC_AUTO"
+echo "checking whether C compiler works... "
+echo "typedef int x;" > "$tmpc"
+if $CC_AUTO $CPPFLAGS_AUTO $CFLAGS_AUTO -c -o /dev/null "$tmpc" 2>"$tmpe" ; then
+ echo " ... yes"
+else
+ echo " ... no. Compiler output follows:"
+ cat < "$tmpe"
+ exit 1
+fi
+
+echo "checking target system type..."
+test -n "$target" || target=$($CC_AUTO -dumpmachine 2>/dev/null) || target=unknown
+echo " ... $target"
+if test ! -d $sysdeps || test ! -f $sysdeps/target ; then
+ echo "$0: error: $sysdeps is not a valid sysdeps directory"
+ exit 1
+fi
+if [ "x$target" != "x$(cat $sysdeps/target)" ] ; then
+ echo "$0: error: target $target does not match the contents of $sysdeps/target"
+ exit 1
+fi
+
+rt_lib=$(cat $sysdeps/rt.lib)
+socket_lib=$(cat $sysdeps/socket.lib)
+sysclock_lib=$(cat $sysdeps/sysclock.lib)
+tainnow_lib=$(cat $sysdeps/tainnow.lib)
+util_lib=$(cat $sysdeps/util.lib)
+
+tryflag CFLAGS_AUTO -std=c99
+tryflag CFLAGS_AUTO -fomit-frame-pointer
+tryflag CFLAGS_AUTO -fno-exceptions
+tryflag CFLAGS_AUTO -fno-unwind-tables
+tryflag CFLAGS_AUTO -fno-asynchronous-unwind-tables
+tryflag CFLAGS_AUTO -Wa,--noexecstack
+tryflag CFLAGS_AUTO -fno-stack-protector
+tryflag CPPFLAGS_AUTO -Werror=implicit-function-declaration
+tryflag CPPFLAGS_AUTO -Werror=implicit-int
+tryflag CPPFLAGS_AUTO -Werror=pointer-sign
+tryflag CPPFLAGS_AUTO -Werror=pointer-arith
+
+if $evenmorestatic ; then
+ LDFLAGS_NOSHARED=-static
+fi
+
+if $shared ; then
+ tryldflag LDFLAGS_AUTO -Wl,--hash-style=both
+fi
+
+if test -z "$vpaths" ; then
+ while read dep ; do
+ base=$(basename $dep) ;
+ vpaths="$vpaths /usr/lib/$base"
+ addlibspath="$addlibspath -L/usr/lib/$base"
+ done < package/deps-build
+fi
+
+CPPFLAGS_AUTO="$CPPFLAGS_AUTO $addincpath"
+LDFLAGS_AUTO="$LDFLAGS_AUTO $addlibspath"
+$allstatic || LDFLAGS_AUTO="$LDFLAGS_AUTO $addlibdpath"
+
+echo "creating config.mak..."
+cmdline=$(quote "$0")
+for i ; do cmdline="$cmdline $(quote "$i")" ; done
+exec 3>&1 1>config.mak
+cat << EOF
+# This file was generated by:
+# $cmdline
+# Any changes made here will be lost if configure is re-run.
+
+target := $target
+package := $package
+prefix := $prefix
+exec_prefix := $exec_prefix
+dynlibdir := $dynlibdir
+libexecdir := $libexecdir
+bindir := $bindir
+sbindir := $sbindir
+libdir := $libdir
+includedir := $includedir
+datadir := $datadir
+sysdeps := $sysdeps
+slashpackage := $slashpackage
+sproot := $sproot
+version := $version
+home := $home
+exthome := $exthome
+RT_LIB := ${rt_lib}
+SOCKET_LIB := ${socket_lib}
+SYSCLOCK_LIB := ${sysclock_lib}
+TAINNOW_LIB := ${tainnow_lib}
+UTIL_LIB := ${util_lib}
+
+CC := $CC_AUTO
+CFLAGS := $CFLAGS_AUTO
+CPPFLAGS := $CPPFLAGS_AUTO
+LDFLAGS := $LDFLAGS_AUTO
+LDFLAGS_NOSHARED := $LDFLAGS_NOSHARED
+CROSS_COMPILE := $cross
+
+vpath lib%a$vpaths
+EOF
+if $allstatic ; then
+ echo ".LIBPATTERNS := lib%.a"
+ echo "DO_ALLSTATIC := 1"
+ vpathd=
+fi
+ echo "vpath lib%.so$vpathd"
+if $static ; then
+ echo "DO_STATIC := 1"
+else
+ echo "DO_STATIC :="
+fi
+if $shared ; then
+ echo "DO_SHARED := 1"
+else
+ echo "DO_SHARED :="
+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..fc7055d
--- /dev/null
+++ b/doc/index.html
@@ -0,0 +1,123 @@
+
+
+
+
+
+ s6-linux-init - tools for a Linux init system
+
+
+
+
+
+
+
+Software
+skarnet.org
+
+
+ s6-linux-init
+
+ What is it ?
+
+
+ s6-linux-init is a set of minimalistic tools to create and manage
+the init process on a Linux system - i.e. the first process created
+by the kernel at boot time.
+
+
+
+ s6-linux-init is meant to automate creation of scripts revolving
+around the use of other skarnet.org tools, especially s6, in order
+to provide a complete booting environment with integrated supervision
+and logging without having to hand-craft all the details.
+
+
+
+
+ Installation
+
+ Requirements
+
+
+ - A Linux-based system with a standard C development environment
+ - GNU make, version 4.0 or later
+ - skalibs version
+2.3.5.1 or later
+ - execline version
+2.1.2.2 or later
+ - s6-portable-utils version
+2.0.5.0 or later
+ - s6-linux-utils version
+2.0.2.0 or later
+ - s6 version
+2.1.4.0 or later
+
+
+
+When you build s6-linux-init, the
+ s6-linux-init-maker tool
+is created; then you run that tool to create an init script,
+and then you can boot your system on that init script.
+
+
+
+ The listed dependencies are all build-time dependencies and also
+boot-time dependencies, i.e. you need the tools installed to build
+s6-linux-init and to boot your system. There are no run-time
+dependencies, except skalibs if you linked against the shared version of
+the library.
+
+
+ Licensing
+
+
+ s6-linux-utils is free software. It is available under the
+ISC license.
+
+
+ Download
+
+
+
+ Compilation
+
+
+ - See the enclosed INSTALL file for installation details.
+
+
+ Upgrade notes
+
+
+ - This page lists the differences to be aware of between
+the previous versions of s6-linux-init and the current one.
+
+
+
+
+ Reference
+
+ Commands
+
+
+ All these commands exit 111 if they encounter a temporary error, and
+100 if they encounter a permanent error - such as a misuse.
+
+
+
+
+ Related resources
+
+
+ - s6-linux-init is discussed on the
+skaware mailing-list.
+
+
+
+
diff --git a/doc/s6-linux-init-maker.html b/doc/s6-linux-init-maker.html
new file mode 100644
index 0000000..3c27a2f
--- /dev/null
+++ b/doc/s6-linux-init-maker.html
@@ -0,0 +1,276 @@
+
+
+
+
+
+ s6-linux-init: the s6-linux-init-maker program
+
+
+
+
+
+
+
+s6-linux-init
+Software
+skarnet.org
+
+
+ The s6-linux-init-maker program
+
+
+s6-linux-init-maker reads configuration options on
+the command line, and outputs a directory to place in the
+root filesystem as well as a script suitable as an init program.
+
+
+
+ s6-linux-init-maker only writes scripts. At boot time, these
+scripts will call commands provided by other skarnet.org packages
+such as
+execline or
+s6. It is the
+responsibility of the administrator to make sure that all the
+dependencies are properly installed at boot time, and that the
+correct options have been given to s6-linux-init-maker so that
+the programs are found on the root filesystem of the
+machine - else the scripts will crash.
+
+
+
+
+ Interface and usage
+
+
+ s6-linux-init-maker \
+ [ -c basedir ] \
+ [ -l tmpfsdir ] \
+ [ -b execline_bindir ] \
+ [ -u log_user ] \
+ [ -g early_getty ] \
+ [ -2 stage2 ] \
+ [ -3 stage3 ] \
+ [ -p initial_path ] \
+ [ -m initial_umask ] \
+ [ -t timestamp_style ] \
+ [ -d dev_style ] \
+ [ -e initial_envvar ] ... \
+ dir > stage1
+
+
+
+ - s6-linux-init-maker should be run as root.
+ - s6-linux-init-maker parses options on its command line.
+ - It writes data into a directory dir, which must not
+exist beforehand.
+ - It then prints a script to its standard output.
+ - It exits 0 if everything went well, 100 if a user error occurred,
+and 111 if a problem occurred during the directory or script creation.
+
+
+
+ dir should then be copied by the administrator to the place
+declared as basedir. Be careful: it contains fifos, files with
+precise uid/gid permissions, and files with non-standard access rights,
+so be sure to copy it verbatim. The
+s6-hiercopy
+tool can do it, as well as the GNU or busybox cp -a command.
+
+
+
+ The stage1 script printed by s6-linux-init-maker on its
+stdout is then suitable as an init program. The administrator should
+copy it to /sbin/init and make it executable.
+
+
+ Boot sequence
+
+
+ When the kernel boots, it runs the stage1 script, and this is
+what happens:
+
+
+
+ - stage1 is an
+execline script, so
+the first process run by the kernel is the
+execlineb
+program launcher.
+ - stage1 mounts a
+tmpfs
+filesystem on tmpfsdir.
+ - stage1 copies basedir/run-image verbatim to
+tmpfsdir.
+ - stage1 reads a global set of environment variables from the
+basedir/env
+environment directory.
+ - stage1 forks a child that will block until
+s6-svscan is running.
+ - stage1 executes, as process 1, into
+s6-svscan,
+with tmpfsdir/service as a
+scan directory.
+ - This scan directory already contains at least one service, which is the
+catch-all logger: error messages from the supervision tree, and
+from services that do not have a dedicated logger, are handled by a
+special s6-log
+instance and made available in tmpfsdir/uncaught-logs
+instead of clogging the system console.
+ - If the -g option has been given to s6-linux-init-maker, the
+scan directory will also contain a service for an early getty.
+ - s6-svscan starts all the services defined in the scan directory,
+and unblocks the child forked by stage1.
+ - This child executes into stage2.
+
+
+
+ stage2 is the responsibility of the administrator - it will
+not be written automatically!
+It should
+contain all the necessary initialization sequence to bring up a proper
+system. When stage2 is executed, the machine state is as follows:
+
+
+
+ - stage2's working directory is / and its stdin
+is /dev/null. stage2's
+stdout and stderr both point to the pipe to the catch-all logger, so
+unless redirected, stage2's output will be logged into the
+tmpfsdir/uncaught-logs directory.
+ - The system has a valid device directory mounted on /dev.
+
- Depending on the kernel boot command line, the root filesystem
+may be in read-only mode.
+ - There is a tmpfs available for root only in tmpfsdir.
+ - s6-svscan
+is running as process 1. At any time, it is possible to make it supervise a long-lived
+process by linking the appropriate
+service directory
+into tmpfsdir/service, then running the command
+s6-svscanctl -a tmpfsdir/service. Services without a
+dedicated logger will send their output to the catch-all logger.
+ - A getty service may already be available. The point of this early
+getty is essentially to make it easier to debug if stage2 fails.
+
+
+
+ There is nothing else. In particular, no filesystem has been
+mounted yet, including /proc and /sys; and no one-time
+initialization
+has been performed. The point of stage1 is only to make it
+possible to run stage2 with a logging infrastructure and a
+supervision infrastructure already available, and all the
+real machine and service initialization should happen in stage2.
+
+
+ Shutdown sequence
+
+
+ When s6-svscan is told to exit via an appropriate
+s6-svscanctl
+command, it executes into the stage3 script, which, like
+stage2, is the responsibility of the administrator. stage3
+is run in the following state:
+
+
+
+ - It runs as process 1. (Doing so makes it easier to recover after
+killing all processes by kill -9 -1 or
+s6-nuke).
+ - Its working directory is / and its stdin is /dev/null
+ - Its stdout and stderr are both /dev/console
+ - Depending on the exact s6-svscanctl command that terminated s6-svscan,
+and what has happened before that command was sent, there may or may not be
+long-running services that remain alive. The catch-all logger and its
+supervisor will always be alive, which is not a problem because they
+do not hold any file descriptor to a filesystem that would need to be
+unmounted.
+
+
+ s6-linux-init-maker options
+
+
+ - -c basedir : at boot time, stage1
+will read its read-only data from basedir. After running
+s6-linux-init-maker, the administrator should make sure to copy the
+created directory dir to basedir. basedir
+must be absolute. Default is
+/etc/s6.
+
+ - -l tmpfsdir : at boot time, a tmpfs will
+be mounted on tmpfsdir. The directory should already exist in
+the root filesystem, and be empty. tmpfsdir must be absolute. Default is
+/run.
+
+ - -b execline_bindir : init is run by the kernel
+without a PATH, and since it is a script, it is necessary to tell it where
+to find the
+execlineb
+launcher and the first few early commands before PATH can be set.
+execline_bindir is the location where the execline binaries can be
+found. It must be absolute. Default is
+/bin.
+
+ - -u log_user : the catch-all
+logger will not run as root, but as log_user. Default is
+nobody.
+
+ - -g early_getty : if this option
+is set, s6-linux-init-maker will define a service that will run
+very early, before stage2 is executed. This early service
+should be a getty, to allow logins even if stage2 fails.
+early_getty should be a simple command line: for instance,
+"/sbin/getty 38400 tty1". By default, no early service
+is defined.
+
+ - -2 stage2 : stage2 is
+the location of the stage 2 script that will be run when the
+system has an operational supervision tree. It must be absolute. Default is
+/etc/rc.init.
+
+ - -3 stage3 : stage3 is
+the location of the stage 3 script that will be run at the end of
+the machine lifetime, when s6-svscan is told to terminate.
+It must be absolute. Default is
+/etc/rc.shutdown.
+
+ - -p initial_path : the value to
+set the PATH environment variable to, for all the starting processes.
+This will be done as early as possible in stage1. Default is
+the value that has been compiled in
+skalibs via the
+--with-default-path configure option, i.e. by default
+/usr/bin:/bin.
+
+ - -m initial_umask : the value of
+the initial file umask for all the starting processes, in octal.
+Default is
+022.
+
+ - -t timestamp_style : how
+logs are timestamped by the catch-all logger. 0 means no
+timestamp, 1 means
+external TAI64N format,
+2 means
+ISO 8601 format,
+and 3 means both. Default is
+1.
+
+ - -d dev_style : how /dev is
+handled on this system. 0 means a static /dev, 1 means
+devtmpfs but not automounted by the kernel at boot time, and 2 means
+devtmpfs automounted by the kernel at boot time. Default is
+2.
+
+ - -e initial_envvar : this option
+can be repeated. For every initial_envvar, s6-linux-init-maker
+will adjust the global environment directory in dir/env.
+initial_envvar must either be of the form VAR,
+to make sure that VAR does not appear in the global
+environment, or of the form VAR=VALUE, to add an
+environment variable VAR with the value VALUE.
+The TZ variable, for instance, is a good candidate to be set in
+the global environment.
+
+
+
+
diff --git a/doc/upgrade.html b/doc/upgrade.html
new file mode 100644
index 0000000..92acdfc
--- /dev/null
+++ b/doc/upgrade.html
@@ -0,0 +1,28 @@
+
+
+
+
+
+ s6-linux-init: how to upgrade
+
+
+
+
+
+
+
+s6-linux-init
+Software
+skarnet.org
+
+
+ What has changed in s6-linux-init
+
+ in 0.0.1.0
+
+
+
+
+
diff --git a/package/deps-build b/package/deps-build
new file mode 100644
index 0000000..2e5eebc
--- /dev/null
+++ b/package/deps-build
@@ -0,0 +1,5 @@
+/package/prog/skalibs
+/package/admin/execline
+/package/admin/s6-portable-utils
+/package/admin/s6-linux-utils
+/package/admin/s6
diff --git a/package/deps.mak b/package/deps.mak
new file mode 100644
index 0000000..5e669fe
--- /dev/null
+++ b/package/deps.mak
@@ -0,0 +1,8 @@
+#
+# This file has been generated by tools/gen-deps.sh
+#
+
+src/init/s6-linux-init-maker.o src/init/s6-linux-init-maker.lo: src/init/s6-linux-init-maker.c
+
+s6-linux-init-maker: private EXTRA_LIBS :=
+s6-linux-init-maker: src/init/s6-linux-init-maker.o -lskarnet
diff --git a/package/info b/package/info
new file mode 100644
index 0000000..cb108ed
--- /dev/null
+++ b/package/info
@@ -0,0 +1,4 @@
+package=s6-linux-init
+version=0.0.1.0
+category=admin
+package_macro_name=S6_LINUX_INIT
diff --git a/package/modes b/package/modes
new file mode 100644
index 0000000..4b115b4
--- /dev/null
+++ b/package/modes
@@ -0,0 +1 @@
+s6-linux-init-maker 0700
diff --git a/package/targets.mak b/package/targets.mak
new file mode 100644
index 0000000..2330c89
--- /dev/null
+++ b/package/targets.mak
@@ -0,0 +1,6 @@
+BIN_TARGETS :=
+
+SBIN_TARGETS := \
+s6-linux-init-maker
+
+LIBEXEC_TARGETS :=
diff --git a/src/init/deps-exe/s6-linux-init-maker b/src/init/deps-exe/s6-linux-init-maker
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/init/deps-exe/s6-linux-init-maker
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/init/s6-linux-init-maker.c b/src/init/s6-linux-init-maker.c
new file mode 100644
index 0000000..a965cc0
--- /dev/null
+++ b/src/init/s6-linux-init-maker.c
@@ -0,0 +1,377 @@
+/* ISC license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define USAGE "s6-linux-init-maker [ -c basedir ] [ -l tmpfsdir ] [ -b execline_bindir ] [ -u log_user ] [ -g early_getty_cmd ] [ -2 stage2_script ] [ -3 stage3_script ] [ -p initial_path ] [ -m initial_umask ] [ -t timestamp_style ] [ -d dev_style ] [ -e initial_envvar ... ] dir"
+#define dieusage() strerr_dieusage(100, USAGE)
+#define dienomem() strerr_diefu1sys(111, "stralloc_catb") ;
+
+#define CRASH_SCRIPT \
+"#!" EXECLINE_EXTBINPREFIX "execlineb -P\n\n" \
+EXECLINE_EXTBINPREFIX "redirfd -r 0 /dev/console\n" \
+EXECLINE_EXTBINPREFIX "redirfd -w 1 /dev/console\n" \
+EXECLINE_EXTBINPREFIX "fdmove -c 2 1\n" \
+EXECLINE_EXTBINPREFIX "foreground { " \
+S6_PORTABLE_UTILS_EXTBINPREFIX "s6-echo -- " \
+"\"s6-svscan crashed. Dropping to an interactive shell.\" }\n" \
+"/bin/sh -i\n"
+
+#define BANNER1 "s6-init: stage 1"
+#define BANNER2 "s6-init: stage 2"
+
+static char const *slashrun = "/run" ;
+static char const *robase = "/etc/s6" ;
+static char const *init_script = "/etc/rc.init" ;
+static char const *shutdown_script = "/etc/rc.shutdown" ;
+static char const *bindir = "/bin" ;
+static char const *initial_path = SKALIBS_DEFAULTPATH ;
+static char const *early_getty = 0 ;
+static uid_t uncaught_logs_uid = 65534 ;
+static gid_t uncaught_logs_gid = 65534 ;
+static unsigned int initial_umask = 022 ;
+static unsigned int timestamp_style = 1 ;
+static unsigned int slashdev_style = 2 ;
+
+typedef int writetobuf_func_t (buffer *) ;
+typedef writetobuf_func_t *writetobuf_func_t_ref ;
+
+static int early_getty_script (buffer *b)
+{
+ if (buffer_puts(b, "#!" EXECLINE_EXTBINPREFIX "execlineb -P\n\n") < 0
+ || buffer_puts(b, early_getty) < 0
+ || buffer_put(b, "\n", 1) < 0)
+ return 0 ;
+ return 1 ;
+}
+
+static int s6_svscan_log_script (buffer *b)
+{
+ unsigned int sabase = satmp.len ;
+ char fmt[UINT64_FMT] ;
+ if (buffer_puts(b,
+ "#!" EXECLINE_EXTBINPREFIX "execlineb -P\n\n"
+ EXECLINE_EXTBINPREFIX "redirfd -rnb 0 fifo\n"
+ S6_EXTBINPREFIX "s6-applyuidgid -u ") < 0
+ || buffer_put(b, fmt, uint64_fmt(fmt, uncaught_logs_uid)) < 0
+ || buffer_puts(b, " -g ") < 0
+ || buffer_put(b, fmt, gid_fmt(fmt, uncaught_logs_gid)) < 0
+ || buffer_puts(b, " --\n" S6_EXTBINPREFIX "s6-log -bp -- ") < 0
+ || buffer_puts(b, timestamp_style & 1 ? "t " : "") < 0
+ || buffer_puts(b, timestamp_style & 2 ? "T " : "") < 0) return 0 ;
+ if (!string_quote(&satmp, slashrun, str_len(slashrun))) return 0 ;
+ if (buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0)
+ {
+ satmp.len = sabase ;
+ return 0 ;
+ }
+ satmp.len = sabase ;
+ if (buffer_puts(b, "/uncaught-logs\n") < 0) return 0 ;
+ return 1 ;
+}
+
+static int finish_script (buffer *b)
+{
+ unsigned int sabase = satmp.len ;
+ if (buffer_puts(b,
+ "#!" EXECLINE_EXTBINPREFIX "execlineb -S0\n\n"
+ EXECLINE_EXTBINPREFIX "cd /\n"
+ EXECLINE_EXTBINPREFIX "redirfd -w 2 /dev/console\n"
+ EXECLINE_EXTBINPREFIX "fdmove -c 1 2\n"
+ EXECLINE_EXTBINPREFIX "wait { }\n") < 0
+ || !string_quote(&satmp, shutdown_script, str_len(shutdown_script))) return 0 ;
+ if (buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0)
+ {
+ satmp.len = sabase ;
+ return 0 ;
+ }
+ satmp.len = sabase ;
+ if (buffer_puts(b, " ${@}\n") < 0) return 0 ;
+ return 1 ;
+}
+
+static void cleanup (char const *base)
+{
+ int e = errno ;
+ rm_rf(base) ;
+ errno = e ;
+}
+
+static void auto_dir (char const *base, char const *dir, uid_t uid, gid_t gid, unsigned int mode)
+{
+ unsigned int clen = str_len(base) ;
+ unsigned int dlen = str_len(dir) ;
+ char fn[clen + dlen + 2] ;
+ byte_copy(fn, clen, base) ;
+ fn[clen] = dlen ? '/' : 0 ;
+ byte_copy(fn + clen + 1, dlen + 1, dir) ;
+ if (mkdir(fn, mode) < 0
+ || ((uid || gid) && (chown(fn, uid, gid) < 0 || chmod(fn, mode) < 0)))
+ {
+ cleanup(base) ;
+ strerr_diefu2sys(111, "mkdir ", fn) ;
+ }
+}
+
+static void auto_file (char const *base, char const *file, char const *s, unsigned int n, int executable)
+{
+ unsigned int clen = str_len(base) ;
+ unsigned int flen = str_len(file) ;
+ char fn[clen + flen + 2] ;
+ byte_copy(fn, clen, base) ;
+ fn[clen] = '/' ;
+ byte_copy(fn + clen + 1, flen + 1, file) ;
+ if (!openwritenclose_unsafe(fn, s, n)
+ || (executable && chmod(fn, 0755) < 0))
+ {
+ cleanup(base) ;
+ strerr_diefu2sys(111, "write to ", fn) ;
+ }
+}
+
+static void auto_fifo (char const *base, char const *fifo)
+{
+ unsigned int baselen = str_len(base) ;
+ unsigned int fifolen = str_len(fifo) ;
+ char fn[baselen + fifolen + 2] ;
+ byte_copy(fn, baselen, base) ;
+ fn[baselen] = '/' ;
+ byte_copy(fn + baselen + 1, fifolen + 1, fifo) ;
+ if (mkfifo(fn, 0600) < 0)
+ {
+ cleanup(base) ;
+ strerr_diefu2sys(111, "mkfifo ", fn) ;
+ }
+}
+
+static void auto_script (char const *base, char const *file, writetobuf_func_t_ref scriptf)
+{
+ char buf[4096] ;
+ buffer b ;
+ int fd ;
+ unsigned int baselen = str_len(base) ;
+ unsigned int filelen = str_len(file) ;
+ char fn[baselen + filelen + 2] ;
+ byte_copy(fn, baselen, base) ;
+ fn[baselen] = '/' ;
+ byte_copy(fn + baselen + 1, filelen + 1, file) ;
+ fd = open_trunc(fn) ;
+ if (fd < 0 || ndelay_off(fd) < 0 || fchmod(fd, 0755) < 0)
+ {
+ cleanup(base) ;
+ strerr_diefu3sys(111, "open ", fn, " for script writing") ;
+ }
+ buffer_init(&b, &fd_writesv, fd, buf, 4096) ;
+ if (!(*scriptf)(&b) || !buffer_flush(&b))
+ {
+ cleanup(base) ;
+ strerr_diefu2sys(111, "write to ", fn) ;
+ }
+ close(fd) ;
+}
+
+static void make_image (char const *base)
+{
+ auto_dir(base, "run-image", 0, 0, 0755) ;
+ auto_dir(base, "run-image/uncaught-logs", uncaught_logs_uid, uncaught_logs_gid, 02700) ;
+ auto_dir(base, "run-image/service", 0, 0, 0755) ;
+ auto_dir(base, "run-image/service/.s6-svscan", 0, 0, 0755) ;
+ auto_file(base, "run-image/service/.s6-svscan/crash", CRASH_SCRIPT, sizeof(CRASH_SCRIPT) - 1, 1) ;
+ auto_script(base, "run-image/service/.s6-svscan/finish", &finish_script) ;
+ auto_dir(base, "run-image/service/s6-svscan-log", 0, 0, 0755) ;
+ auto_fifo(base, "run-image/service/s6-svscan-log/fifo") ;
+ auto_script(base, "run-image/service/s6-svscan-log/run", &s6_svscan_log_script) ;
+ if (early_getty)
+ {
+ auto_dir(base, "run-image/service/early-getty", 0, 0, 0755) ;
+ auto_script(base, "run-image/service/early-getty/run", &early_getty_script) ;
+ }
+}
+
+static void make_env (char const *base, char const *modif, unsigned int modiflen)
+{
+ auto_dir(base, "env", 0, 0, 0755) ;
+ while (modiflen)
+ {
+ unsigned int len = str_len(modif) ;
+ unsigned int pos = byte_chr(modif, len, '=') ;
+ char fn[5 + pos] ;
+ byte_copy(fn, 4, "env/") ;
+ byte_copy(fn + 4, pos, modif) ;
+ fn[4 + pos] = 0 ;
+
+ if (pos + 1 < len) auto_file(base, fn, modif + pos + 1, len - pos - 1, 0) ;
+ else if (pos + 1 == len) auto_file(base, fn, "\n", 1, 0) ;
+ else auto_file(base, fn, "", 0, 0) ;
+ modif += len+1 ; modiflen -= len+1 ;
+ }
+}
+
+static int make_init_script (buffer *b)
+{
+ unsigned int sabase = satmp.len, pos, pos2 ;
+ char fmt[UINT_OFMT] ;
+ if (buffer_puts(b, "#!") < 0
+ || buffer_puts(b, bindir) < 0
+ || buffer_puts(b, "/execlineb -P\n\n") < 0
+ || buffer_puts(b, bindir) < 0
+ || buffer_puts(b, "/export PATH ") < 0
+ || !string_quote(&satmp, initial_path, str_len(initial_path))) return 0 ;
+ if (buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0) goto err ;
+ satmp.len = sabase ;
+ if (buffer_put(b, "\n", 1) < 0
+ || buffer_puts(b, bindir) < 0
+ || buffer_puts(b, "/cd /\n"
+ EXECLINE_EXTBINPREFIX "umask 0") < 0
+ || buffer_put(b, fmt, uint_ofmt(fmt, initial_umask)) < 0
+ || buffer_puts(b, "\n"
+ EXECLINE_EXTBINPREFIX "if { "
+ S6_PORTABLE_UTILS_EXTBINPREFIX "s6-echo -- \"" BANNER1 "\" }\n"
+ EXECLINE_EXTBINPREFIX "if { "
+ S6_LINUX_UTILS_EXTBINPREFIX "s6-mount -nwt tmpfs -o mode=0755 tmpfs ") < 0
+ || !string_quote(&satmp, slashrun, str_len(slashrun))) return 0 ;
+ pos = satmp.len ;
+ if (buffer_put(b, satmp.s + sabase, pos - sabase) < 0
+ || buffer_puts(b, " }\n"
+ EXECLINE_EXTBINPREFIX "if { "
+ S6_PORTABLE_UTILS_EXTBINPREFIX "s6-hiercopy ") < 0
+ || !string_quote(&satmp, robase, str_len(robase))) return 0 ;
+ pos2 = satmp.len ;
+ if (buffer_put(b, satmp.s + pos, pos2 - pos) < 0
+ || buffer_puts(b, "/run-image ") < 0
+ || buffer_put(b, satmp.s + sabase, pos - sabase) < 0
+ || buffer_puts(b, " }\n") < 0) goto err ;
+ if (slashdev_style == 1)
+ {
+ if (buffer_puts(b,
+ EXECLINE_EXTBINPREFIX "if { "
+ S6_LINUX_UTILS_EXTBINPREFIX "s6-mount -nt devtmpfs dev /dev }\n") < 0)
+ goto err ;
+ }
+ if (buffer_puts(b,
+ EXECLINE_EXTBINPREFIX "redirfd -r 0 /dev/null\n"
+ S6_EXTBINPREFIX "s6-envdir -I -- ") < 0
+ || buffer_put(b, satmp.s + pos, pos2 - pos) < 0
+ || buffer_puts(b, "/env\n"
+ EXECLINE_EXTBINPREFIX "background\n{\n "
+ S6_EXTBINPREFIX "s6-setsid --\n "
+ EXECLINE_EXTBINPREFIX "redirfd -w 2 ") < 0
+ || buffer_put(b, satmp.s + sabase, pos - sabase) < 0
+ || buffer_puts(b, "/service/s6-svscan-log/fifo\n "
+ EXECLINE_EXTBINPREFIX "if { "
+ S6_PORTABLE_UTILS_EXTBINPREFIX "s6-echo -- \"" BANNER2 "\" }\n "
+ EXECLINE_EXTBINPREFIX "fdmove -c 1 2\n ") < 0
+ || !string_quote(&satmp, init_script, str_len(init_script))
+ || buffer_put(b, satmp.s + pos2, satmp.len - pos2) < 0
+ || buffer_puts(b, "\n}\n"
+ EXECLINE_EXTBINPREFIX "unexport !\n"
+ EXECLINE_EXTBINPREFIX "redirfd -wnb 1 ") < 0
+ || buffer_put(b, satmp.s + sabase, pos - sabase) < 0
+ || buffer_puts(b,
+ "/service/s6-svscan-log/fifo\n"
+ EXECLINE_EXTBINPREFIX "fdmove -c 2 1\n"
+ EXECLINE_EXTBINPREFIX "cd ") < 0
+ || buffer_put(b, satmp.s + sabase, pos - sabase) < 0
+ || buffer_puts(b, "/service\n") < 0) goto err ;
+ if (sizeof(S6_EXTBINPREFIX) > 1)
+ {
+ if (buffer_puts(b, EXECLINE_EXTBINPREFIX "exec -a s6-svscan --\n") < 0)
+ goto err ;
+ }
+ if (buffer_puts(b, S6_EXTBINPREFIX "s6-svscan -t0\n") < 0) goto err ;
+ return 1 ;
+ err:
+ satmp.len = sabase ;
+ return 0 ;
+}
+
+int main (int argc, char const *const *argv)
+{
+ char const *catchall_user = "nobody" ;
+ stralloc modif = STRALLOC_ZERO ;
+ PROG = "s6-linux-init-maker" ;
+ {
+ subgetopt_t l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ register int opt = subgetopt_r(argc, argv, "c:l:b:u:g:2:3:p:m:t:d:e:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'c' : robase = l.arg ; break ;
+ case 'l' : slashrun = l.arg ; break ;
+ case 'b' : bindir = l.arg ; break ;
+ case 'u' : catchall_user = l.arg ; break ;
+ case 'g' : early_getty = l.arg ; break ;
+ case '2' : init_script = l.arg ; break ;
+ case '3' : shutdown_script = l.arg ; break ;
+ case 'p' : initial_path = l.arg ; break ;
+ case 'm' : if (!uint0_oscan(l.arg, &initial_umask)) dieusage() ; break ;
+ case 't' : if (!uint0_scan(l.arg, ×tamp_style)) dieusage() ; break ;
+ case 'd' : if (!uint0_scan(l.arg, &slashdev_style)) dieusage() ; break ;
+ case 'e' : if (!stralloc_catb(&modif, l.arg, str_len(l.arg) + 1)) dienomem() ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (!argc) dieusage() ;
+
+ if (robase[0] != '/')
+ strerr_dief3x(100, "base directory ", robase, " is not absolute") ;
+ if (slashrun[0] != '/')
+ strerr_dief3x(100, "tmpfs directory ", slashrun, " is not absolute") ;
+ if (bindir[0] != '/')
+ strerr_dief3x(100, "initial location for binaries ", bindir, " is not absolute") ;
+ if (init_script[0] != '/')
+ strerr_dief3x(100, "stage 2 script location ", init_script, " is not absolute") ;
+ if (shutdown_script[0] != '/')
+ strerr_dief3x(100, "stage 3 script location ", shutdown_script, " is not absolute") ;
+ if (timestamp_style > 3)
+ strerr_dief1x(100, "-t timestamp_style must be 0, 1, 2 or 3") ;
+ if (slashdev_style > 2)
+ strerr_dief1x(100, "-d dev_style must be 0, 1 or 2") ;
+
+
+ {
+ struct passwd *pw = getpwnam(catchall_user) ;
+ if (!pw)
+ {
+ if (errno)
+ strerr_diefu2sys(111, "getpwnam for ", catchall_user) ;
+ else
+ strerr_dief3x(100, "getpwnam for ", catchall_user, ": no such user") ;
+ }
+ uncaught_logs_uid = pw->pw_uid ;
+ uncaught_logs_gid = pw->pw_gid ;
+ }
+
+ if (mkdir(argv[0], 0755) < 0)
+ strerr_diefu2sys(111, "mkdir ", argv[0]) ;
+
+ make_env(argv[0], modif.s, modif.len) ;
+ stralloc_free(&modif) ;
+ make_image(argv[0]) ;
+ if (!make_init_script(buffer_1) || !buffer_flush(buffer_1))
+ strerr_diefu1sys(111, "write to stdout") ;
+ return 0 ;
+}
diff --git a/tools/gen-deps.sh b/tools/gen-deps.sh
new file mode 100755
index 0000000..4615f28
--- /dev/null
+++ b/tools/gen-deps.sh
@@ -0,0 +1,83 @@
+#!/bin/sh -e
+
+. package/info
+
+echo '#'
+echo '# This file has been generated by tools/gen-deps.sh'
+echo '#'
+echo
+
+for dir in src/include/${package} src/* ; do
+ for file in $(ls -1 $dir | grep -- \\.h$) ; do
+ {
+ grep -F -- "#include <${package}/" < ${dir}/$file | cut -d'<' -f2 | cut -d'>' -f1 ;
+ grep -- '#include ".*\.h"' < ${dir}/$file | cut -d'"' -f2
+ } | sort -u | {
+ deps=
+ while read dep ; do
+ if echo $dep | grep -q "^${package}/" ; then
+ deps="$deps src/include/$dep"
+ elif test -f "${dir}/$dep" ; then
+ deps="$deps ${dir}/$dep"
+ else
+ deps="$deps src/include-local/$dep"
+ fi
+ done
+ if test -n "$deps" ; then
+ echo "${dir}/${file}:${deps}"
+ fi
+ }
+ done
+done
+
+for dir in src/* ; do
+ for file in $(ls -1 $dir | grep -- \\.c$) ; do
+ {
+ grep -F -- "#include <${package}/" < ${dir}/$file | cut -d'<' -f2 | cut -d'>' -f1 ;
+ grep -- '#include ".*\.h"' < ${dir}/$file | cut -d'"' -f2
+ } | sort -u | {
+ deps=" ${dir}/$file"
+ while read dep ; do
+ if echo $dep | grep -q "^${package}/" ; then
+ deps="$deps src/include/$dep"
+ elif test -f "${dir}/$dep" ; then
+ deps="$deps ${dir}/$dep"
+ else
+ deps="$deps src/include-local/$dep"
+ fi
+ done
+ o=$(echo $file | sed s/\\.c$/.o/)
+ lo=$(echo $file | sed s/\\.c$/.lo/)
+ echo "${dir}/${o} ${dir}/${lo}:${deps}"
+ }
+ done
+done
+echo
+
+for dir in $(ls -1 src | grep -v ^include) ; do
+ for file in $(ls -1 src/$dir/deps-lib) ; do
+ deps=
+ while read dep ; do
+ deps="$deps src/$dir/$dep"
+ done < src/$dir/deps-lib/$file
+ echo "lib$file.a:$deps"
+ echo "lib${file}.so:$(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: private 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.2.3