From 330f54ac7f780872223f9cac62347393ffb4ef86 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Thu, 6 Jul 2017 21:42:01 +0000 Subject: Initial commit --- .gitignore | 9 + AUTHORS | 4 + COPYING | 13 + INSTALL | 166 +++++++++++ Makefile | 147 +++++++++ NEWS | 6 + README | 31 ++ configure | 429 +++++++++++++++++++++++++++ doc/index.html | 110 +++++++ doc/libwpactrl/index.html | 233 +++++++++++++++ doc/quickstart.html | 33 +++ doc/upgrade.html | 28 ++ package/deps-build | 1 + package/deps.mak | 21 ++ package/info | 4 + package/modes | 1 + package/targets.mak | 5 + src/include/bcnm/wpactrl.h | 210 +++++++++++++ src/libwpactrl/deps-lib/wpactrl | 12 + src/libwpactrl/wpactrl-internal.h | 18 ++ src/libwpactrl/wpactrl_command.c | 41 +++ src/libwpactrl/wpactrl_end.c | 11 + src/libwpactrl/wpactrl_fd_recv.c | 47 +++ src/libwpactrl/wpactrl_fd_timed_recv.c | 29 ++ src/libwpactrl/wpactrl_filter_add.c | 12 + src/libwpactrl/wpactrl_filter_exact_search.c | 12 + src/libwpactrl/wpactrl_filter_remove.c | 16 + src/libwpactrl/wpactrl_query.c | 11 + src/libwpactrl/wpactrl_querysa.c | 15 + src/libwpactrl/wpactrl_start.c | 45 +++ src/libwpactrl/wpactrl_update.c | 48 +++ src/libwpactrl/wpactrl_zero.c | 5 + tools/gen-deps.sh | 89 ++++++ tools/install.sh | 64 ++++ 34 files changed, 1926 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/libwpactrl/index.html create mode 100644 doc/quickstart.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/include/bcnm/wpactrl.h create mode 100644 src/libwpactrl/deps-lib/wpactrl create mode 100644 src/libwpactrl/wpactrl-internal.h create mode 100644 src/libwpactrl/wpactrl_command.c create mode 100644 src/libwpactrl/wpactrl_end.c create mode 100644 src/libwpactrl/wpactrl_fd_recv.c create mode 100644 src/libwpactrl/wpactrl_fd_timed_recv.c create mode 100644 src/libwpactrl/wpactrl_filter_add.c create mode 100644 src/libwpactrl/wpactrl_filter_exact_search.c create mode 100644 src/libwpactrl/wpactrl_filter_remove.c create mode 100644 src/libwpactrl/wpactrl_query.c create mode 100644 src/libwpactrl/wpactrl_querysa.c create mode 100644 src/libwpactrl/wpactrl_start.c create mode 100644 src/libwpactrl/wpactrl_update.c create mode 100644 src/libwpactrl/wpactrl_zero.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..6334de8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +*.o +*.a +*.lo +*.so +*.so.* +*.a.xyzzy +*.so.xyzzy +config.mak +src/include/bcnm/config.h diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..c1a5cf7 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,4 @@ +Main author: + Laurent Bercot + +Thanks to: diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..518dac1 --- /dev/null +++ b/COPYING @@ -0,0 +1,13 @@ +Copyright (c) 2016-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..20e5d14 --- /dev/null +++ b/INSTALL @@ -0,0 +1,166 @@ +Build Instructions +------------------ + +* Requirements + ------------ + + - A Linux-based system with a standard C development environment + - GNU make version 3.81 or later + - skalibs version 2.5.1.1 or later: http://skarnet.org/software/skalibs/ + + This software is Linux-specific. It will run on a Linux kernel, +version 2.6.32 or later. However, it is not 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 binaries in /usr/bin and the libraries in /usr/lib. + + You can strip the binaries and libraries of their extra symbols via +"make strip" before the "make install" phase. It will shave a few bytes +off them. + + +* Customization + ------------- + + You can customize paths via flags given to configure. + See ./configure --help for a list of all available configure options. + + +* Environment variables + --------------------- + + Controlling a build process via environment variables is a big and +dangerous hammer. You should try and pass flags to configure instead; +nevertheless, a few standard environment variables are recognized. + + If the CC environment variable is set, its value will override compiler +detection by configure. The --host=HOST option will still add a HOST- +prefix to the value of CC. + + The values of CFLAGS, CPPFLAGS and LDFLAGS will be appended to flags +auto-detected by configure. To entirely override the flags set by +configure instead, use make variables. + + +* Make variables + -------------- + + You can invoke make with a few variables for more configuration. + + CC, CFLAGS, CPPFLAGS, LDFLAGS, LDLIBS, AR, RANLIB, STRIP, INSTALL and +CROSS_COMPILE can all be overridden on the make command line. This is +an even bigger hammer than running ./configure with environment +variables, so it is advised to only do this when it is the only way of +obtaining the behaviour you want. + + DESTDIR can be given on the "make install" command line in order to +install to a staging directory. + + +* Shared libraries + ---------------- + + Software from skarnet.org is small enough that shared libraries are +generally not worth using. Static linking is simpler and incurs less +runtime overhead and less points of failure: so by default, shared +libraries are not built and binaries are linked against the static +versions of the skarnet.org libraries. Nevertheless, you can: + * build shared libraries: --enable-shared + * link binaries against shared libraries: --disable-allstatic + + +* Static binaries + --------------- + + By default, binaries are linked against static versions of all the +libraries they depend on, except for the libc. You can enforce +linking against the static libc with --enable-static-libc. + + (If you are using a GNU/Linux system, be aware that the GNU libc +behaves badly with static linking and produces huge executables, +which is why it is not the default. Other libcs are better suited +to static linking, for instance musl: http://musl-libc.org/) + + +* Cross-compilation + ----------------- + + skarnet.org packages centralize all the difficulty of +cross-compilation in one place: skalibs. Once you have +cross-compiled skalibs, the rest is easy. + + * Use the --host=HOST option to configure, HOST being the triplet +for your target. + * Make sure your cross-toolchain binaries (i.e. prefixed with HOST-) +are accessible via your PATH environment variable. + * Make sure to use the correct version of skalibs for your target, +and the correct sysdeps directory, making use of the +--with-include, --with-lib, --with-dynlib and --with-sysdeps +options as necessary. + + +* The slashpackage convention + --------------------------- + + The slashpackage convention (http://cr.yp.to/slashpackage.html) +is a package installation scheme that provides a few guarantees +over other conventions such as the FHS, for instance fixed +absolute pathnames. skarnet.org packages support it: use the +--enable-slashpackage option to configure, or +--enable-slashpackage=DIR for a prefixed DIR/package tree. +This option will activate slashpackage support during the build +and set slashpackage-compatible installation directories. +If $package_home is the home of the package, defined as +DIR/package/$category/$package-$version with the variables +read from the package/info file, then: + + --dynlibdir is set to $package_home/library.so + --bindir is set to $package_home/command + --sbindir is also set to $package_home/command (slashpackage +differentiates root-only binaries by their Unix rights, not their +location in the filesystem) + --libexecdir is also set to $package_home/command (slashpackage +does not need a specific directory for internal binaries) + --libdir is set to $package_home/library + --includedir is set to $package_home/include + + --prefix is pretty much ignored when you use --enable-slashpackage. +You should probably not use both --enable-slashpackage and --prefix. + + When using slashpackage, two additional Makefile targets are +available after "make install": + - "make update" changes the default version of the software to the +freshly installed one. (This is useful when you have several installed +versions of the same software, which slashpackage supports.) + - "make -L global-links" adds links from /command and /library.so to the +default version of the binaries and shared libraries. The "-L" option to +make is necessary because targets are symbolic links, and the default make +behaviour is to check the pointed file's timestamp and not the symlink's +timestamp. + + +* Absolute pathnames + ------------------ + + You may want to use fixed absolute pathnames even if you're not +following the slashpackage convention: for instance, the Nix packaging +system prefers calling binaries with immutable paths rather than rely on +PATH resolution. If you are in that case, use the --enable-absolute-paths +option to configure. This will ensure that programs calling binaries from +this package will call them with their full installation path (in bindir) +without relying on a PATH search. + + +* Out-of-tree builds + ------------------ + + skarnet.org packages do not support out-of-tree builds. They +are small, so it does not cost much to duplicate the entire +source tree if parallel builds are needed. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bffc468 --- /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 := -iquote src/include-local -Isrc/include $(CPPFLAGS) +CFLAGS_ALL := $(CFLAGS) -pipe -Wall +CFLAGS_SHARED := -fPIC +LDFLAGS_ALL := $(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 bcnm. diff --git a/configure b/configure new file mode 100755 index 0000000..644c6ce --- /dev/null +++ b/configure @@ -0,0 +1,429 @@ +#!/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 $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= +CFLAGS_AUTO="$CFLAGS" +CPPFLAGS_AUTO="-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -O2 $CPPFLAGS" +LDFLAGS_AUTO="$LDFLAGS" +LDFLAGS_SHARED=-shared +LDFLAGS_NOSHARED= +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 +slashpackage=false +abspath=false +sproot= +home= +exthome= +allstatic=true +evenmorestatic=false +addincpath='' +addlibspath='' +addlibdpath='' +vpaths='' +vpathd='' +build= + +for arg ; do + case "$arg" in + --help) usage ;; + --prefix=*) prefix=${arg#*=} ;; + --exec-prefix=*) exec_prefix=${arg#*=} ;; + --dynlibdir=*) dynlibdir=${arg#*=} ;; + --libexecdir=*) libexecdir=${arg#*=} ;; + --bindir=*) bindir=${arg#*=} ;; + --libdir=*) libdir=${arg#*=} ;; + --includedir=*) includedir=${arg#*=} ;; + --with-sysdeps=*) sysdeps=${arg#*=} manualsysdeps=true ;; + --with-include=*) var=${arg#*=} ; stripdir var ; addincpath="$addincpath -I$var" ;; + --with-lib=*) var=${arg#*=} ; stripdir var ; addlibspath="$addlibspath -L$var" ; vpaths="$vpaths $var" ;; + --with-dynlib=*) var=${arg#*=} ; stripdir var ; addlibdpath="$addlibdpath -L$var" ; vpathd="$vpathd $var" ;; + --enable-shared|--enable-shared=yes) shared=true ;; + --disable-shared|--enable-shared=no) shared=false ;; + --enable-static|--enable-static=yes) static=true ;; + --disable-static|--enable-static=no) static=false ;; + --enable-allstatic|--enable-allstatic=yes) allstatic=true ;; + --disable-allstatic|--enable-allstatic=no) allstatic=false ; evenmorestatic=false ;; + --enable-static-libc|--enable-static-libc=yes) allstatic=true ; evenmorestatic=true ;; + --disable-static-libc|--enable-static-libc=no) evenmorestatic=false ;; + --enable-slashpackage=*) sproot=${arg#*=} ; slashpackage=true ; ;; + --enable-slashpackage) sproot= ; slashpackage=true ;; + --disable-slashpackage) sproot= ; slashpackage=false ;; + --enable-absolute-paths|--enable-absolute-paths=yes) abspath=true ;; + --disable-absolute-paths|--enable-absolute-paths=no) abspath=false ;; + --enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;; + --host=*|--target=*) target=${arg#*=} ;; + --build=*) build=${arg#*=} ;; + -* ) echo "$0: unknown option $arg" ;; + *=*) ;; + *) target=$arg ;; + esac +done + +# Add /usr in the default default case +if test -z "$prefix" ; then + if test "$libdir" = '$prefix/lib/$package' ; then + libdir=/usr/lib/$package + fi + if test "$includedir" = '$prefix/include' ; then + includedir=/usr/include + fi + if test "$sysdeps" = '$prefix/lib/skalibs/sysdeps' ; then + sysdeps=/usr/lib/skalibs/sysdeps + fi +fi + +# Expand installation directories +stripdir prefix +for i in exec_prefix dynlibdir libexecdir bindir libdir includedir sysdeps sproot ; do + eval tmp=\${$i} + eval $i=$tmp + stripdir $i +done + +# Get usable temp filenames +i=0 +set -C +while : ; do + i=$(($i+1)) + tmpc="./tmp-configure-$$-$PPID-$i.c" + tmpe="./tmp-configure-$$-$PPID-$i.tmp" + 2>|/dev/null > "$tmpc" && break + 2>|/dev/null > "$tmpe" && break + test "$i" -gt 50 && fail "$0: cannot create temporary files" +done +set +C +trap 'rm -f "$tmpc" "$tmpe"' EXIT ABRT INT QUIT TERM HUP + +# Set slashpackage values +if $slashpackage ; then + home=${sproot}/package/${category}/${package}-${version} + exthome=${sproot}/package/${category}/${package} + if $manualsysdeps ; then + : + else + sysdeps=${sproot}/package/prog/skalibs/sysdeps + fi + extbinprefix=${exthome}/command + dynlibdir=${home}/library.so + bindir=${home}/command + libdir=${home}/library + libexecdir=$bindir + includedir=${home}/include + while read dep ; do + addincpath="$addincpath -I${sproot}${dep}/include" + vpaths="$vpaths ${sproot}${dep}/library" + addlibspath="$addlibspath -L${sproot}${dep}/library" + vpathd="$vpathd ${sproot}${dep}/library.so" + addlibdpath="$addlibdpath -L${sproot}${dep}/library.so" + done < package/deps-build +fi + +# Find a C compiler to use +if test -n "$target" && test x${build} != x${target} ; then + cross=${target}- +else + cross= +fi +echo "checking for C compiler..." +trycc ${cross}${CC} +trycc ${cross}gcc +trycc ${cross}clang +trycc ${cross}cc +test -n "$CC_AUTO" || { echo "$0: cannot find a C compiler" ; exit 1 ; } +echo " ... $CC_AUTO" +echo "checking whether C compiler works... " +echo "typedef int x;" > "$tmpc" +if $CC_AUTO $CPPFLAGS_AUTO $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..." +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_AUTO -fomit-frame-pointer +tryflag CFLAGS_AUTO -fno-exceptions +tryflag CFLAGS_AUTO -fno-unwind-tables +tryflag CFLAGS_AUTO -fno-asynchronous-unwind-tables +tryflag CPPFLAGS_AUTO -Wa,--noexecstack +tryflag CFLAGS_AUTO -fno-stack-protector +tryflag CPPFLAGS_AUTO -Werror=implicit-function-declaration +tryflag CPPFLAGS_AUTO -Werror=implicit-int +tryflag CPPFLAGS_AUTO -Werror=pointer-sign +tryflag CPPFLAGS_AUTO -Werror=pointer-arith +tryflag 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_AUTO -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}} +CFLAGS := $CFLAGS_AUTO +CPPFLAGS := $CPPFLAGS_AUTO +LDFLAGS := $LDFLAGS_AUTO +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..ae475e1 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,110 @@ + + + + + + bcnm - a better client network manager + + + + + + +

