From 32759d402e7327865ea18a203bd1c09f98735bd1 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Sun, 22 Oct 2017 17:09:25 +0000 Subject: Initial commit --- .gitignore | 8 + AUTHORS | 6 + COPYING | 13 ++ INSTALL | 165 ++++++++++++++++++ Makefile | 147 ++++++++++++++++ NEWS | 7 + README | 26 +++ configure | 446 ++++++++++++++++++++++++++++++++++++++++++++++++ doc/index.html | 115 +++++++++++++ doc/mdevd-coldplug.html | 74 ++++++++ doc/mdevd-netlink.html | 123 +++++++++++++ doc/mdevd.html | 130 ++++++++++++++ doc/upgrade.html | 28 +++ package/deps-build | 1 + package/deps.mak | 14 ++ package/info | 4 + package/modes | 3 + package/targets.mak | 7 + tools/gen-deps.sh | 89 ++++++++++ tools/install.sh | 64 +++++++ 20 files changed, 1470 insertions(+) create mode 100644 .gitignore create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 INSTALL create mode 100644 Makefile create mode 100644 NEWS create mode 100644 README create mode 100755 configure create mode 100644 doc/index.html create mode 100644 doc/mdevd-coldplug.html create mode 100644 doc/mdevd-netlink.html create mode 100644 doc/mdevd.html create mode 100644 doc/upgrade.html create mode 100644 package/deps-build create mode 100644 package/deps.mak create mode 100644 package/info create mode 100644 package/modes create mode 100644 package/targets.mak create mode 100755 tools/gen-deps.sh create mode 100755 tools/install.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..03df4a0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.so +*.so.* +mdevd +mdevd-netlink +mdevd-coldplug diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..8d69cec --- /dev/null +++ b/AUTHORS @@ -0,0 +1,6 @@ +Main author: + Laurent Bercot + +Thanks to: + Rob Landley + Natanael Copa diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..9e2739b --- /dev/null +++ b/COPYING @@ -0,0 +1,13 @@ +Copyright (c) 2017 Laurent Bercot + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..ca073f2 --- /dev/null +++ b/INSTALL @@ -0,0 +1,165 @@ +Build Instructions +------------------ + +* Requirements + ------------ + + - A Linux-based system with a standard C development environment + - GNU make version 3.81 or later + - skalibs version 2.6.0.0 or later: http://skarnet.org/software/skalibs/ + + This software is Linux-specific. It will run on a Linux kernel, +version 2.6.10 or later. + + +* 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. + + +* 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. + + Be aware that the GNU libc behaves badly with static linking and +produces huge executables, which is why it is not the default. +Other libcs are better suited to static linking, for instance +musl: http://musl-libc.org/ + + +* Cross-compilation + ----------------- + + skarnet.org packages centralize all the difficulty of +cross-compilation in one place: skalibs. Once you have +cross-compiled skalibs, the rest is easy. + + * Use the --host=HOST option to configure, HOST being the triplet +for your target. + * Make sure your cross-toolchain binaries (i.e. prefixed with HOST-) +are accessible via your PATH environment variable. + * Make sure to use the correct version of skalibs for your target, +and the correct sysdeps directory, making use of the +--with-include, --with-lib, --with-dynlib and --with-sysdeps +options as necessary. + + +* The slashpackage convention + --------------------------- + + The slashpackage convention (http://cr.yp.to/slashpackage.html) +is a package installation scheme that provides a few guarantees +over other conventions such as the FHS, for instance fixed +absolute pathnames. skarnet.org packages support it: use the +--enable-slashpackage option to configure, or +--enable-slashpackage=DIR for a prefixed DIR/package tree. +This option will activate slashpackage support during the build +and set slashpackage-compatible installation directories. +If $package_home is the home of the package, defined as +DIR/package/$category/$package-$version with the variables +read from the package/info file, then: + + --dynlibdir is set to $package_home/library.so + --bindir is set to $package_home/command + --sbindir is also set to $package_home/command (slashpackage +differentiates root-only binaries by their Unix rights, not their +location in the filesystem) + --libexecdir is also set to $package_home/command (slashpackage +does not need a specific directory for internal binaries) + --libdir is set to $package_home/library + --includedir is set to $package_home/include + + --prefix is pretty much ignored when you use --enable-slashpackage. +You should probably not use both --enable-slashpackage and --prefix. + + When using slashpackage, two additional Makefile targets are +available after "make install": + - "make update" changes the default version of the software to the +freshly installed one. (This is useful when you have several installed +versions of the same software, which slashpackage supports.) + - "make -L global-links" adds links from /command and /library.so to the +default version of the binaries and shared libraries. The "-L" option to +make is necessary because targets are symbolic links, and the default make +behaviour is to check the pointed file's timestamp and not the symlink's +timestamp. + + +* Absolute pathnames + ------------------ + + You may want to use fixed absolute pathnames even if you're not +following the slashpackage convention: for instance, the Nix packaging +system prefers calling binaries with immutable paths rather than rely on +PATH resolution. If you are in that case, use the --enable-absolute-paths +option to configure. This will ensure that programs calling binaries from +this package will call them with their full installation path (in bindir) +without relying on a PATH search. + + +* Out-of-tree builds + ------------------ + + skarnet.org packages do not support out-of-tree builds. They +are small, so it does not cost much to duplicate the entire +source tree if parallel builds are needed. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..259d624 --- /dev/null +++ b/Makefile @@ -0,0 +1,147 @@ +# +# 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) +CFLAGS_SHARED := -fPIC +LDFLAGS_ALL := $(LDFLAGS_AUTO) $(LDFLAGS) +REALCC = $(CROSS_COMPILE)$(CC) +AR := $(CROSS_COMPILE)ar +RANLIB := $(CROSS_COMPILE)ranlib +STRIP := $(CROSS_COMPILE)strip +INSTALL := ./tools/install.sh + +ALL_BINS := $(LIBEXEC_TARGETS) $(BIN_TARGETS) +ALL_LIBS := $(SHARED_LIBS) $(STATIC_LIBS) $(INTERNAL_LIBS) +ALL_INCLUDES := $(wildcard src/include/$(package)/*.h) + +all: $(ALL_LIBS) $(ALL_BINS) $(ALL_INCLUDES) + +clean: + @exec rm -f $(ALL_LIBS) $(ALL_BINS) $(wildcard src/*/*.o src/*/*.lo) $(EXTRA_TARGETS) + +distclean: clean + @exec rm -f config.mak src/include/$(package)/config.h + +tgz: distclean + @. package/info && \ + rm -rf /tmp/$$package-$$version && \ + cp -a . /tmp/$$package-$$version && \ + cd /tmp && \ + tar -zpcv --owner=0 --group=0 --numeric-owner --exclude=.git* -f /tmp/$$package-$$version.tar.gz $$package-$$version && \ + exec rm -rf /tmp/$$package-$$version + +strip: $(ALL_LIBS) $(ALL_BINS) +ifneq ($(strip $(STATIC_LIBS)),) + exec $(STRIP) -x -R .note -R .comment -R .note.GNU-stack $(STATIC_LIBS) +endif +ifneq ($(strip $(ALL_BINS)$(SHARED_LIBS)),) + exec $(STRIP) -R .note -R .comment -R .note.GNU-stack $(ALL_BINS) $(SHARED_LIBS) +endif + +install: install-dynlib install-libexec install-bin install-lib install-include +install-dynlib: $(SHARED_LIBS:lib%.so.xyzzy=$(DESTDIR)$(dynlibdir)/lib%.so) +install-libexec: $(LIBEXEC_TARGETS:%=$(DESTDIR)$(libexecdir)/%) +install-bin: $(BIN_TARGETS:%=$(DESTDIR)$(bindir)/%) +install-lib: $(STATIC_LIBS:lib%.a.xyzzy=$(DESTDIR)$(libdir)/lib%.a) +install-include: $(ALL_INCLUDES:src/include/$(package)/%.h=$(DESTDIR)$(includedir)/$(package)/%.h) +install-data: $(ALL_DATA:src/etc/%=$(DESTDIR)$(datadir)/%) + +ifneq ($(exthome),) + +$(DESTDIR)$(exthome): $(DESTDIR)$(home) + exec $(INSTALL) -l $(notdir $(home)) $(DESTDIR)$(exthome) + +update: $(DESTDIR)$(exthome) + +global-links: $(DESTDIR)$(exthome) $(SHARED_LIBS:lib%.so.xyzzy=$(DESTDIR)$(sproot)/library.so/lib%.so.$(version_M)) $(BIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%) + +$(DESTDIR)$(sproot)/command/%: $(DESTDIR)$(home)/command/% + exec $(INSTALL) -D -l ..$(subst $(sproot),,$(exthome))/command/$( + + Please use the mailing-list for +questions about mdevd. diff --git a/configure b/configure new file mode 100755 index 0000000..a5654da --- /dev/null +++ b/configure @@ -0,0 +1,446 @@ +#!/bin/sh + +. package/info + +usage () { +cat </dev/null 2>&1 && { echo "$1" ; return 0 ; } +$1 +EOF + echo "$1" | sed -e "s/'/'\\\\''/g" -e "1s/^/'/" -e "\$s/\$/'/" -e "s#^'\([-[:alnum:]_,./:]*\)=\(.*\)\$#\1='\2#" -e "s|\*/|* /|g" +} + +fail () { + echo "$*" + exit 1 +} + +fnmatch () { + eval "case \"\$2\" in $1) return 0 ;; *) return 1 ;; esac" +} + +cmdexists () { + type "$1" >/dev/null 2>&1 +} + +trycc () { + test -z "$CC_AUTO" && cmdexists "$1" && CC_AUTO="$*" +} + +stripdir () { + while eval "fnmatch '*/' \"\${$1}\"" ; do + eval "$1=\${$1%/}" + done +} + +tryflag () { + echo "checking whether compiler accepts $2 ..." + echo "typedef int x;" > "$tmpc" + if $CC_AUTO $CPPFLAGS_AUTO $CPPFLAGS $CPPFLAGS_POST $CFLAGS_AUTO $CFLAGS $CFLAGS_POST "$2" -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then + echo " ... yes" + eval "$1=\"\${$1} \$2\"" + eval "$1=\${$1# }" + return 0 + else + echo " ... no" + return 1 + fi +} + +tryldflag () { + echo "checking whether linker accepts $2 ..." + echo "typedef int x;" > "$tmpc" + if $CC_AUTO $CFLAGS_AUTO $CFLAGS $CFLAGS_POST $LDFLAGS_AUTO $LDFLAGS $LDFLAGS_POST -nostdlib "$2" -o /dev/null "$tmpc" >/dev/null 2>&1 ; then + echo " ... yes" + eval "$1=\"\${$1} \$2\"" + eval "$1=\${$1# }" + return 0 + else + echo " ... no" + return 1 + fi +} + + +# Actual script + +CC_AUTO= +CPPFLAGS_AUTO="-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -iquote src/include-local -Isrc/include" +CPPFLAGS_POST="$CPPFLAGS" +CPPFLAGS= +CFLAGS_AUTO="-pipe -Wall" +CFLAGS_POST="$CFLAGS" +CFLAGS=-O2 +LDFLAGS_AUTO= +LDFLAGS_POST="$LDFLAGS" +LDFLAGS= +LDFLAGS_NOSHARED= +LDFLAGS_SHARED=-shared +prefix= +exec_prefix='$prefix' +dynlibdir='$prefix/lib' +libexecdir='$exec_prefix/libexec' +bindir='$exec_prefix/bin' +libdir='$prefix/lib/$package' +includedir='$prefix/include' +shebangdir='$bindir' +shebangisdefault=true +sysdeps='$prefix/lib/skalibs/sysdeps' +manualsysdeps=false +shared=false +static=true +slashpackage=false +abspath=false +sproot= +home= +exthome= +allstatic=true +evenmorestatic=false +addincpath='' +addlibspath='' +addlibdpath='' +vpaths='' +vpathd='' +build= + +for arg ; do + case "$arg" in + --help) usage ;; + --prefix=*) prefix=${arg#*=} ;; + --exec-prefix=*) exec_prefix=${arg#*=} ;; + --dynlibdir=*) dynlibdir=${arg#*=} ;; + --libexecdir=*) libexecdir=${arg#*=} ;; + --bindir=*) bindir=${arg#*=} ;; + --libdir=*) libdir=${arg#*=} ;; + --includedir=*) includedir=${arg#*=} ;; + --shebangdir=*) shebangisdefault=false ; shebangdir=${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-absolute-paths|--enable-absolute-paths=yes) abspath=true ;; + --disable-absolute-paths|--enable-absolute-paths=no) abspath=false ;; + --enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;; + --host=*|--target=*) target=${arg#*=} ;; + --build=*) build=${arg#*=} ;; + -* ) echo "$0: unknown option $arg" ;; + *=*) ;; + *) target=$arg ;; + esac +done + +# Add /usr in the default default case +if test -z "$prefix" ; then + if test "$libdir" = '$prefix/lib/$package' ; then + libdir=/usr/lib/$package + fi + if test "$includedir" = '$prefix/include' ; then + includedir=/usr/include + fi + if test "$sysdeps" = '$prefix/lib/skalibs/sysdeps' ; then + sysdeps=/usr/lib/skalibs/sysdeps + fi +fi + +# Expand installation directories +stripdir prefix +for i in exec_prefix dynlibdir libexecdir bindir libdir includedir shebangdir 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 + if $shebangisdefault ; then + shebangdir=${extbinprefix} + fi + while read dep ; do + addincpath="$addincpath -I${sproot}${dep}/include" + vpaths="$vpaths ${sproot}${dep}/library" + addlibspath="$addlibspath -L${sproot}${dep}/library" + vpathd="$vpathd ${sproot}${dep}/library.so" + addlibdpath="$addlibdpath -L${sproot}${dep}/library.so" + done < package/deps-build +fi + +# Find a C compiler to use +if test -n "$target" && test x${build} != x${target} ; then + cross=${target}- +else + cross= +fi +echo "checking for C compiler..." +trycc ${cross}${CC} +trycc ${cross}gcc +trycc ${cross}clang +trycc ${cross}cc +test -n "$CC_AUTO" || { echo "$0: cannot find a C compiler" ; exit 1 ; } +echo " ... $CC_AUTO" +echo "checking whether C compiler works... " +echo "typedef int x;" > "$tmpc" +if $CC_AUTO $CPPFLAGS_AUTO $CPPFLAGS $CPPFLAGS_POST $CFLAGS_AUTO $CFLAGS $CFLAGS_POST -c -o /dev/null "$tmpc" 2>"$tmpe" ; then + echo " ... yes" +else + echo " ... no. Compiler output follows:" + cat < "$tmpe" + exit 1 +fi + +echo "checking target system type..." +if test -z "$target" ; then + if test -n "$build" ; then + target=$build ; + else + target=$($CC_AUTO -dumpmachine 2>/dev/null) || target=unknown + fi +fi +echo " ... $target" +if test ! -d $sysdeps || test ! -f $sysdeps/target ; then + echo "$0: error: $sysdeps is not a valid sysdeps directory" + exit 1 +fi +if [ "x$target" != "x$(cat $sysdeps/target)" ] ; then + echo "$0: error: target $target does not match the contents of $sysdeps/target" + exit 1 +fi + +spawn_lib=$(cat $sysdeps/spawn.lib) +socket_lib=$(cat $sysdeps/socket.lib) +sysclock_lib=$(cat $sysdeps/sysclock.lib) +tainnow_lib=$(cat $sysdeps/tainnow.lib) +timer_lib=$(cat $sysdeps/timer.lib) +util_lib=$(cat $sysdeps/util.lib) + +tryflag CFLAGS_AUTO -std=c99 +tryflag CFLAGS -fomit-frame-pointer +tryflag CFLAGS_AUTO -fno-exceptions +tryflag CFLAGS_AUTO -fno-unwind-tables +tryflag CFLAGS_AUTO -fno-asynchronous-unwind-tables +tryflag CFLAGS_AUTO -Wa,--noexecstack +tryflag CFLAGS -fno-stack-protector +tryflag CPPFLAGS_AUTO -Werror=implicit-function-declaration +tryflag CPPFLAGS_AUTO -Werror=implicit-int +tryflag CPPFLAGS_AUTO -Werror=pointer-sign +tryflag CPPFLAGS_AUTO -Werror=pointer-arith +tryflag CFLAGS_AUTO -ffunction-sections +tryflag CFLAGS_AUTO -fdata-sections + +tryldflag LDFLAGS_AUTO -Wl,--sort-section=alignment +tryldflag LDFLAGS_AUTO -Wl,--sort-common + +CPPFLAGS_AUTO="${CPPFLAGS_AUTO}${addincpath}" + +if $evenmorestatic ; then + LDFLAGS_NOSHARED=-static +fi + +if $shared ; then + tryldflag LDFLAGS -Wl,--hash-style=both +fi + +LDFLAGS_SHARED="${LDFLAGS_SHARED}${addlibdpath}" + +if $allstatic ; then + LDFLAGS_NOSHARED="${LDFLAGS_NOSHARED}${addlibspath}" + tryldflag LDFLAGS_NOSHARED -Wl,--gc-sections +else + LDFLAGS_NOSHARED="${LDFLAGS_NOSHARED}${addlibdpath}" +fi + +if test -z "$vpaths" ; then + while read dep ; do + base=$(basename $dep) ; + vpaths="$vpaths /usr/lib/$base" + addlibspath="$addlibspath -L/usr/lib/$base" + done < package/deps-build +fi + +echo "creating config.mak..." +cmdline=$(quote "$0") +for i ; do cmdline="$cmdline $(quote "$i")" ; done +exec 3>&1 1>config.mak +cat << EOF +# This file was generated by: +# $cmdline +# Any changes made here will be lost if configure is re-run. + +target := $target +package := $package +prefix := $prefix +exec_prefix := $exec_prefix +dynlibdir := $dynlibdir +libexecdir := $libexecdir +bindir := $bindir +libdir := $libdir +includedir := $includedir +sysdeps := $sysdeps +slashpackage := $slashpackage +sproot := $sproot +version := $version +home := $home +exthome := $exthome +SPAWN_LIB := ${spawn_lib} +SOCKET_LIB := ${socket_lib} +SYSCLOCK_LIB := ${sysclock_lib} +TAINNOW_LIB := ${tainnow_lib} +TIMER_LIB := ${timer_lib} +UTIL_LIB := ${util_lib} + +CC := ${CC_AUTO##${cross}} +CPPFLAGS_AUTO := $CPPFLAGS_AUTO +CPPFLAGS := $CPPFLAGS $CPPFLAGS_POST +CFLAGS_AUTO := $CFLAGS_AUTO +CFLAGS := $CFLAGS $CFLAGS_POST +LDFLAGS_AUTO := $LDFLAGS_AUTO +LDFLAGS := $LDFLAGS $LDFLAGS_POST +LDFLAGS_SHARED := $LDFLAGS_SHARED +LDFLAGS_NOSHARED := $LDFLAGS_NOSHARED +CROSS_COMPILE := $cross + +vpath lib%.a$vpaths +vpath lib%.so$vpathd +EOF +if $allstatic ; then + echo ".LIBPATTERNS := lib%.a" + echo "DO_ALLSTATIC := 1" +else + echo ".LIBPATTERNS := lib%.so" +fi +if $static ; then + echo "DO_STATIC := 1" +else + echo "DO_STATIC :=" +fi +if $shared ; then + echo "DO_SHARED := 1" +else + echo "DO_SHARED :=" +fi + +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..91c01d3 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,115 @@ + + + + + + mdevd - A mdev-compatible Linux hotplug manager daemon + + + + + + +

