From 4ba5ae5776c2e9ba4f297115c19923a928cf3e87 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Mon, 20 Nov 2017 14:51:36 +0000 Subject: Initial release / rename to utmps --- .gitignore | 8 + AUTHORS | 2 + COPYING | 13 + INSTALL | 175 +++++++++++ Makefile | 154 ++++++++++ NEWS | 6 + README | 27 ++ README.macosx | 4 + README.solaris | 12 + configure | 470 ++++++++++++++++++++++++++++++ doc/index.html | 132 +++++++++ doc/libutmps/index.html | 171 +++++++++++ doc/overview.html | 109 +++++++ doc/upgrade.html | 28 ++ doc/utmps-utmpd.html | 77 +++++ doc/utmps-wtmpd.html | 78 +++++ examples/openrc/utmpd | 8 + examples/openrc/wtmpd | 8 + examples/s6-rc/sutmp-prepare/dependencies | 1 + examples/s6-rc/sutmp-prepare/down | 1 + examples/s6-rc/sutmp-prepare/type | 1 + examples/s6-rc/sutmp-prepare/up | 2 + examples/s6-rc/utmpd-log/consumer-for | 1 + examples/s6-rc/utmpd-log/dependencies | 1 + examples/s6-rc/utmpd-log/run | 5 + examples/s6-rc/utmpd-log/type | 1 + examples/s6-rc/utmpd/dependencies | 1 + examples/s6-rc/utmpd/notification-fd | 1 + examples/s6-rc/utmpd/pipeline-name | 1 + examples/s6-rc/utmpd/producer-for | 1 + examples/s6-rc/utmpd/run | 8 + examples/s6-rc/utmpd/type | 1 + examples/s6-rc/wtmpd-log/consumer-for | 1 + examples/s6-rc/wtmpd-log/dependencies | 1 + examples/s6-rc/wtmpd-log/run | 5 + examples/s6-rc/wtmpd-log/type | 1 + examples/s6-rc/wtmpd/dependencies | 1 + examples/s6-rc/wtmpd/notification-fd | 1 + examples/s6-rc/wtmpd/pipeline-name | 1 + examples/s6-rc/wtmpd/producer-for | 1 + examples/s6-rc/wtmpd/run | 8 + examples/s6-rc/wtmpd/type | 1 + examples/s6/utmpd/log/run | 5 + examples/s6/utmpd/notification-fd | 1 + examples/s6/utmpd/run | 11 + examples/s6/wtmpd/log/run | 5 + examples/s6/wtmpd/notification-fd | 1 + examples/s6/wtmpd/run | 9 + package/deps-build | 1 + package/deps.mak | 41 +++ package/info | 4 + package/modes | 2 + package/targets.mak | 7 + patch-for-solaris | 21 ++ src/include/utmps/utmps.h | 35 +++ src/include/utmps/utmpx.h | 75 +++++ src/include/utmpx.h | 13 + src/utmps/deps-exe/utmps-utmpd | 2 + src/utmps/deps-exe/utmps-wtmpd | 2 + src/utmps/deps-lib/utmps | 21 ++ src/utmps/endutxent.c | 10 + src/utmps/getutxent.c | 12 + src/utmps/getutxid.c | 12 + src/utmps/getutxline.c | 12 + src/utmps/logwtmp.c | 22 ++ src/utmps/pututxline.c | 14 + src/utmps/setutxent.c | 11 + src/utmps/updwtmpx.c | 10 + src/utmps/utmps-internal.h | 16 + src/utmps/utmps-utmpd.c | 216 ++++++++++++++ src/utmps/utmps-wtmpd.c | 107 +++++++ src/utmps/utmps_end.c | 10 + src/utmps/utmps_getent.c | 21 ++ src/utmps/utmps_getid.c | 27 ++ src/utmps/utmps_getline.c | 25 ++ src/utmps/utmps_here.c | 8 + src/utmps/utmps_here_maybe_init.c | 11 + src/utmps/utmps_putline.c | 22 ++ src/utmps/utmps_rewind.c | 19 ++ src/utmps/utmps_start.c | 18 ++ src/utmps/utmps_updwtmpx.c | 28 ++ src/utmps/utmps_utmpx_pack.c | 9 + src/utmps/utmps_utmpx_unpack.c | 13 + tools/gen-deps.sh | 93 ++++++ tools/install.sh | 64 ++++ 85 files changed, 2595 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 100644 README.macosx create mode 100644 README.solaris create mode 100755 configure create mode 100644 doc/index.html create mode 100644 doc/libutmps/index.html create mode 100644 doc/overview.html create mode 100644 doc/upgrade.html create mode 100644 doc/utmps-utmpd.html create mode 100644 doc/utmps-wtmpd.html create mode 100755 examples/openrc/utmpd create mode 100755 examples/openrc/wtmpd create mode 100644 examples/s6-rc/sutmp-prepare/dependencies create mode 100644 examples/s6-rc/sutmp-prepare/down create mode 100644 examples/s6-rc/sutmp-prepare/type create mode 100644 examples/s6-rc/sutmp-prepare/up create mode 100644 examples/s6-rc/utmpd-log/consumer-for create mode 100644 examples/s6-rc/utmpd-log/dependencies create mode 100644 examples/s6-rc/utmpd-log/run create mode 100644 examples/s6-rc/utmpd-log/type create mode 100644 examples/s6-rc/utmpd/dependencies create mode 100644 examples/s6-rc/utmpd/notification-fd create mode 100644 examples/s6-rc/utmpd/pipeline-name create mode 100644 examples/s6-rc/utmpd/producer-for create mode 100644 examples/s6-rc/utmpd/run create mode 100644 examples/s6-rc/utmpd/type create mode 100644 examples/s6-rc/wtmpd-log/consumer-for create mode 100644 examples/s6-rc/wtmpd-log/dependencies create mode 100644 examples/s6-rc/wtmpd-log/run create mode 100644 examples/s6-rc/wtmpd-log/type create mode 100644 examples/s6-rc/wtmpd/dependencies create mode 100644 examples/s6-rc/wtmpd/notification-fd create mode 100644 examples/s6-rc/wtmpd/pipeline-name create mode 100644 examples/s6-rc/wtmpd/producer-for create mode 100644 examples/s6-rc/wtmpd/run create mode 100644 examples/s6-rc/wtmpd/type create mode 100755 examples/s6/utmpd/log/run create mode 100644 examples/s6/utmpd/notification-fd create mode 100755 examples/s6/utmpd/run create mode 100755 examples/s6/wtmpd/log/run create mode 100644 examples/s6/wtmpd/notification-fd create mode 100755 examples/s6/wtmpd/run create mode 100644 package/deps-build create mode 100644 package/deps.mak create mode 100644 package/info create mode 100644 package/modes create mode 100644 package/targets.mak create mode 100755 patch-for-solaris create mode 100644 src/include/utmps/utmps.h create mode 100644 src/include/utmps/utmpx.h create mode 100644 src/include/utmpx.h create mode 100644 src/utmps/deps-exe/utmps-utmpd create mode 100644 src/utmps/deps-exe/utmps-wtmpd create mode 100644 src/utmps/deps-lib/utmps create mode 100644 src/utmps/endutxent.c create mode 100644 src/utmps/getutxent.c create mode 100644 src/utmps/getutxid.c create mode 100644 src/utmps/getutxline.c create mode 100644 src/utmps/logwtmp.c create mode 100644 src/utmps/pututxline.c create mode 100644 src/utmps/setutxent.c create mode 100644 src/utmps/updwtmpx.c create mode 100644 src/utmps/utmps-internal.h create mode 100644 src/utmps/utmps-utmpd.c create mode 100644 src/utmps/utmps-wtmpd.c create mode 100644 src/utmps/utmps_end.c create mode 100644 src/utmps/utmps_getent.c create mode 100644 src/utmps/utmps_getid.c create mode 100644 src/utmps/utmps_getline.c create mode 100644 src/utmps/utmps_here.c create mode 100644 src/utmps/utmps_here_maybe_init.c create mode 100644 src/utmps/utmps_putline.c create mode 100644 src/utmps/utmps_rewind.c create mode 100644 src/utmps/utmps_start.c create mode 100644 src/utmps/utmps_updwtmpx.c create mode 100644 src/utmps/utmps_utmpx_pack.c create mode 100644 src/utmps/utmps_utmpx_unpack.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..29db243 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*.o +*.lo +/config.mak +/src/include/utmps/config.h +/libutmps.a.xyzzy +/libutmps.so.xyzzy +/utmps-utmpd +/utmps-wtmpd diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..7a708a1 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Main author: + Laurent Bercot diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..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..53d90eb --- /dev/null +++ b/INSTALL @@ -0,0 +1,175 @@ +Build Instructions +------------------ + +* Requirements + ------------ + + - A POSIX-compliant C development environment + - GNU make version 3.81 or later + - skalibs version 2.6.1.0 or later: http://skarnet.org/software/skalibs/ + + This software will run on any operating system that implements +POSIX.1-2008, available at: + http://pubs.opengroup.org/onlinepubs/9699919799/ + + +* Standard usage + -------------- + + ./configure && make && sudo make install + + will work for most users. + It will install the binaries in /bin and the static libraries in +/usr/lib/utmps. + + Please note that static libraries in /usr/lib/utmps *will not* +be found by a default linker invocation: you need -L/usr/lib/utmps. +Other skarnet.org software automatically handles that case if the +default configuration is used, but if you change the configuration, +remember to use the appropriate --with-lib configure option. + + You can strip the binaries and libraries of their extra symbols via +"make strip" before the "make install" phase. It will shave a few bytes +off them. + + +* Customization + ------------- + + You can customize paths via flags given to configure. + See ./configure --help for a list of all available configure options. + + +* Environment variables + --------------------- + + Controlling a build process via environment variables is a big and +dangerous hammer. You should try and pass flags to configure instead; +nevertheless, a few standard environment variables are recognized. + + If the CC environment variable is set, its value will override compiler +detection by configure. The --host=HOST option will still add a HOST- +prefix to the value of CC. + + The values of CFLAGS, CPPFLAGS and LDFLAGS will be appended to flags +auto-detected by configure. To entirely override the flags set by +configure instead, use make variables. + + +* Make variables + -------------- + + You can invoke make with a few variables for more configuration. + + CC, CFLAGS, CPPFLAGS, LDFLAGS, LDLIBS, AR, RANLIB, STRIP, INSTALL and +CROSS_COMPILE can all be overridden on the make command line. This is +an even bigger hammer than running ./configure with environment +variables, so it is advised to only do this when it is the only way of +obtaining the behaviour you want. + + DESTDIR can be given on the "make install" command line in order to +install to a staging directory. + + +* Shared libraries + ---------------- + + Software from skarnet.org is small enough that shared libraries are +generally not worth using. Static linking is simpler and incurs less +runtime overhead and less points of failure: so by default, shared +libraries are not built and binaries are linked against the static +versions of the skarnet.org libraries. Nevertheless, you can: + * build shared libraries: --enable-shared + * link binaries against shared libraries: --disable-allstatic + + +* Static binaries + --------------- + + By default, binaries are linked against static versions of all the +libraries they depend on, except for the libc. You can enforce +linking against the static libc with --enable-static-libc. + + (If you are using a GNU/Linux system, be aware that the GNU libc +behaves badly with static linking and produces huge executables, +which is why it is not the default. Other libcs are better suited +to static linking, for instance musl: http://musl-libc.org/. If +you're using utmps, chances are you're running musl, or a similar +libc, anyway.) + + +* 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..04360b4 --- /dev/null +++ b/Makefile @@ -0,0 +1,154 @@ +# +# This Makefile requires GNU make. +# +# Do not make changes here. +# Use the included .mak files. +# + +it: all + +make_need := 3.81 +ifeq "" "$(strip $(filter $(make_need), $(firstword $(sort $(make_need) $(MAKE_VERSION)))))" +fail := $(error Your make ($(MAKE_VERSION)) is too old. You need $(make_need) or newer) +endif + +CC = $(error Please use ./configure first) + +STATIC_LIBS := +SHARED_LIBS := +INTERNAL_LIBS := +EXTRA_TARGETS := +LIB_DEFS := + +define library_definition +LIB$(firstword $(subst =, ,$(1))) := lib$(lastword $(subst =, ,$(1))).$(if $(DO_ALLSTATIC),a,so).xyzzy +ifdef DO_SHARED +SHARED_LIBS += lib$(lastword $(subst =, ,$(1))).so.xyzzy +endif +ifdef DO_STATIC +STATIC_LIBS += lib$(lastword $(subst =, ,$(1))).a.xyzzy +endif +endef + +-include config.mak +include package/targets.mak + +$(foreach var,$(LIB_DEFS),$(eval $(call library_definition,$(var)))) + +include package/deps.mak + +version_m := $(basename $(version)) +version_M := $(basename $(version_m)) +version_l := $(basename $(version_M)) +CPPFLAGS_ALL := $(CPPFLAGS_AUTO) $(CPPFLAGS) +CFLAGS_ALL := $(CFLAGS_AUTO) $(CFLAGS) +ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),) +CFLAGS_SHARED := -fPIC +else +CFLAGS_SHARED := +endif +LDFLAGS_ALL := $(LDFLAGS_AUTO) $(LDFLAGS) +REALCC = $(CROSS_COMPILE)$(CC) +AR := $(CROSS_COMPILE)ar +RANLIB := $(CROSS_COMPILE)ranlib +STRIP := $(CROSS_COMPILE)strip +INSTALL := ./tools/install.sh + +ALL_BINS := $(LIBEXEC_TARGETS) $(BIN_TARGETS) +ALL_LIBS := $(SHARED_LIBS) $(STATIC_LIBS) $(INTERNAL_LIBS) +ALL_INCLUDES := $(wildcard src/include/$(package)/*.h) + +all: $(ALL_LIBS) $(ALL_BINS) $(ALL_INCLUDES) src/include/utmpx.h + +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) $(DESTDIR)$(includedir)/utmpx.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/$( diff --git a/README.macosx b/README.macosx new file mode 100644 index 0000000..d71a096 --- /dev/null +++ b/README.macosx @@ -0,0 +1,4 @@ + + This package will compile and run on Darwin (MacOS X), but the building of +shared libraries is not supported. + Make sure you use the --disable-shared option to configure. diff --git a/README.solaris b/README.solaris new file mode 100644 index 0000000..91a5b26 --- /dev/null +++ b/README.solaris @@ -0,0 +1,12 @@ + + This package assumes the existence of a POSIX shell in /bin/sh. + On Solaris, /bin/sh is not POSIX. Most versions of Solaris provide +a POSIX shell in /usr/xpg4/bin/sh. + + To compile this package on Solaris, you will need to run + + ./patch-for-solaris + + before you run ./configure. This script will change the #! invocation +of the configure script and various tools so that a POSIX shell is used +for the compilation process. diff --git a/configure b/configure new file mode 100755 index 0000000..f21429a --- /dev/null +++ b/configure @@ -0,0 +1,470 @@ +#!/bin/sh + +. package/info + +usage () { +cat </dev/null 2>&1 && { echo "$1" ; return 0 ; } +$1 +EOF + echo "$1" | sed -e "s/'/'\\\\''/g" -e "1s/^/'/" -e "\$s/\$/'/" -e "s#^'\([-[:alnum:]_,./:]*\)=\(.*\)\$#\1='\2#" -e "s|\*/|* /|g" +} + +fail () { + echo "$*" + exit 1 +} + +fnmatch () { + eval "case \"\$2\" in $1) return 0 ;; *) return 1 ;; esac" +} + +cmdexists () { + type "$1" >/dev/null 2>&1 +} + +trycc () { + test -z "$CC_AUTO" && cmdexists "$1" && CC_AUTO="$*" +} + +stripdir () { + while eval "fnmatch '*/' \"\${$1}\"" ; do + eval "$1=\${$1%/}" + done +} + +tryflag () { + echo "checking whether compiler accepts $2 ..." + echo "typedef int x;" > "$tmpc" + if $CC_AUTO $CPPFLAGS_AUTO $CPPFLAGS $CPPFLAGS_POST $CFLAGS_AUTO $CFLAGS $CFLAGS_POST "$2" -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then + echo " ... yes" + eval "$1=\"\${$1} \$2\"" + eval "$1=\${$1# }" + return 0 + else + echo " ... no" + return 1 + fi +} + +tryldflag () { + echo "checking whether linker accepts $2 ..." + echo "typedef int x;" > "$tmpc" + if $CC_AUTO $CFLAGS_AUTO $CFLAGS $CFLAGS_POST $LDFLAGS_AUTO $LDFLAGS $LDFLAGS_POST -nostdlib "$2" -o /dev/null "$tmpc" >/dev/null 2>&1 ; then + echo " ... yes" + eval "$1=\"\${$1} \$2\"" + eval "$1=\${$1# }" + return 0 + else + echo " ... no" + return 1 + fi +} + + +# Actual script + +CC_AUTO= +CPPFLAGS_AUTO="-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -iquote src/include-local -Isrc/include" +CPPFLAGS_POST="$CPPFLAGS" +CPPFLAGS= +CFLAGS_AUTO="-pipe -Wall" +CFLAGS_POST="$CFLAGS" +CFLAGS=-O2 +LDFLAGS_AUTO= +LDFLAGS_POST="$LDFLAGS" +LDFLAGS= +LDFLAGS_NOSHARED= +LDFLAGS_SHARED=-shared +prefix= +exec_prefix='$prefix' +dynlibdir='$prefix/lib' +libexecdir='$exec_prefix/libexec' +bindir='$exec_prefix/bin' +libdir='$prefix/lib/$package' +includedir='$prefix/include' +sysdeps='$prefix/lib/skalibs/sysdeps' +manualsysdeps=false +shared=false +static=true +allpic=detect +slashpackage=false +abspath=false +sproot= +home= +exthome= +allstatic=true +evenmorestatic=false +addincpath='' +addlibspath='' +addlibdpath='' +vpaths='' +vpathd='' +build= +utmpdpath=/run/utmps/utmpd-socket +wtmpdpath=/run/utmps/wtmpd-socket + +for arg ; do + case "$arg" in + --help) usage ;; + --prefix=*) prefix=${arg#*=} ;; + --exec-prefix=*) exec_prefix=${arg#*=} ;; + --dynlibdir=*) dynlibdir=${arg#*=} ;; + --libexecdir=*) libexecdir=${arg#*=} ;; + --bindir=*) bindir=${arg#*=} ;; + --libdir=*) libdir=${arg#*=} ;; + --includedir=*) includedir=${arg#*=} ;; + --with-sysdeps=*) sysdeps=${arg#*=} manualsysdeps=true ;; + --with-include=*) var=${arg#*=} ; stripdir var ; addincpath="$addincpath -I$var" ;; + --with-lib=*) var=${arg#*=} ; stripdir var ; addlibspath="$addlibspath -L$var" ; vpaths="$vpaths $var" ;; + --with-dynlib=*) var=${arg#*=} ; stripdir var ; addlibdpath="$addlibdpath -L$var" ; vpathd="$vpathd $var" ;; + --enable-shared|--enable-shared=yes) shared=true ;; + --disable-shared|--enable-shared=no) shared=false ;; + --enable-static|--enable-static=yes) static=true ;; + --disable-static|--enable-static=no) static=false ;; + --enable-allstatic|--enable-allstatic=yes) allstatic=true ;; + --disable-allstatic|--enable-allstatic=no) allstatic=false ; evenmorestatic=false ;; + --enable-static-libc|--enable-static-libc=yes) allstatic=true ; evenmorestatic=true ;; + --disable-static-libc|--enable-static-libc=no) evenmorestatic=false ;; + --enable-all-pic|--enable-all-pic=yes) allpic=true ;; + --disable-all-pic|--enable-all-pic=no) allpic=false ;; + --enable-slashpackage=*) sproot=${arg#*=} ; slashpackage=true ; ;; + --enable-slashpackage) sproot= ; slashpackage=true ;; + --disable-slashpackage) sproot= ; slashpackage=false ;; + --enable-absolute-paths|--enable-absolute-paths=yes) abspath=true ;; + --disable-absolute-paths|--enable-absolute-paths=no) abspath=false ;; + --enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;; + --host=*|--target=*) target=${arg#*=} ;; + --build=*) build=${arg#*=} ;; + --with-utmpd-socket=*) utmpdpath=${arg#*=} ;; + --with-wtmpd-socket=*) wtmpdpath=${arg#*=} ;; + -* ) echo "$0: unknown option $arg" ;; + *=*) ;; + *) target=$arg ;; + esac +done + +# Add /usr in the default default case +if test -z "$prefix" ; then + if test "$libdir" = '$prefix/lib/$package' ; then + libdir=/usr/lib/$package + fi + if test "$includedir" = '$prefix/include' ; then + includedir=/usr/include + fi + if test "$sysdeps" = '$prefix/lib/skalibs/sysdeps' ; then + sysdeps=/usr/lib/skalibs/sysdeps + fi +fi + +# Expand installation directories +stripdir prefix +for i in exec_prefix dynlibdir libexecdir bindir libdir includedir sysdeps sproot ; do + eval tmp=\${$i} + eval $i=$tmp + stripdir $i +done + +# Get usable temp filenames +i=0 +set -C +while : ; do + i=$(($i+1)) + tmpc="./tmp-configure-$$-$PPID-$i.c" + tmpe="./tmp-configure-$$-$PPID-$i.tmp" + 2>|/dev/null > "$tmpc" && break + 2>|/dev/null > "$tmpe" && break + test "$i" -gt 50 && fail "$0: cannot create temporary files" +done +set +C +trap 'rm -f "$tmpc" "$tmpe"' EXIT ABRT INT QUIT TERM HUP + +# Set slashpackage values +if $slashpackage ; then + home=${sproot}/package/${category}/${package}-${version} + exthome=${sproot}/package/${category}/${package} + if $manualsysdeps ; then + : + else + sysdeps=${sproot}/package/prog/skalibs/sysdeps + fi + extbinprefix=${exthome}/command + dynlibdir=${home}/library.so + bindir=${home}/command + libdir=${home}/library + libexecdir=$bindir + includedir=${home}/include + while read dep ; do + addincpath="$addincpath -I${sproot}${dep}/include" + vpaths="$vpaths ${sproot}${dep}/library" + addlibspath="$addlibspath -L${sproot}${dep}/library" + vpathd="$vpathd ${sproot}${dep}/library.so" + addlibdpath="$addlibdpath -L${sproot}${dep}/library.so" + done < package/deps-build +fi + +# Find a C compiler to use +if test -n "$target" && test x${build} != x${target} ; then + cross=${target}- +else + cross= +fi +echo "checking for C compiler..." +trycc ${cross}${CC} +trycc ${cross}gcc +trycc ${cross}clang +trycc ${cross}cc +test -n "$CC_AUTO" || { echo "$0: cannot find a C compiler" ; exit 1 ; } +echo " ... $CC_AUTO" +echo "checking whether C compiler works... " +echo "typedef int x;" > "$tmpc" +if $CC_AUTO $CPPFLAGS_AUTO $CPPFLAGS $CPPFLAGS_POST $CFLAGS_AUTO $CFLAGS $CFLAGS_POST -c -o /dev/null "$tmpc" 2>"$tmpe" ; then + echo " ... yes" +else + echo " ... no. Compiler output follows:" + cat < "$tmpe" + exit 1 +fi + +echo "checking target system type..." +if test -z "$target" ; then + if test -n "$build" ; then + target=$build ; + else + target=$($CC_AUTO -dumpmachine 2>/dev/null) || target=unknown + fi +fi +echo " ... $target" +if test ! -d $sysdeps || test ! -f $sysdeps/target ; then + echo "$0: error: $sysdeps is not a valid sysdeps directory" + exit 1 +fi +if [ "x$target" != "x$(cat $sysdeps/target)" ] ; then + echo "$0: error: target $target does not match the contents of $sysdeps/target" + exit 1 +fi + +if test $allpic = detect ; then + echo "Checking whether we need to build everything as PIC..." + if $CC_AUTO $CPPFLAGS_AUTO $CPPFLAGS $CPPFLAGS_POST $CFLAGS_AUTO $CFLAGS $CFLAGS_POST -dM -E - < /dev/null | grep -qF __PIE__ ; then + allpic=true + echo " ... yes" + else + allpic=false + echo " ... no" + fi +fi +if $allpic ; then + tryflag CFLAGS_AUTO -fPIC +fi + +spawn_lib=$(cat $sysdeps/spawn.lib) +socket_lib=$(cat $sysdeps/socket.lib) +sysclock_lib=$(cat $sysdeps/sysclock.lib) +tainnow_lib=$(cat $sysdeps/tainnow.lib) +timer_lib=$(cat $sysdeps/timer.lib) +util_lib=$(cat $sysdeps/util.lib) + +tryflag CFLAGS_AUTO -std=c99 +tryflag CFLAGS -fomit-frame-pointer +tryflag CFLAGS_AUTO -fno-exceptions +tryflag CFLAGS_AUTO -fno-unwind-tables +tryflag CFLAGS_AUTO -fno-asynchronous-unwind-tables +tryflag CFLAGS_AUTO -Wa,--noexecstack +tryflag CFLAGS -fno-stack-protector +tryflag CPPFLAGS_AUTO -Werror=implicit-function-declaration +tryflag CPPFLAGS_AUTO -Werror=implicit-int +tryflag CPPFLAGS_AUTO -Werror=pointer-sign +tryflag CPPFLAGS_AUTO -Werror=pointer-arith +tryflag CFLAGS_AUTO -ffunction-sections +tryflag CFLAGS_AUTO -fdata-sections + +tryldflag LDFLAGS_AUTO -Wl,--sort-section=alignment +tryldflag LDFLAGS_AUTO -Wl,--sort-common + +CPPFLAGS_AUTO="${CPPFLAGS_AUTO}${addincpath}" + +if $evenmorestatic ; then + LDFLAGS_NOSHARED=-static +fi + +if $shared ; then + tryldflag LDFLAGS -Wl,--hash-style=both +fi + +LDFLAGS_SHARED="${LDFLAGS_SHARED}${addlibdpath}" + +if $allstatic ; then + LDFLAGS_NOSHARED="${LDFLAGS_NOSHARED}${addlibspath}" + tryldflag LDFLAGS_NOSHARED -Wl,--gc-sections +else + LDFLAGS_NOSHARED="${LDFLAGS_NOSHARED}${addlibdpath}" +fi + +if test -z "$vpaths" ; then + while read dep ; do + base=$(basename $dep) ; + vpaths="$vpaths /usr/lib/$base" + addlibspath="$addlibspath -L/usr/lib/$base" + done < package/deps-build +fi + +echo "creating config.mak..." +cmdline=$(quote "$0") +for i ; do cmdline="$cmdline $(quote "$i")" ; done +exec 3>&1 1>config.mak +cat << EOF +# This file was generated by: +# $cmdline +# Any changes made here will be lost if configure is re-run. + +target := $target +package := $package +prefix := $prefix +exec_prefix := $exec_prefix +dynlibdir := $dynlibdir +libexecdir := $libexecdir +bindir := $bindir +libdir := $libdir +includedir := $includedir +sysdeps := $sysdeps +slashpackage := $slashpackage +sproot := $sproot +version := $version +home := $home +exthome := $exthome +SPAWN_LIB := ${spawn_lib} +SOCKET_LIB := ${socket_lib} +SYSCLOCK_LIB := ${sysclock_lib} +TAINNOW_LIB := ${tainnow_lib} +TIMER_LIB := ${timer_lib} +UTIL_LIB := ${util_lib} + +CC := ${CC_AUTO##${cross}} +CPPFLAGS_AUTO := $CPPFLAGS_AUTO +CPPFLAGS := $CPPFLAGS $CPPFLAGS_POST +CFLAGS_AUTO := $CFLAGS_AUTO +CFLAGS := $CFLAGS $CFLAGS_POST +LDFLAGS_AUTO := $LDFLAGS_AUTO +LDFLAGS := $LDFLAGS $LDFLAGS_POST +LDFLAGS_SHARED := $LDFLAGS_SHARED +LDFLAGS_NOSHARED := $LDFLAGS_NOSHARED +CROSS_COMPILE := $cross + +vpath lib%.a$vpaths +vpath lib%.so$vpathd +EOF +if $allstatic ; then + echo ".LIBPATTERNS := lib%.a" + echo "DO_ALLSTATIC := 1" +else + echo ".LIBPATTERNS := lib%.so" +fi +if $static ; then + echo "DO_STATIC := 1" +else + echo "DO_STATIC :=" +fi +if $shared ; then + echo "DO_SHARED := 1" +else + echo "DO_SHARED :=" +fi +if $allpic ; then + echo "STATIC_LIBS_ARE_PIC := 1" +else + echo "STATIC_LIBS_ARE_PIC :=" +fi + +exec 1>&3 3>&- +echo " ... done." + +echo "creating src/include/${package}/config.h..." +mkdir -p -m 0755 src/include/${package} +exec 3>&1 1> src/include/${package}/config.h +cat <&3 3>&- +echo " ... done." diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000..8d080da --- /dev/null +++ b/doc/index.html @@ -0,0 +1,132 @@ + + + + + + utmps - a secure utmp implementation + + + + + + +