+Software
+skarnet.org +

+ +

bcnm

+ +

What is it ?

+ +

+ bcnm is a client network manager: it automatically handles network +connections for a client machine. It supports Ethernet and Wi-Fi. +IP addresses can be attributed statically or via DHCP. +

+ +

+ + This is very much a work in progress. Do not expect full functionality +in the short or even middle term. + +

+ +
+ +

Installation

+ +

Requirements

+ +
    +
  • A Linux-based system with a standard C development environment
  • +
  • GNU make, version 3.81 or later
  • +
  • skalibs version +2.5.1.1 or later
  • +
+ +

Licensing

+ +

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

+ +

Download

+ +
    +
  • The current released version of bcnm is +0.0.1.0.
  • +
  • Alternatively, you can checkout a copy of the +bcnm +git repository: +
     git clone git://git.skarnet.org/bcnm 
  • +
  • There's also a +GitHub mirror +of the bcnm 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 bcnm 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. +

+ +
    +
+ +

Libraries

+ + + +

Related resources

+ +
    +
  • bcnm is discussed on the +skaware mailing-list.
  • +
+ + + diff --git a/doc/libwpactrl/index.html b/doc/libwpactrl/index.html new file mode 100644 index 0000000..845cc7b --- /dev/null +++ b/doc/libwpactrl/index.html @@ -0,0 +1,233 @@ + + + + + + bcnm: the wpactrl library interface + + + + + +