+Software
+skarnet.org +

+ +

mdevd

+ +

What is it ?

+ +

+ mdevd is a small daemon managing kernel hotplug events, similarly to udevd. +

+ +

+ It uses the same configuration file as +mdev, +which is a hotplug manager integrated in the +Busybox suite of tools. +However, mdev needs to be registered in +/proc/sys/kernel/hotplug, and the kernel forks +an instance of mdev for every event; by contrast, mdevd is a daemon +and does not fork. +

+ +

+ The point of mdevd is to provide a drop-in replacement to mdev +that does not fork, so it can handle large influxes of events +at boot time without a performance drop. mdevd is designed to be +entirely compatible with advanced mdev usage such as +mdev-like-a-boss. +

+ +
+ +

Installation

+ +

Requirements

+ +
    +
  • A Linux-based system with a standard C development environment. +The Linux kernel must be 2.6.10 or later.
  • +
  • GNU make, version 3.81 or later
  • +
  • skalibs version +2.6.0.0 or later. It's a build-time requirement. It's also a run-time +requirement if you link against the shared version of the skalibs +library.
  • +
+ +

Licensing

+ +

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

+ +

Download

+ +
    +
  • The current released version of mdevd is +0.0.1.0.
  • +
  • Alternatively, you can checkout a copy of the +mdevd +git repository: +
     git clone git://git.skarnet.org/mdevd 
  • +
  • There's also a +GitHub mirror +of the mdevd git repository.
  • +