+Software
+skarnet.org +

+ +

utmps

+ +

What is it ?

+ +

+ utmps is an implementation of the utmp.h and utmpx.h +family of functions performing user accounting on Unix systems. +

+ +

+ Traditionally, utmp functionality is provided by the system's +libc. However, not all libcs implement utmp: for instance the +musl libc, on Linux, does not. The +main reason for it is that utmp functionality is difficult to +implement in a secure way; in particular, it is impossible to implement +without either running a daemon or allowing arbitrary programs to tamper +with user accounting. +

+ +

+ utmps is a secure implementation of user accounting, using +a daemon as the only authority to manage the utmp and wtmp data; programs +running utmp functions are just clients to this daemon. +

+ +
+ + + +
+ +

Installation

+ +

Requirements

+ +
    +
  • A POSIX-compliant system with a standard C development environment
  • +
  • GNU make, version 3.81 or later
  • +
  • skalibs version +2.6.1.0 or later. 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

+ +

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

+ +

Download

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

Reference

+ +

Commands

+ + + +

Libraries

+ + + +
+ + +

Related resources

+
+ +

utmps discussion

+ +
    +
  • utmps is discussed on the +skaware mailing-list.
  • +
+ + + diff --git a/doc/libutmps/index.html b/doc/libutmps/index.html new file mode 100644 index 0000000..0372726 --- /dev/null +++ b/doc/libutmps/index.html @@ -0,0 +1,171 @@ + + + + + + utmps: the utmps library interface + + + + + + +