+bcn,
+Software
+skarnet.org +

+ +

The wpactrl library interface

+ +

+wpactrl is a library designed to interface a client +with the wpa_supplicant +program, in a smaller, cleaner, more user-friendly and more +packager-friendly way than the wpa_ctrl interface that +comes with the wpa_supplicant +distribution. +

+ +

Compiling

+ +
    +
  • Use #include <bcnm/wpactrl.h>
  • +
+ +

Linking

+ +
    +
  • Make sure the bcnm libraries, as well as the skalibs +libraries, are visible in your library search path.
  • +
  • Link against -lwpactrl and -lskarnet. +Also add `cat $sysdeps/socket.lib $sysdeps/tainnow.lib` +to the end of your command line invoking the linker, in order +to be portable to libcs that put socket or time functions into +separate libraries. +($sysdeps stands for your skalibs sysdeps directory.)
  • +
+ + +

Programming

+ +

+ The bcnm/wpactrl.h header is the reference for the exact +function prototypes. +

+ +

General usage

+ +

+ libwpactrl stores its information in a wpactrl_t structure. +Such a structure must be allocated (can be declared in the stack) and +initialized to WPACTRL_ZERO before use. The address of that wpactrl_t +structure is then used as a handle and given as an argument to all the +wpactrl_* function calls. +

+ +

Connections

+ +

+ A wpactrl_t instance represents two connections to a wpa_supplicant +program: an attached one and a detached one. For proper operation, +it is important to regularly read the data from the attached connection. This is +achieved by calling the wpactrl_update() function whenever data is available +on the attached connection; this is notified by the connection's fd becoming +readable. The attached connection's fd can be obtained via the wpactrl_fd() +function. So, proper usage of a wpactrl_t instance involves an asynchronous +event loop. +

+ +

Synchronous functions

+ +

+ The bulk of libwpactrl functions take two extra arguments at the end, named +deadline and stamp, of type +tain_t. This means +they are synchronous function calls, and the extra arguments are there to ensure +those calls do not block forever. +

+ +

+deadline is an absolute date: if the function has not returned when this +date is reached, it will immediately return with a code meaning "failure" and +errno set to ETIMEDOUT. stamp must be first initialized to an +accurate enough approximation of the current time, for instance via skalibs' +tain_now() function; it will then be automatically updated by the +libwpactrl function calls to always contain (an accurate enough approximation +of) the current time. +

+ +

+ skalibs can keep track of the +timestamp for you, in the global STAMP variable. All libwpactrl +functions taking deadline and stamp arguments also have a +version with a name ending in _g, that only takes a deadline +argument, and assumes the STAMP variable always contains (an accurate +enough approximation of) the current time. +

+ +

+ Those synchronous function calls normally return almost instantly: there should +be no blocking code path between the function call and its return. Nevertheless, +since they involve communication with a complex wpa_supplicant process, +it's impossible to guarantee that they will never block, so the deadline pattern +is there to set a cap on the amount of time they block. A deadline set a few +seconds into the future should be enough. +

+ + +

Starting and stopping a session

+ +

+ int wpactrl_start (wpactrl_t *a, char const *path, tain_t const *deadline, tain_t *stamp)
+Starts a session with a wpa_supplicant instance listening on a Unix socket +at path. +The function returns 1 if it succeeds, or 0 (and sets errno) if +it fails. +

+ +

+ int wpactrl_end (wpactrl_t *a)
+Ends the session, freeing all used resources. +

+ +

Low-level command sending

+ +

+ ssize_t wpactrl_query (wpactrl_t *a, char const *q, size_t qlen, char *ans, size_t anslen, tain_t const *deadline, tain_t *stamp)
+Sends the query q of size qlen to the connected instance +of wpa_supplicant, and reads its answer into the buffer pointed to by +ans. Returns -1 in case of failure, or the number of bytes of +the answer in case of success. Returns -1 with errno set to EMSGSIZE if +the answer is bigger than anslen bytes. +

+ +

+ ssize_t wpactrl_querysa (wpactrl_t *a, char const *q, size_t qlen, stralloc *sa, tain_t const *deadline, tain_t *stamp)
+Sends the query q of size qlen to the connected instance +of wpa_supplicant, and reads its answer into the +stralloc +pointed to by sa. Returns 1 if it succeeds and 0 if it fails. +

+ +

+ wparesponse_t wpactrl_command (wpactrl_t *a, char const *q, size_t qlen, tain_t const *deadline, tain_t *stamp)
+Sends the command q of size qlen to the connected instance +of wpa_supplicant, and returns its answer under the form of a +wparesponse_t, which is an enumeration defined in the +bcnm/wpactrl.h header. This function is meant to be used +with commands returning a well-known value, such as RECONFIGURE +(returning OK or FAIL) or PING +(returning PONG). +

+ +

Reading from the attached connection

+ +

+ int wpactrl_update (wpactrl_t *a)
+Reads unsolicited messages from wpa_supplicant. If the messages +are whitelisted, it keeps them, otherwise it discards them. +The function returns the number of messages that have been read, +or -1 in case of failure. A positive number does not mean that +all pending messages have been read: there is a cap on the +number of messages that can be consecutively read, to prevent +a spamming wpa_supplicant from monopolizing your program. +

+ +

+ char *wpactrl_data (wpactrl_t *a)
+Returns a pointer to the unsolicited messages from wpa_supplicant +that have been read by wpactrl_update() but haven't been +acknowledged yet. +

+ +