+ +

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 mdevd and the current one.
  • +
+ +
+ +

Reference

+ +

Commands

+ + + +

Related resources

+ +
    +
  • mdevd is discussed on the +skaware mailing-list.
  • +
+ + + diff --git a/doc/mdevd-coldplug.html b/doc/mdevd-coldplug.html new file mode 100644 index 0000000..8355df3 --- /dev/null +++ b/doc/mdevd-coldplug.html @@ -0,0 +1,74 @@ + + + + + + mdevd: the mdevd-coldplug program + + + + + + +

+mdevd
+Software
+skarnet.org +

+ +

The mdevd-coldplug program

+ +

+mdevd-coldplug performs a coldplug: it scans +/sys for all registered devices an uevent manager would +want to perform actions on, and generates uevents for all these +devices. +

+ +

Interface

+ +
+     mdevd-coldplug [ -s slashsys ]
+
+ +
    +
  • mdevd-coldplug scans /sys for devices.
  • +
  • For every suitable device it finds, it generates an +uevent and writes it to its stdout, using the same format +as mdevd-netlink.
  • +
  • It exits when it has finished scanning.
  • +
+ +

+ This implies that the mdevd-coldplug | mdevd command line +will function as a coldplug manager, just like mdev -s. +

+ +

Options

+ +
    +
  • -s slashsys : assume the sysfs +pseudo-filesystem is mounted on slashsys. Default is /sys.
  • +