+utmps
+Software
+skarnet.org +

+ +

The utmps library interface

+ +

General information

+ +

+ libutmps is a client library meant to be used by client +programs needing utmp functionality. It interacts with the +utmps-utmpd and +utmps-wtmpd daemons. +

+ +

+ Application programs can use it directly, but most existing programs +simply use the standard +utmpx.h +interface, which in utmps is implemented as a series of thin wrappers +around the utmps library. +

+ +

Compiling

+ +
    +
  • Make sure the utmps headers, as well as the skalibs headers, +are visible in your header search path.
  • +
  • Use #include <utmps/utmps.h>
  • +
  • To use the standard utmpx.h interface, you can +just #include <utmpx.h>, which will work as long +as the utmps/utmpx.h header is accessible in your header +search path.
  • +
+ +

Linking

+ +
    +
  • Make sure the utmps library, as well as the skalibs library, +are visible in your library search path.
  • +
  • Link against -lutmps, -lskarnet,
  • +`cat $SYSDEPS/socket.lib` and +`cat $SYSDEPS/tainnow.lib`, $SYSDEPS being your skalibs +sysdeps directory. +
+ +

Programming

+ +

+ Check the utmps/utmps.h header for the exact function list, +and the utmps/utmpx.h header for the definition of the standard +struct utmpx data type. +

+ +

Synchronous functions with a specified maximum execution time

+ +

+ The standard utmpx.h functions are fully synchronous. They were not +initially meant to perform inter-processus communication; however, in +utmps, they do. Their synchronous nature is obviously not changed here, +but the underlying utmps functions use a safety mechanism to bound their +execution time in case daemons fail to respond. This mechanism is described, +for instance, +here. +

+ +

Starting and ending a session

+ +

+int utmps_start (utmps *a, char const *path, tain_t const *deadline, tain_t *stamp)
+Connects to a utmps-utmpd service listening on a Unix domain socket at path. +a must point to a previously allocated utmps object, which is flat and can +be allocated in the stack. This object must have been initialized to UTMPS_ZERO before the call. +a will be a handle describing the session, and must be given to all utmps functions +called in that session. +deadline and stamp are used to bound the execution time as described in the +above link. The function returns 1 if it succeeds; it returns 0, and sets errno, if it fails. +

+ +

+void utmps_end (utmps *a)
+Ends the session described by a, and releases all used resources. +

+ +

Reading from the utmp database

+ +

+ Any user authorized to connect to the utmpd service can call these functions. In other +words, if utmps_start() succeeded, then these functions should not fail due to +insufficient permissions. +

+ +

+int utmps_rewind (utmps *a, tain_t const *deadline, tain_t *stamp)
+Performs the setutxent() functionality on the utmp database addressed via a, +i.e. sets the internal pointer at the start of the database. +On success, stores the result into *b and returns 1. On failure, returns 0 and sets errno. +

+ +

+int utmps_getent (utmps *a, struct utmpx *b, tain_t const *deadline, tain_t *stamp)
+Performs the getutxent() functionality on the utmp database addressed via a. +On success, stores the result into *b and returns 1. On failure, returns 0 and sets errno. +

+ +

+int utmps_getid (utmps *a, unsigned short type, char const *id, struct utmpx *b, tain_t const *deadline, tain_t *stamp)
+Performs the getutxid() functionality on the utmp database addressed via a, +using ut_type type and ut_id id. id must be a null-terminated +string; only its first UTMPS_UT_IDSIZE-1 characters will be taken into account. +On success, the function stores the result into *b and returns 1. On failure, +it returns 0 and sets errno. +

+ +

+int utmps_getline (utmps *a, char const *line, struct utmpx *b, tain_t const *deadline, tain_t *stamp)
+Performs the getutxline() functionality on the utmp database addressed via a, +using ut_line line. line must be a null-terminated +string; only its first UTMPS_UT_LINESIZE-1 characters will be taken into account. +On success, the function stores the result into *b and returns 1. On failure, +it returns 0 and sets errno. +

+ +

Writing to the utmp database

+ +

+ Currently, only the super-user is allowed to use this function. +

+ +

+int utmps_putline (utmps *a, struct utmpx const *b, tain_t const *deadline, tain_t *stamp)
+Performs the pututxline() functionality on the utmp database addressed via a, +i.e. writes the *b structure into the utmp database looking for an appropriate +record to replace, and appending to the database if no such record can be found. +On success, the function returns 1. On failure, it returns 0 and sets errno. +

+ +

Writing to the wtmp database

+ +

+int utmps_updwtmpx (char const *path, struct utmpx const *b, tain_t const *deadline, tain_t *stamp)
+Unlike the previous functions, utmps_updwtmpx() does not use a utmps handle, because +it does not connect to an utmpd service. Instead, it connects to a wtmpd service listening +on Unix domain socket path, once for every call. It appends the *b structure +to the wtmp database, returning 1 on success and 0 (and setting errno) on failure. +

+ +

+ utmps_updwtmpx() will only succeed if the caller is root, or if +b→ut_user resolves (according to getpwnam()) to the +effective uid of the caller. In other words: users can append phony records +for themselves, but not for others, and only root can spoof the whole +wtmp database. +

+ + + diff --git a/doc/overview.html b/doc/overview.html new file mode 100644 index 0000000..22e9210 --- /dev/null +++ b/doc/overview.html @@ -0,0 +1,109 @@ + + + + + + utmps: an overview + + + + + + +

+utmps
+Software
+skarnet.org +

+ +

An overview of utmps

+ +

+ utmps is a secure implementation of the utmp functionality, i.e. +user accounting on Unix systems. It includes full POSIX +utmpx.h +functionality, a few extensions created by GNU, and an underlying +C client library with better error reporting +than the POSIX interface specifies. +

+ +

The issues with traditional utmp

+ +

+ Traditional utmp implementations, as performed by most Unix +libcs, are woefully insecure. The fundamental issue with utmp +is that it requires user programs to write to files (the utmp or wtmp +databases) owned by either root or a specific system user. That means +having the suid bit set on programs using it. +