+ char *wpactrl_datalen (wpactrl_t *a)
+Returns the length of unsolicited messages from wpa_supplicant +that have been read by wpactrl_update() but haven't been +acknowledged yet. +

+ +

+ void wpactrl_ackdata (wpactrl_t *a) +Acknowledges reading the latest batch of unsolicited messages +from wpa_supplicant: allows the next invocation of +wpactrl_update() to reuse the storage. +

+ +

+ int wpactrl_filter_add (wpactrl_t *a, char const *prefix)
+Adds prefix to the whitelist. Unsolicited messages from +wpa_supplicant will be stored and made available to the application +if they start with %lt;priority>prefix, +priority being a single nonzero digit. If the filter is +activated (which is the default), then only messages matching prefixes +registered via wpactrl_filter_add() will be stored, and all +other messages will be discarded. The function returns +1 if it succeeds and 0 if it fails. +

+ +

+ void wpactrl_filter_remove (wpactrl_t *a, char const *prefix)
+Removes prefix from the whitelist. +

+ +

+ void wpactrl_filter_activate (wpactrl_t *a) +Activates the message filter. Unsolicited messages from +wpa_supplicant will be discarded unless they are explicitly +whitelisted by a call to wpactrl_filter_add(). This +is the default. +

+ +

+ void wpactrl_filter_deactivate (wpactrl_t *a) +Dectivates the message filter. All the unsolicited messages from +wpa_supplicant will be stored and made available to the +application. +

+ +

Higher-level commands

+ + + diff --git a/doc/quickstart.html b/doc/quickstart.html new file mode 100644 index 0000000..e9bbd3f --- /dev/null +++ b/doc/quickstart.html @@ -0,0 +1,33 @@ + + + + + + bcnm: quickstart and FAQ + + + + + + +

+bcnm
+Software
+skarnet.org +

+ +

Quickstart and FAQ for bcnm

+ +

Quickstart

+ + + + + diff --git a/doc/upgrade.html b/doc/upgrade.html new file mode 100644 index 0000000..1c96b68 --- /dev/null +++ b/doc/upgrade.html @@ -0,0 +1,28 @@ + + + + + + bcnm: how to upgrade + + + + + + +

+bcnm
+Software
+skarnet.org +

+ +

What has changed in bcnm