+ +

Exit codes

+ +
    +
  • 0: success
  • +
  • 111: system call failed
  • +
+ +

Notes

+ +
    +
  • mdevd-coldplug is a short-lived program, just like +mdev -s.
  • +
  • Unlike mdev -s, however, mdevd-coldplug does +not act on the uevents it generates. It simply prints them. +This allows for easy debugging.
  • +
  • To act on the uevents, simply pipe the output of +mdevd-coldplug into mdevd.
  • +
+ + + diff --git a/doc/mdevd-netlink.html b/doc/mdevd-netlink.html new file mode 100644 index 0000000..9747f13 --- /dev/null +++ b/doc/mdevd-netlink.html @@ -0,0 +1,123 @@ + + + + + + mdevd: the mdevd-netlink program + + + + + + +

+mdevd
+Software
+skarnet.org +

+ +

The mdevd-netlink program

+ +

+mdevd-netlink listens to the netlink interface for uevents +(also called "hotplug" or "udev" events), and writes those uevents to +its standard output, using a simple format. +

+ +

+mdevd expects uevents in the same +format mdevd-netlink writes them. So the +mdevd-netlink | mdevd command line will function as +a daemon reading uevents from the netlink and handling them. +

+ +

Interface

+ +
+     mdevd-netlink [ -d notif ] [ -v verbosity ] [ -b kbufsz ]
+
+ +
    +
  • mdevd-netlink binds to the netlink interface and listens for +hotplug events, as the udevd program does.
  • +
  • It writes event information to its stdout. The output contains +null characters, so a terminal will not display them correctly. To +properly use mdevd-netlink, it should be piped into a handler +program such as mdevd.
  • +
  • mdevd-netlink is a long-lived program. +When it receives a SIGTERM, it stops listening to hotplug events; +it will exit as soon as it has flushed its event queue to stdout.
  • +