+ +

The utmps solution

+ +

+ utmps uses the age old Unix client-server model, following the +adage "one resource → one daemon". It provides two daemons, +utmps-utmpd and +utmps-wtmpd, which should be the only +programs allowed to access the utmp and wtmp databases respectively. +It provides the +utmps client library to communicate with +those daemons; and it implements the +utmpx.h +interfaces, and the extensions, as wrappers for this client library. +

+ +

Authentication, local services and superservers

+ +

+utmps-utmpd and +utmps-wtmpd do not listen to the +network themselves. They are designed to serve only one client +connection, following the +UCSPI model - +also known as the inetd model. To implement the utmpd and wtmpd +local services, +a Unix domain superserver such as +s6-ipcserver +is required. s6-ipcserver listens to a socket, and spawns a +utmps-utmpd process when a client +calls setutxent() +for instance. +

+ +

+ The utmpd and wtmpd services must be started at boot time in +order for utmp calls to succeed. The examples/ subdirectory +of the utmps package has examples on how to start those services +when using the +s6 supervision suite, +the s6-rc service manager, or +the OpenRC service manager. +

+ +

+ This model has advantages and drawbacks. The main drawback is that it requires +a daemon to be running in order for the system to provide full POSIX +functionality. The main advantage, on the other hand, is that no program +needs to be suid or sgid, and permissions can actually be quite fine-grained. +

+ +
    +
  • utmps-utmpd will allow any user to +read from the utmp database, but will only allow root to write to it.
  • +
  • utmps-wtmpd will only allow a user +to add an entry to the wtmp database if the user is root, or if the +ut_user field of the added entry resolves to the user's effective +uid.
  • +
  • The s6-ipcserver +superserver, which is recommended to implement the utmpd and wtmpd services, +allows fine-tuning the permissions: it is possible to deny users from +connecting to the service, or to only allow certain groups, etc.
  • +
+ +

+ All in all, I believe the flexibility it offers overweighs the inconvenience +of having to run services before providing utmp/wtmp. +

+ + + diff --git a/doc/upgrade.html b/doc/upgrade.html new file mode 100644 index 0000000..b5c9db9 --- /dev/null +++ b/doc/upgrade.html @@ -0,0 +1,28 @@ + + + + + + How to upgrade utmps + + + + + + +

+utmps
+Software
+skarnet.org +

+ +

What has changed in utmps

+ +

in 0.0.1.0

+ +

+ Initial release. +

+ + + diff --git a/doc/utmps-utmpd.html b/doc/utmps-utmpd.html new file mode 100644 index 0000000..57fa6ac --- /dev/null +++ b/doc/utmps-utmpd.html @@ -0,0 +1,77 @@ + + + + + + utmps: the utmps-utmpd program + + + + + + +

+utmps
+Software
+skarnet.org +

+ +

The utmps-utmpd program

+ +

+utmps-utmpd manages the utmp database. It expects to be able to create, read and +modify a file named utmp in the directory it is launched in. +

+ +

+ It is not meant to be called directly; instead, it is expected to be run from +a script as a part of a "utmpd" +local service. +

+ +

+ The examples/ subdirectory of the utmps package provides examples +on how to run such a service. + The simplest way to do so, for testing purposes, is a command line such as: +

+
s6-ipcserver -l0 utmpd-socket utmps-utmpd
+

+ while being in the /run/utmps directory. +

+ +

+/run/utmps/utmpd-socket is the default place where utmps's +implementation of the utmpx.h functions expects the utmpd +service to be. It can be changed at build time by giving the +--with-utmp-socket=PATH option to configure. +

+ +

+ utmps-utmpd does not listen to the socket itself: it reads from its +standard input and writes to its standard output. It relies +on a superserver such as +s6-ipcserver +to manage connections to the socket. An instance of utmps-utmpd is run +for every client connection; +every instance reads the effective uid of the client in an environment +variable set by the superserver, which allows it to filter operations - +for instance, it allows any user to read from the database but it only +allows root to write to it. +

+ +

+ If more fine-grained authorizations are required (only allowing +certain users and groups to connect to the service), the superserver +can be configured to enforce them. +

+ +

+ utmps-utmpd does not need to run as root, provided it can write its file; +it is recommended to create a utmp user and group, dedicated to +utmps-utmpd and +utmps-wtmpd operation, and run the +superserver as this user and group. +

+ + + diff --git a/doc/utmps-wtmpd.html b/doc/utmps-wtmpd.html new file mode 100644 index 0000000..a1e090b --- /dev/null +++ b/doc/utmps-wtmpd.html @@ -0,0 +1,78 @@ + + + + + + utmps: the utmps-wtmpd program + + + + + + +

+utmps
+Software
+skarnet.org +

+ +

The utmps-wtmpd program

+ +

+utmps-wtmpd manages the wtmp database. It expects to be able to create, read and +modify a file named wtmp in the directory it is launched in. +

+ +

+ It is not meant to be called directly; instead, it is expected to be run from +a script as a part of a "wtmpd" +local service. +

+ +

+ The examples/ subdirectory of the utmps package provides examples +on how to run such a service. + The simplest way to do so, for testing purposes, is a command line such as: +

+
s6-ipcserver -l0 utmpd-socket utmps-wtmpd
+

+ while being in the /run/utmps directory. +

+ +

+/run/utmps/wtmpd-socket is the default place where utmps's +implementation of the updwtmpx() function expects the wtmpd +service to be. It can be changed at build time by giving the +--with-wtmp-socket=PATH option to configure. +

+ +

+ utmps-wtmpd does not listen to the socket itself: it reads from its +standard input and writes to its standard output. It relies +on a superserver such as +s6-ipcserver +to manage connections to the socket. An instance of utmps-wtmpd is run +for every client connection; +every instance reads the effective uid of the client in an environment +variable set by the superserver, which allows it to filter operations: +only lines whose ut_user field resolves to the effective uid of +the client will be appended to the database. +

+ +

+ If more fine-grained authorizations are required (only allowing +certain users and groups to connect to the service), the superserver +can be configured to enforce them. For instance, it is possible to +tell s6-ipcserver to only accept connections from root. +

+ +

+ utmps-wtmpd does not need to run as root, provided it can write its file; +it is recommended to create a utmp user and group, dedicated to +utmps-wtmpd and +utmps-utmpd operation, and run the +superserver as this user and group. +