+ +

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..e391903 --- /dev/null +++ b/package/deps.mak @@ -0,0 +1,21 @@ +# +# This file has been generated by tools/gen-deps.sh +# + +src/libwpactrl/wpactrl-internal.h: src/include/bcnm/wpactrl.h +src/libwpactrl/wpactrl_command.o src/libwpactrl/wpactrl_command.lo: src/libwpactrl/wpactrl_command.c src/include/bcnm/wpactrl.h +src/libwpactrl/wpactrl_end.o src/libwpactrl/wpactrl_end.lo: src/libwpactrl/wpactrl_end.c src/include/bcnm/wpactrl.h +src/libwpactrl/wpactrl_fd_recv.o src/libwpactrl/wpactrl_fd_recv.lo: src/libwpactrl/wpactrl_fd_recv.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl-internal.h +src/libwpactrl/wpactrl_fd_timed_recv.o src/libwpactrl/wpactrl_fd_timed_recv.lo: src/libwpactrl/wpactrl_fd_timed_recv.c src/libwpactrl/wpactrl-internal.h +src/libwpactrl/wpactrl_filter_add.o src/libwpactrl/wpactrl_filter_add.lo: src/libwpactrl/wpactrl_filter_add.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl-internal.h +src/libwpactrl/wpactrl_filter_exact_search.o src/libwpactrl/wpactrl_filter_exact_search.lo: src/libwpactrl/wpactrl_filter_exact_search.c +src/libwpactrl/wpactrl_filter_remove.o src/libwpactrl/wpactrl_filter_remove.lo: src/libwpactrl/wpactrl_filter_remove.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl-internal.h +src/libwpactrl/wpactrl_query.o src/libwpactrl/wpactrl_query.lo: src/libwpactrl/wpactrl_query.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl-internal.h +src/libwpactrl/wpactrl_querysa.o src/libwpactrl/wpactrl_querysa.lo: src/libwpactrl/wpactrl_querysa.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl-internal.h +src/libwpactrl/wpactrl_start.o src/libwpactrl/wpactrl_start.lo: src/libwpactrl/wpactrl_start.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl-internal.h +src/libwpactrl/wpactrl_update.o src/libwpactrl/wpactrl_update.lo: src/libwpactrl/wpactrl_update.c src/include/bcnm/wpactrl.h src/libwpactrl/wpactrl-internal.h +src/libwpactrl/wpactrl_zero.o src/libwpactrl/wpactrl_zero.lo: src/libwpactrl/wpactrl_zero.c src/include/bcnm/wpactrl.h + +libwpactrl.a.xyzzy: src/libwpactrl/wpactrl_command.o src/libwpactrl/wpactrl_end.o src/libwpactrl/wpactrl_fd_recv.o src/libwpactrl/wpactrl_fd_timed_recv.o src/libwpactrl/wpactrl_filter_add.o src/libwpactrl/wpactrl_filter_exact_search.o src/libwpactrl/wpactrl_filter_remove.o src/libwpactrl/wpactrl_query.o src/libwpactrl/wpactrl_querysa.o src/libwpactrl/wpactrl_start.o src/libwpactrl/wpactrl_update.o src/libwpactrl/wpactrl_zero.o +libwpactrl.so.xyzzy: EXTRA_LIBS := +libwpactrl.so.xyzzy: src/libwpactrl/wpactrl_command.lo src/libwpactrl/wpactrl_end.lo src/libwpactrl/wpactrl_fd_recv.lo src/libwpactrl/wpactrl_fd_timed_recv.lo src/libwpactrl/wpactrl_filter_add.lo src/libwpactrl/wpactrl_filter_exact_search.lo src/libwpactrl/wpactrl_filter_remove.lo src/libwpactrl/wpactrl_query.lo src/libwpactrl/wpactrl_querysa.lo src/libwpactrl/wpactrl_start.lo src/libwpactrl/wpactrl_update.lo src/libwpactrl/wpactrl_zero.lo diff --git a/package/info b/package/info new file mode 100644 index 0000000..f7a708b --- /dev/null +++ b/package/info @@ -0,0 +1,4 @@ +package=bcnm +version=0.0.1.0 +category=admin +package_macro_name=BCNM diff --git a/package/modes b/package/modes new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/package/modes @@ -0,0 +1 @@ + diff --git a/package/targets.mak b/package/targets.mak new file mode 100644 index 0000000..ebc5af6 --- /dev/null +++ b/package/targets.mak @@ -0,0 +1,5 @@ +BIN_TARGETS := + +LIBEXEC_TARGETS := + +LIB_DEFS := WPACTRL=wpactrl diff --git a/src/include/bcnm/wpactrl.h b/src/include/bcnm/wpactrl.h new file mode 100644 index 0000000..af105c3 --- /dev/null +++ b/src/include/bcnm/wpactrl.h @@ -0,0 +1,210 @@ +/* ISC license. */ + +#ifndef BCNM_WPACTRL_H +#define BCNM_WPACTRL_H + +#include +#include +#include +#include + +typedef enum wparesponse_e wparesponse_t, *wparesponse_t_ref ; +enum wparesponse_e +{ + WPA_ERROR = -1, + WPA_OK = 0, + WPA_PONG, + WPA_UNKNOWNCOMMAND, + WPA_FAIL, + WPA_FAILBUSY, + WPA_FAILCHECKSUM, + WPA_FAILINVALIDPIN, + WPA_FAILCHANNELUNAVAILABLE, + WPA_FAILCHANNELUNSUPPORTED, + WPA_FAILINVALIDRANGE, + WPA_FAILTOOLONGRESPONSE, + WPA_FAILPBCOVERLAP, + WPA_FAILUNKNOWNUUID, + WPA_FAILNOAPSETTINGS, + WPA_FAILNOIFNAMEATTACH, + WPA_UNKNOWNRESPONSE +} ; + +typedef struct wpactrl_s wpactrl_t, *wpactrl_t_ref ; +struct wpactrl_s +{ + int fds ; + int fda ; + uint32_t options ; + stralloc data ; + stralloc filters ; +} ; +#define WPACTRL_ZERO { .fds = -1, .fda = -1, .options = 0, .data = STRALLOC_ZERO, .filters = STRALLOC_ZERO } + +#define WPACTRL_OPTION_NOFILTER 0x0001U + +extern wpactrl_t const wpactrl_zero ; + +extern int wpactrl_start (wpactrl_t *, char const *, tain_t const *, tain_t *) ; +#define wpactrl_start_g(a, path, deadline) wpactrl_start(a, path, (deadline), &STAMP) +extern void wpactrl_end (wpactrl_t *) ; + +extern wparesponse_t wpactrl_command (wpactrl_t *, char const *, size_t, tain_t const *, tain_t *) ; +#define wpactrl_command_g(a, q, qlen, deadline) wpactrl_command(a, q, qlen, (deadline), &STAMP) +extern ssize_t wpactrl_query (wpactrl_t *, char const *, size_t, char *, size_t, tain_t const *, tain_t *) ; +#define wpactrl_query_g(a, q, qlen, ans, ansmax, deadline) wpactrl_query(a, q, qlen, ans, ansmax, (deadline), &STAMP) +extern int wpactrl_querysa (wpactrl_t *, char const *, size_t, stralloc *, tain_t const *, tain_t *) ; +#define wpactrl_querysa_g(a, q, qlen, sa, deadline) wpactrl_querysa(a, q, qlen, sa, (deadline), &STAMP) + +extern int wpactrl_filter_add (wpactrl_t *, char const *) ; +extern void wpactrl_filter_remove (wpactrl_t *, char const *) ; + +#define wpactrl_filter_activate(a) ((a)->options &= ~(uint32_t)WPACTRL_OPTION_NOFILTER) +#define wpactrl_filter_deactivate(a) ((a)->options |= WPACTRL_OPTION_NOFILTER) + +extern int wpactrl_update (wpactrl_t *) ; +#define wpactrl_data(a) ((a)->data.s) +#define wpactrl_datalen(a) ((a)->data.len)) +#define wpactrl_ackdata(a) ((a)->data.len = 0) + + + /* + The following is taken from wpa_supplicant's wpa_ctrl.h. + */ + +#define WPA_CTRL_REQ "CTRL-REQ-" +#define WPA_CTRL_RSP "CTRL-RSP-" +#define WPA_EVENT_CONNECTED "CTRL-EVENT-CONNECTED " +#define WPA_EVENT_DISCONNECTED "CTRL-EVENT-DISCONNECTED " +#define WPA_EVENT_ASSOC_REJECT "CTRL-EVENT-ASSOC-REJECT " +#define WPA_EVENT_AUTH_REJECT "CTRL-EVENT-AUTH-REJECT " +#define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING " +#define WPA_EVENT_PASSWORD_CHANGED "CTRL-EVENT-PASSWORD-CHANGED " +#define WPA_EVENT_EAP_NOTIFICATION "CTRL-EVENT-EAP-NOTIFICATION " +#define WPA_EVENT_EAP_STARTED "CTRL-EVENT-EAP-STARTED " +#define WPA_EVENT_EAP_PROPOSED_METHOD "CTRL-EVENT-EAP-PROPOSED-METHOD " +#define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD " +#define WPA_EVENT_EAP_PEER_CERT "CTRL-EVENT-EAP-PEER-CERT " +#define WPA_EVENT_EAP_PEER_ALT "CTRL-EVENT-EAP-PEER-ALT " +#define WPA_EVENT_EAP_TLS_CERT_ERROR "CTRL-EVENT-EAP-TLS-CERT-ERROR " +#define WPA_EVENT_EAP_STATUS "CTRL-EVENT-EAP-STATUS " +#define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS " +#define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE " +#define WPA_EVENT_TEMP_DISABLED "CTRL-EVENT-SSID-TEMP-DISABLED " +#define WPA_EVENT_REENABLED "CTRL-EVENT-SSID-REENABLED " +#define WPA_EVENT_SCAN_STARTED "CTRL-EVENT-SCAN-STARTED " +#define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS " +#define WPA_EVENT_SCAN_FAILED "CTRL-EVENT-SCAN-FAILED " +#define WPA_EVENT_STATE_CHANGE "CTRL-EVENT-STATE-CHANGE " +#define WPA_EVENT_BSS_ADDED "CTRL-EVENT-BSS-ADDED " +#define WPA_EVENT_BSS_REMOVED "CTRL-EVENT-BSS-REMOVED " +#define WPA_EVENT_NETWORK_NOT_FOUND "CTRL-EVENT-NETWORK-NOT-FOUND " +#define WPA_EVENT_SIGNAL_CHANGE "CTRL-EVENT-SIGNAL-CHANGE " +#define WPA_EVENT_BEACON_LOSS "CTRL-EVENT-BEACON-LOSS " +#define WPA_EVENT_REGDOM_CHANGE "CTRL-EVENT-REGDOM-CHANGE " +#define WPA_EVENT_CHANNEL_SWITCH "CTRL-EVENT-CHANNEL-SWITCH " +#define WPA_EVENT_SUBNET_STATUS_UPDATE "CTRL-EVENT-SUBNET-STATUS-UPDATE " +#define IBSS_RSN_COMPLETED "IBSS-RSN-COMPLETED " +#define WPA_EVENT_FREQ_CONFLICT "CTRL-EVENT-FREQ-CONFLICT " +#define WPA_EVENT_AVOID_FREQ "CTRL-EVENT-AVOID-FREQ " +#define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED " +#define WPS_EVENT_AP_AVAILABLE_PBC "WPS-AP-AVAILABLE-PBC " +#define WPS_EVENT_AP_AVAILABLE_AUTH "WPS-AP-AVAILABLE-AUTH " +#define WPS_EVENT_AP_AVAILABLE_PIN "WPS-AP-AVAILABLE-PIN " +#define WPS_EVENT_AP_AVAILABLE "WPS-AP-AVAILABLE " +#define WPS_EVENT_CRED_RECEIVED "WPS-CRED-RECEIVED " +#define WPS_EVENT_M2D "WPS-M2D " +#define WPS_EVENT_FAIL "WPS-FAIL " +#define WPS_EVENT_SUCCESS "WPS-SUCCESS " +#define WPS_EVENT_TIMEOUT "WPS-TIMEOUT " +#define WPS_EVENT_ACTIVE "WPS-PBC-ACTIVE " +#define WPS_EVENT_DISABLE "WPS-PBC-DISABLE " +#define WPS_EVENT_ENROLLEE_SEEN "WPS-ENROLLEE-SEEN " +#define WPS_EVENT_OPEN_NETWORK "WPS-OPEN-NETWORK " +#define WPS_EVENT_ER_AP_ADD "WPS-ER-AP-ADD " +#define WPS_EVENT_ER_AP_REMOVE "WPS-ER-AP-REMOVE " +#define WPS_EVENT_ER_ENROLLEE_ADD "WPS-ER-ENROLLEE-ADD " +#define WPS_EVENT_ER_ENROLLEE_REMOVE "WPS-ER-ENROLLEE-REMOVE " +#define WPS_EVENT_ER_AP_SETTINGS "WPS-ER-AP-SETTINGS " +#define WPS_EVENT_ER_SET_SEL_REG "WPS-ER-AP-SET-SEL-REG " +#define DPP_EVENT_AUTH_SUCCESS "DPP-AUTH-SUCCESS " +#define DPP_EVENT_NOT_COMPATIBLE "DPP-NOT-COMPATIBLE " +#define DPP_EVENT_RESPONSE_PENDING "DPP-RESPONSE-PENDING " +#define DPP_EVENT_SCAN_PEER_QR_CODE "DPP-SCAN-PEER-QR-CODE " +#define DPP_EVENT_CONF_RECEIVED "DPP-CONF-RECEIVED " +#define DPP_EVENT_CONF_SENT "DPP-CONF-SENT " +#define DPP_EVENT_CONF_FAILED "DPP-CONF-FAILED " +#define DPP_EVENT_CONFOBJ_SSID "DPP-CONFOBJ-SSID " +#define DPP_EVENT_CONNECTOR "DPP-CONNECTOR " +#define DPP_EVENT_C_SIGN_KEY "DPP-C-SIGN-KEY " +#define DPP_EVENT_NET_ACCESS_KEY "DPP-NET-ACCESS-KEY " +#define DPP_EVENT_MISSING_CONNECTOR "DPP-MISSING-CONNECTOR " +#define DPP_EVENT_NETWORK_ID "DPP-NETWORK-ID " +#define MESH_GROUP_STARTED "MESH-GROUP-STARTED " +#define MESH_GROUP_REMOVED "MESH-GROUP-REMOVED " +#define MESH_PEER_CONNECTED "MESH-PEER-CONNECTED " +#define MESH_PEER_DISCONNECTED "MESH-PEER-DISCONNECTED " +#define MESH_SAE_AUTH_FAILURE "MESH-SAE-AUTH-FAILURE " +#define MESH_SAE_AUTH_BLOCKED "MESH-SAE-AUTH-BLOCKED " +#define WMM_AC_EVENT_TSPEC_ADDED "TSPEC-ADDED " +#define WMM_AC_EVENT_TSPEC_REMOVED "TSPEC-REMOVED " +#define WMM_AC_EVENT_TSPEC_REQ_FAILED "TSPEC-REQ-FAILED " +#define P2P_EVENT_DEVICE_FOUND "P2P-DEVICE-FOUND " +#define P2P_EVENT_DEVICE_LOST "P2P-DEVICE-LOST " +#define P2P_EVENT_GO_NEG_REQUEST "P2P-GO-NEG-REQUEST " +#define P2P_EVENT_GO_NEG_SUCCESS "P2P-GO-NEG-SUCCESS " +#define P2P_EVENT_GO_NEG_FAILURE "P2P-GO-NEG-FAILURE " +#define P2P_EVENT_GROUP_FORMATION_SUCCESS "P2P-GROUP-FORMATION-SUCCESS " +#define P2P_EVENT_GROUP_FORMATION_FAILURE "P2P-GROUP-FORMATION-FAILURE " +#define P2P_EVENT_GROUP_STARTED "P2P-GROUP-STARTED " +#define P2P_EVENT_GROUP_REMOVED "P2P-GROUP-REMOVED " +#define P2P_EVENT_CROSS_CONNECT_ENABLE "P2P-CROSS-CONNECT-ENABLE " +#define P2P_EVENT_CROSS_CONNECT_DISABLE "P2P-CROSS-CONNECT-DISABLE " +#define P2P_EVENT_PROV_DISC_SHOW_PIN "P2P-PROV-DISC-SHOW-PIN " +#define P2P_EVENT_PROV_DISC_ENTER_PIN "P2P-PROV-DISC-ENTER-PIN " +#define P2P_EVENT_PROV_DISC_PBC_REQ "P2P-PROV-DISC-PBC-REQ " +#define P2P_EVENT_PROV_DISC_PBC_RESP "P2P-PROV-DISC-PBC-RESP " +#define P2P_EVENT_PROV_DISC_FAILURE "P2P-PROV-DISC-FAILURE" +#define P2P_EVENT_SERV_DISC_REQ "P2P-SERV-DISC-REQ " +#define P2P_EVENT_SERV_DISC_RESP "P2P-SERV-DISC-RESP " +#define P2P_EVENT_SERV_ASP_RESP "P2P-SERV-ASP-RESP " +#define P2P_EVENT_INVITATION_RECEIVED "P2P-INVITATION-RECEIVED " +#define P2P_EVENT_INVITATION_RESULT "P2P-INVITATION-RESULT " +#define P2P_EVENT_INVITATION_ACCEPTED "P2P-INVITATION-ACCEPTED " +#define P2P_EVENT_FIND_STOPPED "P2P-FIND-STOPPED " +#define P2P_EVENT_PERSISTENT_PSK_FAIL "P2P-PERSISTENT-PSK-FAIL id=" +#define P2P_EVENT_PRESENCE_RESPONSE "P2P-PRESENCE-RESPONSE " +#define P2P_EVENT_NFC_BOTH_GO "P2P-NFC-BOTH-GO " +#define P2P_EVENT_NFC_PEER_CLIENT "P2P-NFC-PEER-CLIENT " +#define P2P_EVENT_NFC_WHILE_CLIENT "P2P-NFC-WHILE-CLIENT " +#define P2P_EVENT_FALLBACK_TO_GO_NEG "P2P-FALLBACK-TO-GO-NEG " +#define P2P_EVENT_FALLBACK_TO_GO_NEG_ENABLED "P2P-FALLBACK-TO-GO-NEG-ENABLED " +#define ESS_DISASSOC_IMMINENT "ESS-DISASSOC-IMMINENT " +#define P2P_EVENT_REMOVE_AND_REFORM_GROUP "P2P-REMOVE-AND-REFORM-GROUP " +#define P2P_EVENT_P2PS_PROVISION_START "P2PS-PROV-START " +#define P2P_EVENT_P2PS_PROVISION_DONE "P2PS-PROV-DONE " +#define INTERWORKING_AP "INTERWORKING-AP " +#define INTERWORKING_BLACKLISTED "INTERWORKING-BLACKLISTED " +#define INTERWORKING_NO_MATCH "INTERWORKING-NO-MATCH " +#define INTERWORKING_ALREADY_CONNECTED "INTERWORKING-ALREADY-CONNECTED " +#define INTERWORKING_SELECTED "INTERWORKING-SELECTED " +#define CRED_ADDED "CRED-ADDED " +#define CRED_MODIFIED "CRED-MODIFIED " +#define CRED_REMOVED "CRED-REMOVED " +#define GAS_RESPONSE_INFO "GAS-RESPONSE-INFO " +#define GAS_QUERY_START "GAS-QUERY-START " +#define GAS_QUERY_DONE "GAS-QUERY-DONE " +#define ANQP_QUERY_DONE "ANQP-QUERY-DONE " +#define RX_ANQP "RX-ANQP " +#define RX_HS20_ANQP "RX-HS20-ANQP " +#define RX_HS20_ANQP_ICON "RX-HS20-ANQP-ICON " +#define RX_HS20_ICON "RX-HS20-ICON " +#define RX_MBO_ANQP "RX-MBO-ANQP " +#define HS20_SUBSCRIPTION_REMEDIATION "HS20-SUBSCRIPTION-REMEDIATION " +#define HS20_DEAUTH_IMMINENT_NOTICE "HS20-DEAUTH-IMMINENT-NOTICE " +#define EXT_RADIO_WORK_START "EXT-RADIO-WORK-START " +#define EXT_RADIO_WORK_TIMEOUT "EXT-RADIO-WORK-TIMEOUT " +#define RRM_EVENT_NEIGHBOR_REP_RXED "RRM-NEIGHBOR-REP-RECEIVED " +#define RRM_EVENT_NEIGHBOR_REP_FAILED "RRM-NEIGHBOR-REP-REQUEST-FAILED " + +#endif diff --git a/src/libwpactrl/deps-lib/wpactrl b/src/libwpactrl/deps-lib/wpactrl new file mode 100644 index 0000000..98cd9e6 --- /dev/null +++ b/src/libwpactrl/deps-lib/wpactrl @@ -0,0 +1,12 @@ +wpactrl_command.o +wpactrl_end.o +wpactrl_fd_recv.o +wpactrl_fd_timed_recv.o +wpactrl_filter_add.o +wpactrl_filter_exact_search.o +wpactrl_filter_remove.o +wpactrl_query.o +wpactrl_querysa.o +wpactrl_start.o +wpactrl_update.o +wpactrl_zero.o diff --git a/src/libwpactrl/wpactrl-internal.h b/src/libwpactrl/wpactrl-internal.h new file mode 100644 index 0000000..b271eae --- /dev/null +++ b/src/libwpactrl/wpactrl-internal.h @@ -0,0 +1,18 @@ +/* ISC license. */ + +#ifndef BCNM_WPACTRL_INTERNAL_H +#define BCNM_WPACTRL_INTERNAL_H + +#include +#include +#include +#include + +#define WPACTRL_PACKET_MAX 8192 +#define WPACTRL_RECV_MAX 32 + +extern ssize_t wpactrl_fd_recv (int, char *, size_t) ; +extern ssize_t wpactrl_fd_timed_recv (int, char *, size_t, tain_t const *, tain_t *) ; +extern size_t wpactrl_filter_exact_search (wpactrl_t const *, char const *) gccattr_pure ; + +#endif diff --git a/src/libwpactrl/wpactrl_command.c b/src/libwpactrl/wpactrl_command.c new file mode 100644 index 0000000..c29a58a --- /dev/null +++ b/src/libwpactrl/wpactrl_command.c @@ -0,0 +1,41 @@ +/* ISC license. */ + +#include +#include +#include + +#define WPARESPONSE_MAXLEN 28 + +wparesponse_t wpactrl_command (wpactrl_t *a, char const *s, size_t len, tain_t const *deadline, tain_t *stamp) +{ + static char const *wparesponses[] = + { + "OK\n", + "PONG\n", + "UNKNOWN COMMAND\n", + "FAIL\n", + "FAIL-BUSY\n", + "FAIL-CHECKSUM\n", + "FAIL-INVALID-PIN\n", + "FAIL-CHANNEL-UNAVAILABLE\n", + "FAIL-CHANNEL-UNSUPPORTED\n", + "FAIL-Invalid range\n", + "FAIL-Too long response\n", + "FAIL-PBC-OVERLAP\n", + "FAIL-UNKNOWN-UUID\n", + "FAIL-NO-AP-SETTINGS\n", + "FAIL-NO-IFNAME-MATCH\n", + 0 + } ; + char buf[WPARESPONSE_MAXLEN] ; + ssize_t r = wpactrl_query(a, s, len, buf, WPARESPONSE_MAXLEN, deadline, stamp) ; + if (r < 0) return WPA_ERROR ; + if (!r) return (errno = EPIPE, WPA_ERROR) ; + { + wparesponse_t i = 0 ; + for (; wparesponses[i] ; i++) + if (!strncmp(buf, wparesponses[i], r)) + break ; + return i ; + } +} diff --git a/src/libwpactrl/wpactrl_end.c b/src/libwpactrl/wpactrl_end.c new file mode 100644 index 0000000..40fdb4a --- /dev/null +++ b/src/libwpactrl/wpactrl_end.c @@ -0,0 +1,11 @@ +/* ISC license. */ + +#include +#include + +void wpactrl_free (wpactrl_t *a) +{ + fd_close(a->fda) ; + fd_close(a->fds) ; + *a = wpactrl_zero ; +} diff --git a/src/libwpactrl/wpactrl_fd_recv.c b/src/libwpactrl/wpactrl_fd_recv.c new file mode 100644 index 0000000..3e2a006 --- /dev/null +++ b/src/libwpactrl/wpactrl_fd_recv.c @@ -0,0 +1,47 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include "wpactrl-internal.h" + +ssize_t wpactrl_fd_recv (int fd, char *s, size_t len) +{ + static int const bsd_braindeadness_workaround_flags = +#ifdef SKALIBS_HASMSGDONTWAIT + MSG_DONTWAIT +#else + 0 +#endif + | +#ifdef SKALIBS_HASNBWAITALL + MSG_WAITALL +#else + 0 +#endif + | +#ifdef SKALIBS_HASCMSGCLOEXEC + MSG_CMSG_CLOEXEC +#else + 0 +#endif + ; + struct iovec iov = { .iov_base = s, .iov_len = len } ; + struct msghdr msghdr = + { + .msg_name = 0, + .msg_namelen = 0, + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_flags = 0, + .msg_control = 0, + .msg_controllen = 0 + } ; + ssize_t r ; + do r = recvmsg(fd, &msghdr, bsd_braindeadness_workaround_flags) ; + while (r == -1 && errno == EINTR) ; + return r > 0 && msghdr.msg_flags | MSG_TRUNC ? (errno = EMSGSIZE, -1) : r ; +} diff --git a/src/libwpactrl/wpactrl_fd_timed_recv.c b/src/libwpactrl/wpactrl_fd_timed_recv.c new file mode 100644 index 0000000..db181c1 --- /dev/null +++ b/src/libwpactrl/wpactrl_fd_timed_recv.c @@ -0,0 +1,29 @@ +/* ISC license. */ + +#include +#include +#include +#include "wpactrl-internal.h" + +struct blah_s +{ + int fd ; + char *s ; + size_t len ; +} ; + +static int getfd (struct blah_s *blah) +{ + return blah->fd ; +} + +static ssize_t get (struct blah_s *blah) +{ + return sanitize_read(wpactrl_fd_recv(blah->fd, blah->s, blah->len)) ; +} + +ssize_t wpactrl_fd_timed_recv (int fd, char *s, size_t len, tain_t const *deadline, tain_t *stamp) +{ + struct blah_s blah = { .fd = fd, .s = s, .len = len } ; + return timed_get(&blah, (initfunc_t_ref)&getfd, (getfunc_t_ref)&get, deadline, stamp) ; +} diff --git a/src/libwpactrl/wpactrl_filter_add.c b/src/libwpactrl/wpactrl_filter_add.c new file mode 100644 index 0000000..8896e23 --- /dev/null +++ b/src/libwpactrl/wpactrl_filter_add.c @@ -0,0 +1,12 @@ +/* ISC license. */ + +#include +#include +#include +#include "wpactrl-internal.h" + +int wpactrl_filter_add (wpactrl_t *a, char const *s) +{ + if (wpactrl_filter_exact_search(a, s) < a->filters.len) return 1 ; + return stralloc_catb(&a->filters, s, strlen(s)) ; +} diff --git a/src/libwpactrl/wpactrl_filter_exact_search.c b/src/libwpactrl/wpactrl_filter_exact_search.c new file mode 100644 index 0000000..c7197d7 --- /dev/null +++ b/src/libwpactrl/wpactrl_filter_exact_search.c @@ -0,0 +1,12 @@ +/* ISC license. */ + +#include +#include "wpactrl-internal.h" + +size_t wpactrl_filter_exact_search (wpactrl_t const *a, char const *s) +{ + size_t pos = 0 ; + for ( ; pos < a->filters.len ; pos += strlen(a->filters.s + pos) + 1) + if (!strcmp(s, a->filters.s + pos)) break ; + return pos ; +} diff --git a/src/libwpactrl/wpactrl_filter_remove.c b/src/libwpactrl/wpactrl_filter_remove.c new file mode 100644 index 0000000..d41ad6e --- /dev/null +++ b/src/libwpactrl/wpactrl_filter_remove.c @@ -0,0 +1,16 @@ +/* ISC license. */ + +#include +#include +#include "wpactrl-internal.h" + +void wpactrl_filter_remove (wpactrl_t *a, char const *s) +{ + size_t pos = wpactrl_filter_exact_search(a, s) ; + if (pos >= a->filters.len) + { + size_t after = pos + strlen(a->filters.s + pos) + 1 ; + memmove(a->filters.s + pos, a->filters.s + after, a->filters.len - after) ; + a->filters.len -= after - pos ; + } +} diff --git a/src/libwpactrl/wpactrl_query.c b/src/libwpactrl/wpactrl_query.c new file mode 100644 index 0000000..951c536 --- /dev/null +++ b/src/libwpactrl/wpactrl_query.c @@ -0,0 +1,11 @@ +/* ISC license. */ + +#include +#include +#include "wpactrl-internal.h" + +ssize_t wpactrl_query (wpactrl_t *a, char const *q, size_t qlen, char *ans, size_t ansmax, tain_t const *deadline, tain_t *stamp) +{ + if (!ipc_timed_send(a->fds, q, qlen, deadline, stamp)) return WPA_ERROR ; + return wpactrl_fd_timed_recv(a->fds, ans, ansmax, deadline, stamp) ; +} diff --git a/src/libwpactrl/wpactrl_querysa.c b/src/libwpactrl/wpactrl_querysa.c new file mode 100644 index 0000000..fe06202 --- /dev/null +++ b/src/libwpactrl/wpactrl_querysa.c @@ -0,0 +1,15 @@ +/* ISC license. */ + +#include +#include +#include +#include "wpactrl-internal.h" + +int wpactrl_querysa (wpactrl_t *a, char const *s, size_t len, stralloc *sa, tain_t const *deadline, tain_t *stamp) +{ + char buf[WPACTRL_PACKET_MAX] ; + ssize_t r = wpactrl_query(a, s, len, buf, WPACTRL_PACKET_MAX, deadline, stamp) ; + if (r < 0) return 0 ; + if (!r) return (errno = EPIPE, 0) ; + return stralloc_catb(sa, buf, r) ; +} diff --git a/src/libwpactrl/wpactrl_start.c b/src/libwpactrl/wpactrl_start.c new file mode 100644 index 0000000..86a266b --- /dev/null +++ b/src/libwpactrl/wpactrl_start.c @@ -0,0 +1,45 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include "wpactrl-internal.h" + +int wpactrl_start (wpactrl_t *a, char const *path, tain_t const *deadline, tain_t *stamp) +{ + int fda, fds ; + fds = ipc_datagram_nbcoe() ; + if (fds < 0) goto err ; + if (!ipc_timed_connect(fds, path, deadline, stamp)) goto errs ; + fda = ipc_datagram_nbcoe() ; + if (fda < 0) goto errs ; + if (!ipc_timed_connect(fda, path, deadline, stamp)) goto erra ; + if (!ipc_timed_send(fda, "ATTACH", 6, deadline, stamp)) goto erra ; + { + ssize_t r ; + char answer[3] ; + r = wpactrl_fd_timed_recv(fda, answer, 3, deadline, stamp) ; + if (r != 3 || memcmp(answer, "OK\n", 3)) goto erra ; + } + a->fds = fds ; + a->fda = fda ; + return 1 ; + + erra: + { + int e = errno ; + fd_close(fda) ; + errno = e ; + } + errs: + { + int e = errno ; + fd_close(fds) ; + errno = e ; + } + err: + return 0 ; +} diff --git a/src/libwpactrl/wpactrl_update.c b/src/libwpactrl/wpactrl_update.c new file mode 100644 index 0000000..edbdc6f --- /dev/null +++ b/src/libwpactrl/wpactrl_update.c @@ -0,0 +1,48 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include "wpactrl-internal.h" + +static inline int filter_search (char const *s, size_t len, char const *filters, size_t filterlen) +{ + while (filterlen) + { + size_t flen = strlen(filters) ; + if (len >= flen && !strncmp(filters, s, flen)) return 1 ; + filters += flen+1 ; + filterlen -= flen+1 ; + } + return 0 ; +} + +static inline int validate (char const *s, size_t len) +{ + if (len < 4) return 0 ; + if (s[0] != '<') return 0 ; + if (!memchr("123456789", s[1], 9)) return 0 ; + if (s[2] != '>') return 0 ; + return s[len-1] == '\n' ; +} + +int wpactrl_update (wpactrl_t *a) +{ + unsigned int n = WPACTRL_RECV_MAX ; + unsigned int count = 0 ; + char buf[WPACTRL_PACKET_MAX] ; + while (n--) + { + ssize_t r = sanitize_read(wpactrl_fd_recv(a->fda, buf, WPACTRL_PACKET_MAX)) ; + if (r < 0) return -1 ; + if (!r) break ; + if (a->options & WPACTRL_OPTION_NOFILTER + || (validate(buf, r) && filter_search(buf, r, a->filters.s, a->filters.len))) + { + if (!stralloc_catb(&a->data, buf, r)) return -1 ; + count++ ; + } + } + return (int)count ; +} diff --git a/src/libwpactrl/wpactrl_zero.c b/src/libwpactrl/wpactrl_zero.c new file mode 100644 index 0000000..89b4356 --- /dev/null +++ b/src/libwpactrl/wpactrl_zero.c @@ -0,0 +1,5 @@ +/* ISC license. */ + +#include + +wpactrl_t const wpactrl_zero = WPACTRL_ZERO ; 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