+ +

Options

+ +
    +
  • -d notif : when ready (actually +listening to the netlink), write a newline to file descriptor notif +then close it. This allows mdevd-netlink to use the +s6 mechanism to +notify readiness. notif cannot be lesser than 3. If this +option is not given, no readiness notification is sent.
  • +
  • -v verbosity : be more or less verbose. +Default verbosity is 1. 0 will only print fatal error messages, 3 will +print warnings every time the netlink interface sends something +unexpected.
  • +
  • -b kbufsz : try and reserve a kernel buffer of +kbufsz bytes for the netlink queue. Too large a buffer wastes kernel memory; +too small a buffer risks losing events. The default is 65536 (which is on +the large side).
  • +
+ +

Protocol

+ +
    +
  • An event is a series of null-terminated strings as they are sent by +the kernel to the netlink; mdevd-netlink adds a final empty string +(i.e. an additional null character) to mark the end of the series.
  • +
  • The first string is a short description of the event; it normally +contains the string "@/". Other strings after the first are of the form +"VARIABLE=value", and describe the environment which a hotplug helper +for the event (registered in /proc/sys/kernel/hotplug) would be +spawned with.
  • +
  • Example (newlines added for clarity):
    +add@/class/input/input9/mouse2\0
    +ACTION=add\0
    +DEVPATH=/class/input/input9/mouse2\0
    +SUBSYSTEM=input\0
    +SEQNUM=106\0
    +PHYSDEVPATH=/devices/pci0000:00/0000:00:1d.1/usb2/2­2/2­2:1.0
    +PHYSDEVBUS=usb\0
    +PHYSDEVDRIVER=usbhid\0
    +MAJOR=13\0
    +MINOR=34\0
    +\0 
  • +