+ + + diff --git a/examples/openrc/utmpd b/examples/openrc/utmpd new file mode 100755 index 0000000..a091528 --- /dev/null +++ b/examples/openrc/utmpd @@ -0,0 +1,8 @@ +#!/sbin/openrc-run + +# Assumes the /run/utmps directory already exists and belongs to utmp + +name="utmpd" +command="s6-ipcserver -- /run/utmps/utmpd-socket utmps-utmpd" +pidfile="/run/utmps/utmpd.pid" +start_stop_daemon_args="-b -m -c utmp -d /run/utmps" diff --git a/examples/openrc/wtmpd b/examples/openrc/wtmpd new file mode 100755 index 0000000..5485a8d --- /dev/null +++ b/examples/openrc/wtmpd @@ -0,0 +1,8 @@ +#!/sbin/openrc-run + +# Assumes the /run/utmps directory already exists and belongs to utmp + +name="wtmpd" +command="s6-ipcserver -- /run/utmps/wtmpd-socket utmps-wtmpd" +pidfile="/run/utmps/wtmpd.pid" +start_stop_daemon_args="-b -m -c utmp -d /run/utmps" diff --git a/examples/s6-rc/sutmp-prepare/dependencies b/examples/s6-rc/sutmp-prepare/dependencies new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/examples/s6-rc/sutmp-prepare/dependencies @@ -0,0 +1 @@ + diff --git a/examples/s6-rc/sutmp-prepare/down b/examples/s6-rc/sutmp-prepare/down new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/examples/s6-rc/sutmp-prepare/down @@ -0,0 +1 @@ + diff --git a/examples/s6-rc/sutmp-prepare/type b/examples/s6-rc/sutmp-prepare/type new file mode 100644 index 0000000..bdd22a1 --- /dev/null +++ b/examples/s6-rc/sutmp-prepare/type @@ -0,0 +1 @@ +oneshot diff --git a/examples/s6-rc/sutmp-prepare/up b/examples/s6-rc/sutmp-prepare/up new file mode 100644 index 0000000..6091aad --- /dev/null +++ b/examples/s6-rc/sutmp-prepare/up @@ -0,0 +1,2 @@ +foreground { mkdir -p -m 0755 /run/utmps } +chown utmp:utmp /run/utmps diff --git a/examples/s6-rc/utmpd-log/consumer-for b/examples/s6-rc/utmpd-log/consumer-for new file mode 100644 index 0000000..fe07d03 --- /dev/null +++ b/examples/s6-rc/utmpd-log/consumer-for @@ -0,0 +1 @@ +utmpd diff --git a/examples/s6-rc/utmpd-log/dependencies b/examples/s6-rc/utmpd-log/dependencies new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/examples/s6-rc/utmpd-log/dependencies @@ -0,0 +1 @@ + diff --git a/examples/s6-rc/utmpd-log/run b/examples/s6-rc/utmpd-log/run new file mode 100644 index 0000000..586e53d --- /dev/null +++ b/examples/s6-rc/utmpd-log/run @@ -0,0 +1,5 @@ +#!/bin/execlineb -P + +s6-setuidgid utmplog +exec -c +s6-log t /var/log/utmpd diff --git a/examples/s6-rc/utmpd-log/type b/examples/s6-rc/utmpd-log/type new file mode 100644 index 0000000..5883cff --- /dev/null +++ b/examples/s6-rc/utmpd-log/type @@ -0,0 +1 @@ +longrun diff --git a/examples/s6-rc/utmpd/dependencies b/examples/s6-rc/utmpd/dependencies new file mode 100644 index 0000000..6cfcf60 --- /dev/null +++ b/examples/s6-rc/utmpd/dependencies @@ -0,0 +1 @@ +utmps-prepare diff --git a/examples/s6-rc/utmpd/notification-fd b/examples/s6-rc/utmpd/notification-fd new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/examples/s6-rc/utmpd/notification-fd @@ -0,0 +1 @@ +3 diff --git a/examples/s6-rc/utmpd/pipeline-name b/examples/s6-rc/utmpd/pipeline-name new file mode 100644 index 0000000..d75e141 --- /dev/null +++ b/examples/s6-rc/utmpd/pipeline-name @@ -0,0 +1 @@ +utmpd-pipeline diff --git a/examples/s6-rc/utmpd/producer-for b/examples/s6-rc/utmpd/producer-for new file mode 100644 index 0000000..8ff8e12 --- /dev/null +++ b/examples/s6-rc/utmpd/producer-for @@ -0,0 +1 @@ +utmpd-log diff --git a/examples/s6-rc/utmpd/run b/examples/s6-rc/utmpd/run new file mode 100644 index 0000000..417ef5e --- /dev/null +++ b/examples/s6-rc/utmpd/run @@ -0,0 +1,8 @@ +#!/bin/execlineb -P + +fdmove -c 2 1 +s6-setuidgid utmp +cd /run/utmps +fdmove 1 3 +s6-ipcserver -1 -- /run/utmps/utmpd-socket +utmps-utmpd diff --git a/examples/s6-rc/utmpd/type b/examples/s6-rc/utmpd/type new file mode 100644 index 0000000..5883cff --- /dev/null +++ b/examples/s6-rc/utmpd/type @@ -0,0 +1 @@ +longrun diff --git a/examples/s6-rc/wtmpd-log/consumer-for b/examples/s6-rc/wtmpd-log/consumer-for new file mode 100644 index 0000000..18e5a30 --- /dev/null +++ b/examples/s6-rc/wtmpd-log/consumer-for @@ -0,0 +1 @@ +wtmpd diff --git a/examples/s6-rc/wtmpd-log/dependencies b/examples/s6-rc/wtmpd-log/dependencies new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/examples/s6-rc/wtmpd-log/dependencies @@ -0,0 +1 @@ + diff --git a/examples/s6-rc/wtmpd-log/run b/examples/s6-rc/wtmpd-log/run new file mode 100644 index 0000000..715f41a --- /dev/null +++ b/examples/s6-rc/wtmpd-log/run @@ -0,0 +1,5 @@ +#!/bin/execlineb -P + +s6-setuidgid utmplog +exec -c +s6-log t /var/log/wtmpd diff --git a/examples/s6-rc/wtmpd-log/type b/examples/s6-rc/wtmpd-log/type new file mode 100644 index 0000000..5883cff --- /dev/null +++ b/examples/s6-rc/wtmpd-log/type @@ -0,0 +1 @@ +longrun diff --git a/examples/s6-rc/wtmpd/dependencies b/examples/s6-rc/wtmpd/dependencies new file mode 100644 index 0000000..6cfcf60 --- /dev/null +++ b/examples/s6-rc/wtmpd/dependencies @@ -0,0 +1 @@ +utmps-prepare diff --git a/examples/s6-rc/wtmpd/notification-fd b/examples/s6-rc/wtmpd/notification-fd new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/examples/s6-rc/wtmpd/notification-fd @@ -0,0 +1 @@ +3 diff --git a/examples/s6-rc/wtmpd/pipeline-name b/examples/s6-rc/wtmpd/pipeline-name new file mode 100644 index 0000000..37edf1f --- /dev/null +++ b/examples/s6-rc/wtmpd/pipeline-name @@ -0,0 +1 @@ +wtmpd-pipeline diff --git a/examples/s6-rc/wtmpd/producer-for b/examples/s6-rc/wtmpd/producer-for new file mode 100644 index 0000000..4206ab1 --- /dev/null +++ b/examples/s6-rc/wtmpd/producer-for @@ -0,0 +1 @@ +wtmpd-log diff --git a/examples/s6-rc/wtmpd/run b/examples/s6-rc/wtmpd/run new file mode 100644 index 0000000..b9d9da3 --- /dev/null +++ b/examples/s6-rc/wtmpd/run @@ -0,0 +1,8 @@ +#!/bin/execlineb -P + +fdmove -c 2 1 +s6-setuidgid utmp +cd /run/utmps +fdmove 1 3 +s6-ipcserver -1 -- /run/utmps/wtmpd-socket +utmps-wtmpd diff --git a/examples/s6-rc/wtmpd/type b/examples/s6-rc/wtmpd/type new file mode 100644 index 0000000..5883cff --- /dev/null +++ b/examples/s6-rc/wtmpd/type @@ -0,0 +1 @@ +longrun diff --git a/examples/s6/utmpd/log/run b/examples/s6/utmpd/log/run new file mode 100755 index 0000000..586e53d --- /dev/null +++ b/examples/s6/utmpd/log/run @@ -0,0 +1,5 @@ +#!/bin/execlineb -P + +s6-setuidgid utmplog +exec -c +s6-log t /var/log/utmpd diff --git a/examples/s6/utmpd/notification-fd b/examples/s6/utmpd/notification-fd new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/examples/s6/utmpd/notification-fd @@ -0,0 +1 @@ +3 diff --git a/examples/s6/utmpd/run b/examples/s6/utmpd/run new file mode 100755 index 0000000..238069b --- /dev/null +++ b/examples/s6/utmpd/run @@ -0,0 +1,11 @@ +#!/bin/execlineb -P + +fdmove -c 2 1 +foreground { mkdir -p -m 0755 /run/utmps } +foreground { chown utmp:utmp /run/utmps } +unexport ? +s6-setuidgid utmp +cd /run/utmps +fdmove 1 3 +s6-ipcserver -1 -- /run/utmps/utmpd-socket +utmps-utmpd diff --git a/examples/s6/wtmpd/log/run b/examples/s6/wtmpd/log/run new file mode 100755 index 0000000..5dd01cb --- /dev/null +++ b/examples/s6/wtmpd/log/run @@ -0,0 +1,5 @@ +#!/bin/execlineb -P + +s6-setuidgid utmplog +exec -c +s6-log t /var/log/utmps-wtmpd diff --git a/examples/s6/wtmpd/notification-fd b/examples/s6/wtmpd/notification-fd new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/examples/s6/wtmpd/notification-fd @@ -0,0 +1 @@ +3 diff --git a/examples/s6/wtmpd/run b/examples/s6/wtmpd/run new file mode 100755 index 0000000..9cc49b7 --- /dev/null +++ b/examples/s6/wtmpd/run @@ -0,0 +1,9 @@ +#!/bin/execlineb -P + +fdmove -c 2 1 +unexport ? +s6-setuidgid utmp +cd /run/utmps +fdmove 1 3 +s6-ipcserver -1 -- /run/utmps/wtmpd-socket +utmps-wtmpd 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..303fc9c --- /dev/null +++ b/package/deps.mak @@ -0,0 +1,41 @@ +# +# This file has been generated by tools/gen-deps.sh +# + +src/include/utmps/utmps.h: src/include/utmps/utmpx.h +src/include/utmpx.h: src/include/utmps/utmpx.h +src/utmps/utmps-internal.h: src/include/utmps/utmps.h src/include/utmps/utmpx.h +src/utmps/endutxent.o src/utmps/endutxent.lo: src/utmps/endutxent.c src/utmps/utmps-internal.h src/include/utmps/utmps.h src/include/utmps/utmpx.h +src/utmps/getutxent.o src/utmps/getutxent.lo: src/utmps/getutxent.c src/utmps/utmps-internal.h src/include/utmps/utmps.h src/include/utmps/utmpx.h +src/utmps/getutxid.o src/utmps/getutxid.lo: src/utmps/getutxid.c src/utmps/utmps-internal.h src/include/utmps/utmps.h src/include/utmps/utmpx.h +src/utmps/getutxline.o src/utmps/getutxline.lo: src/utmps/getutxline.c src/utmps/utmps-internal.h src/include/utmps/utmps.h src/include/utmps/utmpx.h +src/utmps/logwtmp.o src/utmps/logwtmp.lo: src/utmps/logwtmp.c src/include/utmps/utmpx.h +src/utmps/pututxline.o src/utmps/pututxline.lo: src/utmps/pututxline.c src/utmps/utmps-internal.h src/include/utmps/utmps.h src/include/utmps/utmpx.h +src/utmps/setutxent.o src/utmps/setutxent.lo: src/utmps/setutxent.c src/utmps/utmps-internal.h src/include/utmps/utmps.h src/include/utmps/utmpx.h +src/utmps/utmps-utmpd.o src/utmps/utmps-utmpd.lo: src/utmps/utmps-utmpd.c src/utmps/utmps-internal.h src/include/utmps/utmpx.h +src/utmps/utmps-wtmpd.o src/utmps/utmps-wtmpd.lo: src/utmps/utmps-wtmpd.c src/utmps/utmps-internal.h src/include/utmps/utmpx.h +src/utmps/utmps_end.o src/utmps/utmps_end.lo: src/utmps/utmps_end.c src/include/utmps/utmps.h +src/utmps/utmps_getent.o src/utmps/utmps_getent.lo: src/utmps/utmps_getent.c src/utmps/utmps-internal.h src/include/utmps/utmps.h src/include/utmps/utmpx.h +src/utmps/utmps_getid.o src/utmps/utmps_getid.lo: src/utmps/utmps_getid.c src/utmps/utmps-internal.h src/include/utmps/utmps.h src/include/utmps/utmpx.h +src/utmps/utmps_getline.o src/utmps/utmps_getline.lo: src/utmps/utmps_getline.c src/utmps/utmps-internal.h src/include/utmps/utmps.h src/include/utmps/utmpx.h +src/utmps/utmps_here.o src/utmps/utmps_here.lo: src/utmps/utmps_here.c src/utmps/utmps-internal.h src/include/utmps/utmps.h src/include/utmps/utmpx.h +src/utmps/utmps_here_maybe_init.o src/utmps/utmps_here_maybe_init.lo: src/utmps/utmps_here_maybe_init.c src/utmps/utmps-internal.h src/include/utmps/config.h src/include/utmps/utmps.h +src/utmps/utmps_putline.o src/utmps/utmps_putline.lo: src/utmps/utmps_putline.c src/utmps/utmps-internal.h src/include/utmps/utmps.h src/include/utmps/utmpx.h +src/utmps/utmps_rewind.o src/utmps/utmps_rewind.lo: src/utmps/utmps_rewind.c src/utmps/utmps-internal.h src/include/utmps/utmps.h +src/utmps/utmps_start.o src/utmps/utmps_start.lo: src/utmps/utmps_start.c src/include/utmps/utmps.h +src/utmps/utmps_updwtmpx.o src/utmps/utmps_updwtmpx.lo: src/utmps/utmps_updwtmpx.c src/utmps/utmps-internal.h src/include/utmps/utmps.h src/include/utmps/utmpx.h +src/utmps/utmps_utmpx_pack.o src/utmps/utmps_utmpx_pack.lo: src/utmps/utmps_utmpx_pack.c src/include/utmps/utmpx.h +src/utmps/utmps_utmpx_unpack.o src/utmps/utmps_utmpx_unpack.lo: src/utmps/utmps_utmpx_unpack.c src/include/utmps/utmpx.h +src/utmps/updwtmpx.o src/utmps/updwtmpx.lo: src/utmps/updwtmpx.c src/include/utmps/config.h src/include/utmps/utmps.h + +ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),) +libutmps.a.xyzzy: src/utmps/endutxent.o src/utmps/getutxent.o src/utmps/getutxid.o src/utmps/getutxline.o src/utmps/logwtmp.o src/utmps/pututxline.o src/utmps/setutxent.o src/utmps/utmps_end.o src/utmps/utmps_getent.o src/utmps/utmps_getid.o src/utmps/utmps_getline.o src/utmps/utmps_here.o src/utmps/utmps_here_maybe_init.o src/utmps/utmps_putline.o src/utmps/utmps_rewind.o src/utmps/utmps_start.o src/utmps/utmps_updwtmpx.o src/utmps/utmps_utmpx_pack.o src/utmps/utmps_utmpx_unpack.o src/utmps/updwtmpx.o +else +libutmps.a.xyzzy: src/utmps/endutxent.lo src/utmps/getutxent.lo src/utmps/getutxid.lo src/utmps/getutxline.lo src/utmps/logwtmp.lo src/utmps/pututxline.lo src/utmps/setutxent.lo src/utmps/utmps_end.lo src/utmps/utmps_getent.lo src/utmps/utmps_getid.lo src/utmps/utmps_getline.lo src/utmps/utmps_here.lo src/utmps/utmps_here_maybe_init.lo src/utmps/utmps_putline.lo src/utmps/utmps_rewind.lo src/utmps/utmps_start.lo src/utmps/utmps_updwtmpx.lo src/utmps/utmps_utmpx_pack.lo src/utmps/utmps_utmpx_unpack.lo src/utmps/updwtmpx.lo +endif +libutmps.so.xyzzy: EXTRA_LIBS := -lskarnet +libutmps.so.xyzzy: src/utmps/endutxent.lo src/utmps/getutxent.lo src/utmps/getutxid.lo src/utmps/getutxline.lo src/utmps/logwtmp.lo src/utmps/pututxline.lo src/utmps/setutxent.lo src/utmps/utmps_end.lo src/utmps/utmps_getent.lo src/utmps/utmps_getid.lo src/utmps/utmps_getline.lo src/utmps/utmps_here.lo src/utmps/utmps_here_maybe_init.lo src/utmps/utmps_putline.lo src/utmps/utmps_rewind.lo src/utmps/utmps_start.lo src/utmps/utmps_updwtmpx.lo src/utmps/utmps_utmpx_pack.lo src/utmps/utmps_utmpx_unpack.lo src/utmps/updwtmpx.lo +utmps-utmpd: EXTRA_LIBS := +utmps-utmpd: src/utmps/utmps-utmpd.o libutmps.a.xyzzy -lskarnet +utmps-wtmpd: EXTRA_LIBS := +utmps-wtmpd: src/utmps/utmps-wtmpd.o libutmps.a.xyzzy -lskarnet diff --git a/package/info b/package/info new file mode 100644 index 0000000..ef6ce64 --- /dev/null +++ b/package/info @@ -0,0 +1,4 @@ +package=utmps +version=0.0.1.0 +category=admin +package_macro_name=UTMPS diff --git a/package/modes b/package/modes new file mode 100644 index 0000000..39e777c --- /dev/null +++ b/package/modes @@ -0,0 +1,2 @@ +utmps-utmpd 0755 +utmps-wtmpd 0755 diff --git a/package/targets.mak b/package/targets.mak new file mode 100644 index 0000000..ff763be --- /dev/null +++ b/package/targets.mak @@ -0,0 +1,7 @@ +BIN_TARGETS := \ +utmps-utmpd \ +utmps-wtmpd + +LIBEXEC_TARGETS := + +LIB_DEFS := UTMPS=utmps diff --git a/patch-for-solaris b/patch-for-solaris new file mode 100755 index 0000000..2d1296b --- /dev/null +++ b/patch-for-solaris @@ -0,0 +1,21 @@ +#!/usr/xpg4/bin/sh + +patchit () { + echo '#!/usr/xpg4/bin/sh' > $1.tmp + tail -n +2 $1 >> $1.tmp + mv -f $1.tmp $1 + chmod 755 $1 +} + +# Solaris doesn't understand POSIX.1-2008 either. +sed -e 's/XOPEN_SOURCE=700/XOPEN_SOURCE=600/' < configure > configure.tmp +mv -f configure.tmp configure + +patchit ./configure +patchit ./tools/install.sh +patchit ./tools/gen-deps.sh + +echo 'SHELL := /usr/xpg4/bin/sh' > Makefile.tmp +echo >> Makefile.tmp +cat Makefile >> Makefile.tmp +mv -f Makefile.tmp Makefile diff --git a/src/include/utmps/utmps.h b/src/include/utmps/utmps.h new file mode 100644 index 0000000..e4760f9 --- /dev/null +++ b/src/include/utmps/utmps.h @@ -0,0 +1,35 @@ +/* ISC license. */ + +#ifndef UTMPS_H +#define UTMPS_H + +#include +#include + +typedef struct utmps_s utmps, *utmps_ref ; +struct utmps_s +{ + int fd ; +} ; +#define UTMPS_ZERO { .fd = -1 } + +extern int utmps_start (utmps *, char const *, tain_t const *, tain_t *) ; +#define utmps_start_g(a, s, deadline) utmps_start(a, s, (deadline), &STAMP) + +extern void utmps_end (utmps *) ; + +extern int utmps_rewind (utmps *, tain_t const *, tain_t *) ; +#define utmps_rewind_g (a, deadline) utmps_rewind(a, (deadline), &STAMP) +extern int utmps_getent (utmps *, struct utmpx *, tain_t const *, tain_t *) ; +#define utmps_getent_g (a, b, deadline) utmps_getent(a, b, (deadline), &STAMP) +extern int utmps_getid (utmps *, unsigned short, char const *, struct utmpx *, tain_t const *, tain_t *) ; +#define utmps_getid_g(a, type, id, b, deadline) utmps_getid(a, type, id, b, (deadline), &STAMP) +extern int utmps_getline (utmps *, char const *, struct utmpx *, tain_t const *, tain_t *) ; +#define utmps_getline_g(a, line, b, deadline) utmps_getline(a, line, b, (deadline), &STAMP) +extern int utmps_putline (utmps *, struct utmpx const *, tain_t const *, tain_t *) ; +#define utmps_putline_g(a, entry, deadline) utmps_putline(a, entry, (deadine), &STAMP) + +extern int utmps_updwtmpx (char const *, struct utmpx const *, tain_t const *, tain_t *) ; +#define utmps_updwtmpx_g(file, b, deadline) utmps_updwtmpx(file, b, (deadline), &STAMP) + +#endif diff --git a/src/include/utmps/utmpx.h b/src/include/utmps/utmpx.h new file mode 100644 index 0000000..4752964 --- /dev/null +++ b/src/include/utmps/utmpx.h @@ -0,0 +1,75 @@ +/* ISC license. */ + +#ifndef UTMPS_UTMPX_H +#define UTMPS_UTMPX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#define UTMPS_UT_LINESIZE 32 +#define UTMPS_UT_NAMESIZE 32 +#define UTMPS_UT_HOSTSIZE 256 +#define UTMPS_UT_IDSIZE 4 + +struct exit_status +{ + short e_termination ; + short e_exit ; +} ; + +struct utmpx +{ + short ut_type ; + pid_t ut_pid ; + char ut_line[UTMPS_UT_LINESIZE] ; + char ut_id[UTMPS_UT_IDSIZE] ; + char ut_user[UTMPS_UT_NAMESIZE] ; + + char ut_host[UTMPS_UT_HOSTSIZE] ; + struct exit_status ut_exit ; + pid_t ut_session ; + + struct timeval ut_tv ; + + uint32_t ut_addr_v6[4] ; + char __unused[20] ; +} ; + +#define ut_name ut_user + +#define EMPTY 0 +#define BOOT_TIME 2 +#define OLD_TIME 4 +#define NEW_TIME 3 +#define USER_PROCESS 7 +#define INIT_PROCESS 5 +#define LOGIN_PROCESS 6 +#define DEAD_PROCESS 8 + +#define RUN_LVL 1 +#define ACCOUNTING 9 + +extern void endutxent (void) ; +extern void setutxent (void) ; +extern struct utmpx *getutxent (void) ; +extern struct utmpx *getutxid (struct utmpx const *) ; +extern struct utmpx *getutxline (struct utmpx const *) ; +extern struct utmpx *pututxline (struct utmpx const *) ; + +extern void updwtmpx (char const *, struct utmpx const *) ; +extern void logwtmp (char const *, char const *, char const *) ; + +#define UT_LINESIZE UTMPS_UT_LINESIZE +#define UT_NAMESIZE UTMPS_UT_NAMESIZE +#define UT_HOSTSIZE UTMPS_UT_HOSTSIZE + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/include/utmpx.h b/src/include/utmpx.h new file mode 100644 index 0000000..fc61b8b --- /dev/null +++ b/src/include/utmpx.h @@ -0,0 +1,13 @@ +/* ISC license. */ + +/* + This file is part of the utmps package. + See https://skarnet.org/software/utmps/ +*/ + +#ifndef UTMPX_H +#define UTMPX_H + +#include + +#endif diff --git a/src/utmps/deps-exe/utmps-utmpd b/src/utmps/deps-exe/utmps-utmpd new file mode 100644 index 0000000..60d8fd7 --- /dev/null +++ b/src/utmps/deps-exe/utmps-utmpd @@ -0,0 +1,2 @@ +libutmps.a.xyzzy +-lskarnet diff --git a/src/utmps/deps-exe/utmps-wtmpd b/src/utmps/deps-exe/utmps-wtmpd new file mode 100644 index 0000000..60d8fd7 --- /dev/null +++ b/src/utmps/deps-exe/utmps-wtmpd @@ -0,0 +1,2 @@ +libutmps.a.xyzzy +-lskarnet diff --git a/src/utmps/deps-lib/utmps b/src/utmps/deps-lib/utmps new file mode 100644 index 0000000..430b7fb --- /dev/null +++ b/src/utmps/deps-lib/utmps @@ -0,0 +1,21 @@ +endutxent.o +getutxent.o +getutxid.o +getutxline.o +logwtmp.o +pututxline.o +setutxent.o +updwtmpx.o +utmps_end.o +utmps_getent.o +utmps_getid.o +utmps_getline.o +utmps_here.o +utmps_here_maybe_init.o +utmps_putline.o +utmps_rewind.o +utmps_start.o +utmps_updwtmpx.o +utmps_utmpx_pack.o +utmps_utmpx_unpack.o +-lskarnet diff --git a/src/utmps/endutxent.c b/src/utmps/endutxent.c new file mode 100644 index 0000000..bc93778 --- /dev/null +++ b/src/utmps/endutxent.c @@ -0,0 +1,10 @@ +/* ISC license. */ + +#include +#include +#include "utmps-internal.h" + +void endutxent (void) +{ + utmps_end(&utmps_here) ; +} diff --git a/src/utmps/getutxent.c b/src/utmps/getutxent.c new file mode 100644 index 0000000..97a5917 --- /dev/null +++ b/src/utmps/getutxent.c @@ -0,0 +1,12 @@ +/* ISC license. */ + +#include +#include +#include "utmps-internal.h" + +struct utmpx *getutxent (void) +{ + utmps_here_maybe_init() ; + if (!utmps_getent(&utmps_here, &utmps_utmpx_here, 0, 0)) return 0 ; + return &utmps_utmpx_here ; +} diff --git a/src/utmps/getutxid.c b/src/utmps/getutxid.c new file mode 100644 index 0000000..262f35c --- /dev/null +++ b/src/utmps/getutxid.c @@ -0,0 +1,12 @@ +/* ISC license. */ + +#include +#include +#include "utmps-internal.h" + +struct utmpx *getutxid (struct utmpx const *b) +{ + utmps_here_maybe_init() ; + if (!utmps_getid(&utmps_here, (unsigned short)b->ut_type, b->ut_id, &utmps_utmpx_here, 0, 0)) return 0 ; + return &utmps_utmpx_here ; +} diff --git a/src/utmps/getutxline.c b/src/utmps/getutxline.c new file mode 100644 index 0000000..e950816 --- /dev/null +++ b/src/utmps/getutxline.c @@ -0,0 +1,12 @@ +/* ISC license. */ + +#include +#include +#include "utmps-internal.h" + +struct utmpx *getutxline (struct utmpx const *b) +{ + utmps_here_maybe_init() ; + if (!utmps_getline(&utmps_here, b->ut_line, &utmps_utmpx_here, 0, 0)) return 0 ; + return &utmps_utmpx_here ; +} diff --git a/src/utmps/logwtmp.c b/src/utmps/logwtmp.c new file mode 100644 index 0000000..e50b68d --- /dev/null +++ b/src/utmps/logwtmp.c @@ -0,0 +1,22 @@ +/* ISC license. */ + +#include +#include +#include +#include + +void logwtmp (char const *line, char const *name, char const *host) +{ + struct utmpx b ; + memset(&b, 0, sizeof(struct utmpx)) ; + strncpy(b.ut_line, line, UTMPS_UT_LINESIZE - 1) ; + strncpy(b.ut_user, name, UTMPS_UT_NAMESIZE - 1) ; + strncpy(b.ut_host, host, UTMPS_UT_HOSTSIZE - 1) ; + b.ut_pid = getpid() ; + { + tain_t now ; + tain_now(&now) ; + timeval_from_tain(&b.ut_tv, &now) ; + } + updwtmpx("", &b) ; +} diff --git a/src/utmps/pututxline.c b/src/utmps/pututxline.c new file mode 100644 index 0000000..4e149d8 --- /dev/null +++ b/src/utmps/pututxline.c @@ -0,0 +1,14 @@ +/* ISC license. */ + +#include +#include +#include "utmps-internal.h" + +struct utmpx *pututxline (struct utmpx const *b) +{ + static struct utmpx here ; /* POSIX says we can't use utmps_utmpx_here */ + utmps_here_maybe_init() ; + if (!utmps_putline(&utmps_here, b, 0, 0)) return 0 ; + here = *b ; + return &here ; +} diff --git a/src/utmps/setutxent.c b/src/utmps/setutxent.c new file mode 100644 index 0000000..b8b8199 --- /dev/null +++ b/src/utmps/setutxent.c @@ -0,0 +1,11 @@ +/* ISC license. */ + +#include +#include +#include "utmps-internal.h" + +void setutxent (void) +{ + utmps_here_maybe_init() ; + utmps_rewind(&utmps_here, 0, 0) ; +} diff --git a/src/utmps/updwtmpx.c b/src/utmps/updwtmpx.c new file mode 100644 index 0000000..0166448 --- /dev/null +++ b/src/utmps/updwtmpx.c @@ -0,0 +1,10 @@ +/* ISC license. */ + +#include +#include + +void updwtmpx (char const *file, struct utmpx const *b) +{ + (void)file ; + utmps_updwtmpx(UTMPS_WTMPD_PATH, b, 0, 0) ; +} diff --git a/src/utmps/utmps-internal.h b/src/utmps/utmps-internal.h new file mode 100644 index 0000000..476e100 --- /dev/null +++ b/src/utmps/utmps-internal.h @@ -0,0 +1,16 @@ +/* ISC license. */ + +#ifndef UTMPS_INTERNAL_H +#define UTMPS_INTERNAL_H + +#include +#include + +extern struct utmpx utmps_utmpx_here ; +extern utmps utmps_here ; +extern void utmps_here_maybe_init (void) ; + +extern void utmps_utmpx_pack (char *, struct utmpx const *) ; +extern void utmps_utmpx_unpack (char const *, struct utmpx *) ; + +#endif diff --git a/src/utmps/utmps-utmpd.c b/src/utmps/utmps-utmpd.c new file mode 100644 index 0000000..e460368 --- /dev/null +++ b/src/utmps/utmps-utmpd.c @@ -0,0 +1,216 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "utmps-internal.h" + +static int fd = -1 ; + +static void get0 (char *s, size_t n) +{ + tain_t deadline ; + tain_ulong(&deadline, 2) ; + tain_add_g(&deadline, &deadline) ; + if (buffer_timed_get_g(buffer_0small, s, n, &deadline) < n) + strerr_diefu1sys(111, "read from stdin") ; +} + +static void flush1 (void) +{ + tain_t deadline ; + tain_ulong(&deadline, 2) ; + tain_add_g(&deadline, &deadline) ; + if (!buffer_timed_flush_g(buffer_1small, &deadline)) + strerr_diefu1sys(111, "write to stdout") ; +} + +static void answer (int e) +{ + char c = e ; + buffer_putnoflush(buffer_1small, &c, 1) ; + flush1() ; +} + +static void maybe_open (void) +{ + if (fd < 0) + { + fd = open("utmp", O_RDWR | O_CREAT) ; + if (fd < 0) + { + int e = errno ; + answer(e) ; + errno = e ; + strerr_diefu1sys(111, "open utmp file") ; + } + } +} + +static int read_utmp_entry (char *s) +{ + ssize_t r ; + int e ; + if (lock_sh(fd) < 0) { e = errno ; goto err ; } + r = read(fd, s, sizeof(struct utmpx)) ; + lock_unx(fd) ; + if (r < 0) { e = errno ; goto err ; } + if (!r) return 0 ; + if (r < sizeof(struct utmpx)) { e = EPIPE ; goto err ; } + return 1 ; + err: + unlink("utmp") ; + answer(e) ; + errno = e ; + strerr_diefu1sys(111, "read utmp file") ; +} + +static int idmatch (unsigned short type, char const *id, struct utmpx const *b) +{ + if (type == BOOT_TIME || type == OLD_TIME || type == NEW_TIME) + { + if (type == (unsigned short)b->ut_type) return 1 ; + } + else if (type == INIT_PROCESS || type == LOGIN_PROCESS || type == USER_PROCESS || type == DEAD_PROCESS) + { + if ((b->ut_type == INIT_PROCESS || b->ut_type == LOGIN_PROCESS || b->ut_type == USER_PROCESS || b->ut_type == DEAD_PROCESS) + && !strncmp(id, b->ut_id, UTMPS_UT_IDSIZE - 1)) return 1 ; + } + return 0 ; +} + +static void do_getent (void) +{ + struct utmpx b ; + char buf[1 + sizeof(struct utmpx)] = "" ; + maybe_open() ; + if (!read_utmp_entry(buf+1)) { answer(ESRCH) ; return ; } + utmps_utmpx_unpack(buf+1, &b) ; + utmps_utmpx_pack(buf+1, &b) ; + buffer_putnoflush(buffer_1small, buf, 1 + sizeof(struct utmpx)) ; + flush1() ; +} + +static void do_getid (void) +{ + unsigned short type ; + char rbuf[USHORT_PACK + UTMPS_UT_IDSIZE] ; + char sbuf[1 + sizeof(struct utmpx)] = "" ; + get0(rbuf, USHORT_PACK + UTMPS_UT_IDSIZE) ; + ushort_unpack_big(rbuf, &type) ; + rbuf[USHORT_PACK + UTMPS_UT_IDSIZE - 1] = 0 ; + maybe_open() ; + for (;;) + { + struct utmpx b ; + if (!read_utmp_entry(sbuf+1)) { answer(ESRCH) ; return ; } + utmps_utmpx_unpack(sbuf+1, &b) ; + if (idmatch(type, rbuf + USHORT_PACK, &b)) break ; + } + buffer_putnoflush(buffer_1small, sbuf, 1 + sizeof(struct utmpx)) ; + flush1() ; +} + +static void do_getline (void) +{ + char rbuf[UTMPS_UT_LINESIZE] ; + char sbuf[1 + sizeof(struct utmpx)] = "" ; + get0(rbuf, UTMPS_UT_LINESIZE) ; + rbuf[UTMPS_UT_LINESIZE - 1] = 0 ; + maybe_open() ; + for (;;) + { + struct utmpx b ; + if (!read_utmp_entry(sbuf+1)) { answer(ESRCH) ; return ; } + utmps_utmpx_unpack(sbuf+1, &b) ; + if ((b.ut_type == LOGIN_PROCESS || b.ut_type == USER_PROCESS) + && !strncmp(rbuf, b.ut_line, UTMPS_UT_LINESIZE - 1)) break ; + } + buffer_putnoflush(buffer_1small, sbuf, 1 + sizeof(struct utmpx)) ; + flush1() ; +} + +static void do_putline (uid_t uid) +{ + struct utmpx u ; + char buf[sizeof(struct utmpx)] ; + get0(buf, sizeof(struct utmpx)) ; + if (uid) { answer(EPERM) ; return ; } + utmps_utmpx_unpack(buf, &u) ; + maybe_open() ; + for (;;) + { + struct utmpx b ; + char tmp[sizeof(struct utmpx)] ; + if (!read_utmp_entry(tmp)) goto writeit ; + utmps_utmpx_unpack(tmp, &b) ; + if (idmatch(u.ut_type, u.ut_id, &b)) break ; + } + if (lseek(fd, -sizeof(struct utmpx), SEEK_CUR) < 0) + { + answer(errno) ; + return ; + } + writeit: + utmps_utmpx_pack(buf, &u) ; + if (lock_ex(fd) < 0) { answer(errno) ; return ; } + if (allwrite(fd, buf, sizeof(struct utmpx)) < sizeof(struct utmpx)) + { + int e = errno ; + answer(e) ; + errno = e ; + strerr_diefu1sys(111, "write to utmp") ; + } + fsync(fd) ; + lock_unx(fd) ; + answer(0) ; +} + +static void do_rewind (void) +{ + maybe_open() ; + if (lseek(fd, 0, SEEK_SET) < 0) { answer(errno) ; return ; } + answer(0) ; +} + +int main (void) +{ + uid_t uid ; + char const *x = ucspi_get("REMOTEEUID") ; + if (!x) strerr_diefu1x(100, "get $IPCREMOTEEUID from environment") ; + if (!uid0_scan(x, &uid)) strerr_dieinvalid(100, "IPCREMOTEEUID") ; + if (ndelay_on(0) < 0) strerr_diefu1sys(111, "set stdin non-blocking") ; + tain_now_g() ; + + for (;;) + { + tain_t deadline ; + char c ; + tain_add_g(&deadline, &tain_infinite_relative) ; + if (!buffer_timed_get_g(buffer_0small, &c, 1, &deadline)) break ; + switch (c) + { + case 'e' : do_getent() ; break ; + case 'i' : do_getid() ; break ; + case 'l' : do_getline() ; break ; + case 'E' : do_putline(uid) ; break ; + case 'r' : do_rewind() ; break ; + default : + errno = EPROTO ; + strerr_diefu1sys(1, "interpret stdin") ; + } + } + return 0 ; +} diff --git a/src/utmps/utmps-wtmpd.c b/src/utmps/utmps-wtmpd.c new file mode 100644 index 0000000..b8ff5c3 --- /dev/null +++ b/src/utmps/utmps-wtmpd.c @@ -0,0 +1,107 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "utmps-internal.h" + +static void answer (int e) +{ + char c = e ; + write(1, &c, 1) ; +} + +int main (void) +{ + struct utmpx b ; + char const *x ; + tain_t deadline ; + size_t w ; + uid_t uid ; + int fd ; + char buf[sizeof(struct utmpx)] ; + PROG = "utmps-wtmpd" ; + + x = ucspi_get("REMOTEEUID") ; + if (!x) strerr_diefu1x(100, "get $IPCREMOTEEUID from environment") ; + if (!uid0_scan(x, &uid)) strerr_dieinvalid(100, "IPCREMOTEEUID") ; + if (ndelay_on(0) < 0) strerr_diefu1sys(111, "set stdin non-blocking") ; + tain_now_g() ; + tain_ulong(&deadline, 2) ; + tain_add_g(&deadline, &deadline) ; + + w = buffer_timed_get_g(buffer_0small, buf, 1, &deadline) ; + if (!w) strerr_diefu1sys(111, "read from stdin") ; + if (buf[0] != '+') { errno = EPROTO ; strerr_diefu1sys(111, "read command") ; } + w = buffer_timed_get_g(buffer_0small, buf, sizeof(struct utmpx), &deadline) ; + if (w < sizeof(struct utmpx)) strerr_diefu1sys(111, "read from stdin") ; + utmps_utmpx_unpack(buf, &b) ; + if (uid) + { + struct passwd *pw ; + errno = 0 ; + pw = getpwnam(b.ut_user) ; + if (!pw) + { + if (errno) + { + answer(errno) ; + strerr_diefu1sys(111, "read user database") ; + } + else + { + answer(EPERM) ; + strerr_diefu2x(1, "verify ut_user identity", ": no such user") ; + } + } + if (pw->pw_uid != uid) + { + answer(EPERM) ; + strerr_diefu2x(1, "verify ut_user identity", ": uid mismatch") ; + } + } + + fd = open_append("wtmp") ; + if (fd < 0) + { + answer(errno) ; + strerr_diefu1sys(111, "open wtmp") ; + } + if (lock_ex(fd) < 0) + { + answer(errno) ; + strerr_diefu1sys(111, "open wtmp") ; + } + if (lseek(fd, 0, SEEK_END) < 0) + { + answer(errno) ; + strerr_diefu1sys(111, "lseek on wtmp") ; + } + w = allwrite(fd, buf + 1, sizeof(struct utmpx)) ; + if (w < sizeof(struct utmpx)) + { + int e = errno ; + if (w) + { + struct stat st ; + if (!fstat(fd, &st)) ftruncate(fd, st.st_size - w) ; + } + answer(e) ; + strerr_diefu1sys(111, "append to wtmp") ; + } + fsync(fd) ; + answer(0) ; + return 0 ; +} diff --git a/src/utmps/utmps_end.c b/src/utmps/utmps_end.c new file mode 100644 index 0000000..141dfb7 --- /dev/null +++ b/src/utmps/utmps_end.c @@ -0,0 +1,10 @@ +/* ISC license. */ + +#include +#include + +void utmps_end (utmps *a) +{ + fd_close(a->fd) ; + a->fd = -1 ; +} diff --git a/src/utmps/utmps_getent.c b/src/utmps/utmps_getent.c new file mode 100644 index 0000000..2b21b04 --- /dev/null +++ b/src/utmps/utmps_getent.c @@ -0,0 +1,21 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include "utmps-internal.h" + +int utmps_getent (utmps *a, struct utmpx *b, tain_t const *deadline, tain_t *stamp) +{ + ssize_t r ; + char buf[1 + sizeof(struct utmpx)] ; + if (!ipc_timed_send(a->fd, "e", 1, deadline, stamp)) return 0 ; + r = ipc_timed_recv(a->fd, buf, sizeof(buf), 0, deadline, stamp) ; + if (r < 0) return 0 ; + if (!r) return (errno = EPIPE, 0) ; + if (buf[0]) return (errno = buf[0], 0) ; + utmps_utmpx_unpack(buf + 1, b) ; + return 1 ; +} diff --git a/src/utmps/utmps_getid.c b/src/utmps/utmps_getid.c new file mode 100644 index 0000000..622fec8 --- /dev/null +++ b/src/utmps/utmps_getid.c @@ -0,0 +1,27 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include +#include "utmps-internal.h" + +int utmps_getid (utmps *a, unsigned short type, char const *id, struct utmpx *b, tain_t const *deadline, tain_t *stamp) +{ + ssize_t r ; + char sbuf[1 + USHORT_PACK + UTMPS_UT_IDSIZE] = "i" ; + char rbuf[1 + sizeof(struct utmpx)] ; + ushort_pack_big(sbuf + 1, type) ; + memset(sbuf + 1 + USHORT_PACK, 0, UTMPS_UT_IDSIZE) ; + strncpy(sbuf + 1 + USHORT_PACK, id, UTMPS_UT_IDSIZE - 1) ; + if (!ipc_timed_send(a->fd, sbuf, sizeof(sbuf), deadline, stamp)) return 0 ; + r = ipc_timed_recv(a->fd, rbuf, sizeof(rbuf), 0, deadline, stamp) ; + if (r < 0) return 0 ; + if (!r) return (errno = EPIPE, 0) ; + if (rbuf[0]) return (errno = rbuf[0], 0) ; + utmps_utmpx_unpack(rbuf + 1, b) ; + return 1 ; +} diff --git a/src/utmps/utmps_getline.c b/src/utmps/utmps_getline.c new file mode 100644 index 0000000..4612082 --- /dev/null +++ b/src/utmps/utmps_getline.c @@ -0,0 +1,25 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include "utmps-internal.h" + +int utmps_getline (utmps *a, char const *line, struct utmpx *b, tain_t const *deadline, tain_t *stamp) +{ + ssize_t r ; + char sbuf[1 + UTMPS_UT_LINESIZE] = "l" ; + char rbuf[1 + sizeof(struct utmpx)] ; + memset(sbuf + 1, 0, UTMPS_UT_LINESIZE) ; + strncpy(sbuf + 1, line, UTMPS_UT_LINESIZE - 1) ; + if (!ipc_timed_send(a->fd, sbuf, sizeof(sbuf), deadline, stamp)) return 0 ; + r = ipc_timed_recv(a->fd, rbuf, sizeof(rbuf), 0, deadline, stamp) ; + if (r < 0) return 0 ; + if (!r) return (errno = EPIPE, 0) ; + if (rbuf[0]) return (errno = rbuf[0], 0) ; + utmps_utmpx_unpack(rbuf + 1, b) ; + return 1 ; +} diff --git a/src/utmps/utmps_here.c b/src/utmps/utmps_here.c new file mode 100644 index 0000000..2844c1e --- /dev/null +++ b/src/utmps/utmps_here.c @@ -0,0 +1,8 @@ +/* ISC license. */ + +#include +#include +#include "utmps-internal.h" + +struct utmpx utmps_utmpx_here ; +utmps utmps_here = UTMPS_ZERO ; diff --git a/src/utmps/utmps_here_maybe_init.c b/src/utmps/utmps_here_maybe_init.c new file mode 100644 index 0000000..4f3e207 --- /dev/null +++ b/src/utmps/utmps_here_maybe_init.c @@ -0,0 +1,11 @@ +/* ISC license. */ + +#include +#include +#include "utmps-internal.h" + +void utmps_here_maybe_init (void) +{ + if (utmps_here.fd < 0) + utmps_start(&utmps_here, UTMPS_UTMPD_PATH, 0, 0) ; +} diff --git a/src/utmps/utmps_putline.c b/src/utmps/utmps_putline.c new file mode 100644 index 0000000..306fa1b --- /dev/null +++ b/src/utmps/utmps_putline.c @@ -0,0 +1,22 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include +#include "utmps-internal.h" + +int utmps_putline (utmps *a, struct utmpx const *b, tain_t const *deadline, tain_t *stamp) +{ + ssize_t r ; + char buf[1 + sizeof(struct utmpx)] = "E" ; + utmps_utmpx_pack(buf + 1, b) ; + if (!ipc_timed_send(a->fd, buf, sizeof(buf), deadline, stamp)) return 0 ; + r = ipc_timed_recv(a->fd, buf, 1, 0, deadline, stamp) ; + if (r < 0) return 0 ; + if (!r) return (errno = EPIPE, 0) ; + if (buf[0]) return (errno = buf[0], 0) ; + return 1 ; +} diff --git a/src/utmps/utmps_rewind.c b/src/utmps/utmps_rewind.c new file mode 100644 index 0000000..371cb0d --- /dev/null +++ b/src/utmps/utmps_rewind.c @@ -0,0 +1,19 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include "utmps-internal.h" + +int utmps_rewind (utmps *a, tain_t const *deadline, tain_t *stamp) +{ + ssize_t r ; + char c ; + if (!ipc_timed_send(a->fd, "r", 1, deadline, stamp)) return 0 ; + r = ipc_timed_recv(a->fd, &c, 1, 0, deadline, stamp) ; + if (r < 0) return 0 ; + if (!r) return (errno = EPIPE, 0) ; + if (c) return (errno = c, 0) ; + return 1 ; +} diff --git a/src/utmps/utmps_start.c b/src/utmps/utmps_start.c new file mode 100644 index 0000000..095fd2c --- /dev/null +++ b/src/utmps/utmps_start.c @@ -0,0 +1,18 @@ +/* ISC license. */ + +#include +#include +#include + +int utmps_start (utmps *a, char const *path, tain_t const *deadline, tain_t *stamp) +{ + int fd = ipc_stream_nbcoe() ; + if (fd < 0) return 0 ; + if (!ipc_timed_connect(fd, path, deadline, stamp)) + { + fd_close(fd) ; + return 0 ; + } + a->fd = fd ; + return 1 ; +} diff --git a/src/utmps/utmps_updwtmpx.c b/src/utmps/utmps_updwtmpx.c new file mode 100644 index 0000000..55811c4 --- /dev/null +++ b/src/utmps/utmps_updwtmpx.c @@ -0,0 +1,28 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include "utmps-internal.h" + +int utmps_updwtmpx (char const *path, struct utmpx const *b, tain_t const *deadline, tain_t *stamp) +{ + utmps a = UTMPS_ZERO ; + ssize_t r ; + char buf[1 + sizeof(struct utmpx)] = "+" ; + if (!utmps_start(&a, path, deadline, stamp)) return 0 ; + utmps_utmpx_pack(buf + 1, b) ; + if (!ipc_timed_send(a.fd, buf, 1 + sizeof(struct utmpx), deadline, stamp)) goto err ; + r = ipc_timed_recv(a.fd, buf, 1, 0, deadline, stamp) ; + if (r < 0) goto err ; + if (!r) { errno = EPIPE ; goto err ; } + if (buf[0]) { errno = buf[0] ; goto err ; } + utmps_end(&a) ; + return 1 ; + + err : + utmps_end(&a) ; + return 0 ; +} diff --git a/src/utmps/utmps_utmpx_pack.c b/src/utmps/utmps_utmpx_pack.c new file mode 100644 index 0000000..c5efecb --- /dev/null +++ b/src/utmps/utmps_utmpx_pack.c @@ -0,0 +1,9 @@ +/* ISC license. */ + +#include +#include + +void utmps_utmpx_pack (char *s, struct utmpx const *u) +{ + memcpy(s, u, sizeof(struct utmpx)) ; +} diff --git a/src/utmps/utmps_utmpx_unpack.c b/src/utmps/utmps_utmpx_unpack.c new file mode 100644 index 0000000..a774356 --- /dev/null +++ b/src/utmps/utmps_utmpx_unpack.c @@ -0,0 +1,13 @@ +/* ISC license. */ + +#include +#include + +void utmps_utmpx_unpack (char const *s, struct utmpx *b) +{ + memcpy(b, s, sizeof(struct utmpx)) ; + b->ut_user[UTMPS_UT_NAMESIZE - 1] = 0 ; + b->ut_id[UTMPS_UT_IDSIZE - 1] = 0 ; + b->ut_line[UTMPS_UT_LINESIZE - 1] = 0 ; + b->ut_host[UTMPS_UT_HOSTSIZE - 1] = 0 ; +} diff --git a/tools/gen-deps.sh b/tools/gen-deps.sh new file mode 100755 index 0000000..6383ac2 --- /dev/null +++ b/tools/gen-deps.sh @@ -0,0 +1,93 @@ +#!/bin/sh -e + +. package/info + +echo '#' +echo '# This file has been generated by tools/gen-deps.sh' +echo '#' +echo + +for dir in src/include/${package} src/* ; do + for file in $(ls -1 $dir | grep -- \\.h$) ; do + { + grep -F -- "#include <${package}/" < ${dir}/$file | cut -d'<' -f2 | cut -d'>' -f1 ; + grep -- '#include ".*\.h"' < ${dir}/$file | cut -d'"' -f2 + } | sort -u | { + deps= + while read dep ; do + if echo $dep | grep -q "^${package}/" ; then + deps="$deps src/include/$dep" + elif test -f "${dir}/$dep" ; then + deps="$deps ${dir}/$dep" + else + deps="$deps src/include-local/$dep" + fi + done + if test -n "$deps" ; then + echo "${dir}/${file}:${deps}" + fi + } + done +done + +for dir in src/* ; do + for file in $(ls -1 $dir | grep -- \\.c$) ; do + { + grep -F -- "#include <${package}/" < ${dir}/$file | cut -d'<' -f2 | cut -d'>' -f1 ; + grep -- '#include ".*\.h"' < ${dir}/$file | cut -d'"' -f2 + } | sort -u | { + deps=" ${dir}/$file" + while read dep ; do + if echo $dep | grep -q "^${package}/" ; then + deps="$deps src/include/$dep" + elif test -f "${dir}/$dep" ; then + deps="$deps ${dir}/$dep" + else + deps="$deps src/include-local/$dep" + fi + done + o=$(echo $file | sed s/\\.c$/.o/) + lo=$(echo $file | sed s/\\.c$/.lo/) + echo "${dir}/${o} ${dir}/${lo}:${deps}" + } + done +done +echo + +for dir in $(ls -1 src | grep -v ^include) ; do + for file in $(ls -1 src/$dir/deps-lib) ; do + deps= + libs= + while read dep ; do + if echo $dep | grep -q -e ^-l -e '^\${.*_LIB}' ; then + libs="$libs $dep" + else + deps="$deps src/$dir/$dep" + fi + done < src/$dir/deps-lib/$file + echo 'ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)' + echo "lib${file}.a.xyzzy:$deps" + echo else + echo "lib${file}.a.xyzzy:$(echo "$deps" | sed 's/\.o/.lo/g')" + echo endif + echo "lib${file}.so.xyzzy: EXTRA_LIBS :=$libs" + echo "lib${file}.so.xyzzy:$(echo "$deps" | sed 's/\.o/.lo/g')" + done + + for file in $(ls -1 src/$dir/deps-exe) ; do + deps= + libs= + while read dep ; do + if echo $dep | grep -q -- \\.o$ ; then + dep="src/$dir/$dep" + fi + if echo $dep | grep -q -- '^\${.*_LIB}' ; then + libs="$libs $dep" + else + deps="$deps $dep" + fi + done < src/$dir/deps-exe/$file + echo "$file: EXTRA_LIBS :=$libs" + echo "$file: src/$dir/$file.o$deps" + done +done diff --git a/tools/install.sh b/tools/install.sh new file mode 100755 index 0000000..89f9428 --- /dev/null +++ b/tools/install.sh @@ -0,0 +1,64 @@ +#!/bin/sh + +usage() { + echo "usage: $0 [-D] [-l] [-m mode] src dst" 1>&2 + exit 1 +} + +mkdirp=false +symlink=false +mode=0755 + +while getopts Dlm: name ; do + case "$name" in + D) mkdirp=true ;; + l) symlink=true ;; + m) mode=$OPTARG ;; + ?) usage ;; + esac +done +shift $(($OPTIND - 1)) + +test "$#" -eq 2 || usage +src=$1 +dst=$2 +tmp="$dst.tmp.$$" + +case "$dst" in + */) echo "$0: $dst ends in /" 1>&2 ; exit 1 ;; +esac + +set -C +set -e + +if $mkdirp ; then + umask 022 + case "$2" in + */*) mkdir -p "${dst%/*}" ;; + esac +fi + +trap 'rm -f "$tmp"' EXIT INT QUIT TERM HUP + +umask 077 + +if $symlink ; then + ln -s "$src" "$tmp" +else + cat < "$1" > "$tmp" + chmod "$mode" "$tmp" +fi + +mv -f "$tmp" "$dst" +if test -d "$dst" ; then + rm -f "$dst/$(basename $tmp)" + if $symlink ; then + mkdir "$tmp" + ln -s "$src" "$tmp/$(basename $dst)" + mv -f "$tmp/$(basename $dst)" "${dst%/*}" + rmdir "$tmp" + else + echo "$0: $dst is a directory" 1>&2 + exit 1 + fi +fi -- cgit v1.2.3