+ +

Notes

+ +
    +
  • mdevd-netlink is a daemon; it should be run under a proper supervision system such +as s6.
  • +
  • If you are running mdevd-netlink, the program you pipe its +output into should be the only program handling uevents; that means +that /proc/sys/kernel/hotplug should be empty.
  • +
  • The mdevd-netlink | mdevd command line is a quick +way of running a uevent manager, but there are ways to improve it: +
      +
    • Using the +execline scripting +language, the pipeline { mdevd-netlink } mdevd command +line will avoid leaving a shell around.
    • +
    • The best way to use mdevd-netlink and mdevd is with a +supervision system: +under s6 or +s6-rc, write a service +pipeline where mdevd-netlink is a producer and +mdevd is a consumer. This setup has the advantage, among +others, that you can restart the netlink listener and the event handler +separately.
    • +
  • +
+ + + diff --git a/doc/mdevd.html b/doc/mdevd.html new file mode 100644 index 0000000..b5b8a36 --- /dev/null +++ b/doc/mdevd.html @@ -0,0 +1,130 @@ + + + + + + mdevd: the mdevd program + + + + + + +

+mdevd
+Software
+skarnet.org +

+ +

The mdevd program

+ +

+mdevd is an uevent manager. It reads a series of +uevents on its stdin; for every uevent it reads, it performs +actions according to its configuration file. Actions can +be inserting a kernel module, creating or modifying device +entries in /dev, etc. +

+ +

+ mdevd's configuration file uses the exact same +format as +mdev. +The differences between mdevd and mdev are: +

+ +
    +
  • mdev needs to be registered as a hotplug manager and the +kernel spawns an instance of mdev per uevent; for every uevent, +mdev has to parse its configuration file. By contrast, there +is only one instance of mdevd, reading a series of uevents and +performing actions without forking; the configuration file is +read and parsed only once.
  • +
  • mdevd reads uevents on its stdin. It is not suitable as +a hotplug manager, and it does not connect to the netlink itself +either. It is meant to be used in conjunction with +mdevd-netlink, which reads +uevents from the netlink, or with +mdevd-coldplug, which generates +coldplug uevents.
  • +
+ +

Interface

+ +
+     mdevd [ -v verbosity ] [ -f conffile ] [ -n ] [ -s slashsys ] [ -d slashdev ] [ -F fwbase ]
+
+ +
    +
  • mdevd reads and parses its configuration file /etc/mdev.conf.
  • +
  • It then reads its stdin, waiting for uevents. +
  • It exits when it has finished scanning.
  • +
+ +

Exit codes

+ +
    +
  • 0: EOF read on mdevd's stdin
  • +
  • 1: received an invalid event
  • +
  • 100: wrong usage
  • +
  • 111: system call failed
  • +
+ +

Signals

+ +

+ mdevd reacts to the following signals: +

+ +
    +
  • SIGHUP: re-read the configuration file
  • +
+ +

Options

+ +
    +
  • -v verbosity : be more or less verbose. +Default verbosity is 1. 0 will only print fatal error messages, 3 or more +is seriously verbose debugging.
  • +
  • -n : dry run. mdevd will not create or delete +device nodes, and it will not spawn commands. Instead, it will print to stdout +the commands it would have spawned.
  • +
  • -f conffile : read the configuration +file from conffile. Default is /etc/mdev.conf.
  • +
  • -s slashsys : assume the sysfs +pseudo-filesystem is mounted on slashsys. Default is /sys.
  • +
  • -d slashdev : assume the device nodes +are to be found in slashdev. Default is /dev.
  • +
  • -F fwbase : assume the firmware files, if any, +are to be found in fwbase. Default is /lib/firmware.
  • +
+ +

Configuration file

+ +

+ mdevd uses mdev's configuration file format. +A good mdev.conf example is available +here. +

+ +

+ If mdevd cannot find its configuration file, it will use a simple, basic default +configuration where it can create device nodes as root or delete them, and does +nothing else. +

+ +

Notes

+ +
    +
  • Strictly speaking, mdevd is a short-lived program: it has +a normal exit condition, which is when it receives EOF on its stdin. +That allows it to work as a coldplug manager when paired with +mdevd-coldplug.
  • +
  • However, when paired with mdevd-netlink, +it acts as a daemon, because mdev-netlink normally never exits until +the end of the machine lifetime and never closes its stdout, so +mdevd's stdin never receives EOF.
  • +
+ + + diff --git a/doc/upgrade.html b/doc/upgrade.html new file mode 100644 index 0000000..06c1654 --- /dev/null +++ b/doc/upgrade.html @@ -0,0 +1,28 @@ + + + + + + mdevd: how to upgrade + + + + + + +

+mdevd
+Software
+skarnet.org +

+ +

What has changed in mdevd

+ +

in 0.0.1.0

+ +
    +
  • Initial release.
  • +
+ + + diff --git a/package/deps-build b/package/deps-build new file mode 100644 index 0000000..05d5af4 --- /dev/null +++ b/package/deps-build @@ -0,0 +1 @@ +/package/prog/skalibs diff --git a/package/deps.mak b/package/deps.mak new file mode 100644 index 0000000..64c7965 --- /dev/null +++ b/package/deps.mak @@ -0,0 +1,14 @@ +# +# This file has been generated by tools/gen-deps.sh +# + +src/mdevd/mdevd-coldplug.o src/mdevd/mdevd-coldplug.lo: src/mdevd/mdevd-coldplug.c src/mdevd/mdevd.h +src/mdevd/mdevd-netlink.o src/mdevd/mdevd-netlink.lo: src/mdevd/mdevd-netlink.c src/mdevd/mdevd.h +src/mdevd/mdevd.o src/mdevd/mdevd.lo: src/mdevd/mdevd.c src/mdevd/mdevd.h + +mdevd: EXTRA_LIBS := +mdevd: src/mdevd/mdevd.o -lskarnet +mdevd-coldplug: EXTRA_LIBS := +mdevd-coldplug: src/mdevd/mdevd-coldplug.o -lskarnet +mdevd-netlink: EXTRA_LIBS := +mdevd-netlink: src/mdevd/mdevd-netlink.o -lskarnet diff --git a/package/info b/package/info new file mode 100644 index 0000000..41df5d6 --- /dev/null +++ b/package/info @@ -0,0 +1,4 @@ +package=mdevd +version=0.0.1.0 +category=admin +package_macro_name=MDEVD diff --git a/package/modes b/package/modes new file mode 100644 index 0000000..63c3a48 --- /dev/null +++ b/package/modes @@ -0,0 +1,3 @@ +mdevd 0755 +mdevd-netlink 0755 +mdevd-coldplug 0755 diff --git a/package/targets.mak b/package/targets.mak new file mode 100644 index 0000000..6b16bfa --- /dev/null +++ b/package/targets.mak @@ -0,0 +1,7 @@ +BIN_TARGETS := \ +mdevd \ +mdevd-netlink \ +mdevd-coldplug + +LIBEXEC_TARGETS := + diff --git a/tools/gen-deps.sh b/tools/gen-deps.sh new file mode 100755 index 0000000..5c96dd1 --- /dev/null +++ b/tools/gen-deps.sh @@ -0,0 +1,89 @@ +#!/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 "lib${file}.a.xyzzy:$deps" + echo "lib${file}.so.xyzzy: EXTRA_LIBS :=$libs" + echo "lib${file}.so.xyzzy:$(echo "$deps" | sed 's/\.o/.lo/g')" + done + + for file in $(ls -1 src/$dir/deps-exe) ; do + deps= + libs= + while read dep ; do + if echo $dep | grep -q -- \\.o$ ; then + dep="src/$dir/$dep" + fi + if echo $dep | grep -q -- '^\${.*_LIB}' ; then + libs="$libs $dep" + else + deps="$deps $dep" + fi + done < src/$dir/deps-exe/$file + echo "$file: EXTRA_LIBS :=$libs" + echo "$file: src/$dir/$file.o$deps" + done +done diff --git a/tools/install.sh b/tools/install.sh new file mode 100755 index 0000000..89f9428 --- /dev/null +++ b/tools/install.sh @@ -0,0 +1,64 @@ +#!/bin/sh + +usage() { + echo "usage: $0 [-D] [-l] [-m mode] src dst" 1>&2 + exit 1 +} + +mkdirp=false +symlink=false +mode=0755 + +while getopts Dlm: name ; do + case "$name" in + D) mkdirp=true ;; + l) symlink=true ;; + m) mode=$OPTARG ;; + ?) usage ;; + esac +done +shift $(($OPTIND - 1)) + +test "$#" -eq 2 || usage +src=$1 +dst=$2 +tmp="$dst.tmp.$$" + +case "$dst" in + */) echo "$0: $dst ends in /" 1>&2 ; exit 1 ;; +esac + +set -C +set -e + +if $mkdirp ; then + umask 022 + case "$2" in + */*) mkdir -p "${dst%/*}" ;; + esac +fi + +trap 'rm -f "$tmp"' EXIT INT QUIT TERM HUP + +umask 077 + +if $symlink ; then + ln -s "$src" "$tmp" +else + cat < "$1" > "$tmp" + chmod "$mode" "$tmp" +fi + +mv -f "$tmp" "$dst" +if test -d "$dst" ; then + rm -f "$dst/$(basename $tmp)" + if $symlink ; then + mkdir "$tmp" + ln -s "$src" "$tmp/$(basename $dst)" + mv -f "$tmp/$(basename $dst)" "${dst%/*}" + rmdir "$tmp" + else + echo "$0: $dst is a directory" 1>&2 + exit 1 + fi +fi -- cgit v1.3.1