pax_global_header00006660000000000000000000000064141603041400014503gustar00rootroot0000000000000052 comment=6c5457e9114af515975891e68fda6e26004be021 execline-2.8.2.0/000077500000000000000000000000001416030414000134465ustar00rootroot00000000000000execline-2.8.2.0/.gitignore000066400000000000000000000010641416030414000154370ustar00rootroot00000000000000*.o /*.a.xyzzy *.lo /*.so.xyzzy /config.mak /src/include/execline/config.h /background /backtick /case /define /dollarat /elgetopt /elgetpositionals /elglob /emptyenv /envfile /exec /execlineb /execline-cd /execline-umask /exit /export /fdblock /fdclose /fdmove /fdswap /fdreserve /forbacktickx /foreground /forstdin /forx /getcwd /getpid /heredoc /homeof /if /ifelse /ifte /ifthenelse /import /importas /loopwhilex /multidefine /multisubstitute /pipeline /piperw /posix-cd /posix-umask /redirfd /runblock /shift /trap /tryexec /umask /unexport /wait /withstdinas execline-2.8.2.0/AUTHORS000066400000000000000000000015301416030414000145150ustar00rootroot00000000000000Main author: Laurent Bercot Contributors: Jean Marot Paul Jarc Eric Le Bihan Rasmus Villemoes Colin Booth Mira Ressel Alexis Thanks to: Dan J. Bernstein David Madore Nicolas George Joël Riou Matthew R. Dempsky Lasse Kliemann Vallo Kallaste Jorge Almeida Olivier Brunel Jesse Young Danilo Spinella Éric Vidal Profpatsch execline-2.8.2.0/CONTRIBUTING000066400000000000000000000004371416030414000153040ustar00rootroot00000000000000 Please add a Signed-Off-By: line at the end of your commit, which certifies that you have the right and authority to pass it on as an open-source patch, as explicited in the Developer's Certificate of Origin available in this project's DCO file, or at https://developercertificate.org/ execline-2.8.2.0/COPYING000066400000000000000000000013701416030414000145020ustar00rootroot00000000000000Copyright (c) 2011-2021 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. execline-2.8.2.0/DCO000066400000000000000000000026151416030414000140020ustar00rootroot00000000000000Developer Certificate of Origin Version 1.1 Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 1 Letterman Drive Suite D4700 San Francisco, CA, 94129 Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. execline-2.8.2.0/INSTALL000066400000000000000000000150761416030414000145100ustar00rootroot00000000000000Build Instructions ------------------ * Requirements ------------ - A POSIX-compliant C development environment - GNU make version 3.81 or later - skalibs version 2.11.1.0 or later: https://skarnet.org/software/skalibs/ - Optional: nsss version 0.2.0.1 or later: https://skarnet.org/software/nsss/ This software will run on any operating system that implements POSIX.1-2008, available at: https://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/execline. Please note that static libraries in /usr/lib/execline *will not* be found by a default linker invocation: you need -L/usr/lib/execline. 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: https://musl-libc.org/) execline is especially efficient when statically linked, so it is recommended if you have a suitable libc. * 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. execline-2.8.2.0/Makefile000066400000000000000000000113051416030414000151060ustar00rootroot00000000000000# # 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) 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) 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 $(STATIC_LIBS) endif ifneq ($(strip $(ALL_BINS)$(SHARED_LIBS)),) exec $(STRIP) -R .note -R .comment $(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)/%) $(EXTRA_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/%) $(EXTRA_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 execline. execline-2.8.2.0/README.macos000066400000000000000000000002531416030414000154270ustar00rootroot00000000000000 This package will compile and run on Darwin (MacOS), but the building of shared libraries is not supported. Make sure you use the --disable-shared option to configure. execline-2.8.2.0/README.solaris000066400000000000000000000006531416030414000160050ustar00rootroot00000000000000 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. execline-2.8.2.0/configure000077500000000000000000000350411416030414000153600ustar00rootroot00000000000000#!/bin/sh cd `dirname "$0"` . 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 "$tmpo" "$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 "$tmpe" "$tmpc" >/dev/null 2>&1 ; then echo " ... yes" eval "$1=\"\${$1} \$2\"" eval "$1=\${$1# }" return 0 else echo " ... no" return 1 fi } # Actual script CC_AUTO= CPPFLAGS_AUTO="-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -iquote src/include-local -Isrc/include" CPPFLAGS_POST="$CPPFLAGS" CPPFLAGS= CFLAGS_AUTO="-pipe -Wall" CFLAGS_POST="$CFLAGS" CFLAGS=-O2 LDFLAGS_AUTO= LDFLAGS_POST="$LDFLAGS" LDFLAGS= LDFLAGS_NOSHARED= LDFLAGS_SHARED=-shared prefix= exec_prefix='$prefix' dynlibdir='$prefix/lib' libexecdir='$exec_prefix/libexec' bindir='$exec_prefix/bin' libdir='$prefix/lib/$package' includedir='$prefix/include' shebangdir='$bindir' shebangisdefault=true sysdeps='$prefix/lib/skalibs/sysdeps' manualsysdeps=false shared=false static=true allpic=true slashpackage=false abspath=false usensss=false pposix=false sproot= home= exthome= allstatic=true evenmorestatic=false addincpath='' addlibspath='' addlibdpath='' vpaths='' vpathd='' build= for arg ; do case "$arg" in --help) usage ;; --prefix=*) prefix=${arg#*=} ;; --exec-prefix=*) exec_prefix=${arg#*=} ;; --dynlibdir=*) dynlibdir=${arg#*=} ;; --libexecdir=*) libexecdir=${arg#*=} ;; --bindir=*) bindir=${arg#*=} ;; --libdir=*) libdir=${arg#*=} ;; --includedir=*) includedir=${arg#*=} ;; --shebangdir=*) shebangisdefault=false ; shebangdir=${arg#*=} ;; --with-sysdeps=*) sysdeps=${arg#*=} manualsysdeps=true ;; --with-include=*) var=${arg#*=} ; stripdir var ; addincpath="$addincpath -I$var" ;; --with-lib=*) var=${arg#*=} ; stripdir var ; addlibspath="$addlibspath -L$var" ; vpaths="$vpaths $var" ;; --with-dynlib=*) var=${arg#*=} ; stripdir var ; addlibdpath="$addlibdpath -L$var" ; vpathd="$vpathd $var" ;; --enable-shared|--enable-shared=yes) shared=true ;; --disable-shared|--enable-shared=no) shared=false ;; --enable-static|--enable-static=yes) static=true ;; --disable-static|--enable-static=no) static=false ;; --enable-allstatic|--enable-allstatic=yes) allstatic=true ;; --disable-allstatic|--enable-allstatic=no) allstatic=false ; evenmorestatic=false ;; --enable-static-libc|--enable-static-libc=yes) allstatic=true ; evenmorestatic=true ;; --disable-static-libc|--enable-static-libc=no) evenmorestatic=false ;; --enable-all-pic|--enable-all-pic=yes) allpic=true ;; --disable-all-pic|--enable-all-pic=no) allpic=false ;; --enable-slashpackage=*) sproot=${arg#*=} ; slashpackage=true ; ;; --enable-slashpackage) sproot= ; slashpackage=true ;; --disable-slashpackage) sproot= ; slashpackage=false ;; --enable-absolute-paths|--enable-absolute-paths=yes) abspath=true ;; --disable-absolute-paths|--enable-absolute-paths=no) abspath=false ;; --enable-nsss|--enable-nsss=yes) usensss=true ;; --disable-nsss|--enable-nsss=no) usensss=false ;; --enable-pedantic-posix|--enable-pedantic-posix=yes) pposix=true ;; --disable-pedantic-posix|--enable-pedantic-posix=no) pposix=false ;; --enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;; --enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;; --host=*|--target=*) target=${arg#*=} ;; --build=*) build=${arg#*=} ;; -* ) echo "$0: unknown option $arg" ;; *=*) eval "$arg" ;; *) target=$arg ;; esac done # Add /usr in the default default case if test -z "$prefix" ; then if test "$libdir" = '$prefix/lib/$package' ; then libdir=/usr/lib/$package fi if test "$includedir" = '$prefix/include' ; then includedir=/usr/include fi if test "$sysdeps" = '$prefix/lib/skalibs/sysdeps' ; then sysdeps=/usr/lib/skalibs/sysdeps fi fi # Expand installation directories stripdir prefix for i in exec_prefix dynlibdir libexecdir bindir libdir includedir shebangdir sysdeps sproot ; do eval tmp=\${$i} eval $i=$tmp stripdir $i done # Get usable temp filenames i=0 set -C while : ; do i=$(($i+1)) tmpc="./tmp-configure-$$-$PPID-$i.c" tmpo="./tmp-configure-$$-$PPID-$i.o" tmpe="./tmp-configure-$$-$PPID-$i.tmp" 2>|/dev/null > "$tmpc" && break 2>|/dev/null > "$tmpo" && break 2>|/dev/null > "$tmpe" && break test "$i" -gt 50 && fail "$0: cannot create temporary files" done set +C trap 'rm -f "$tmpc" "$tmpo" "$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=${DESTDIR}${sproot}/package/prog/skalibs/sysdeps fi extbinprefix=${exthome}/command dynlibdir=${home}/library.so bindir=${home}/command libdir=${home}/library libexecdir=$bindir includedir=${home}/include if $shebangisdefault ; then shebangdir=${extbinprefix} fi while read dep condvar ; do if test -n "$condvar" ; then eval "cond=$condvar" else cond=true fi if $cond ; then addincpath="$addincpath -I${DESTDIR}${sproot}${dep}/include" vpaths="$vpaths ${DESTDIR}${sproot}${dep}/library" addlibspath="$addlibspath -L${DESTDIR}${sproot}${dep}/library" vpathd="$vpathd ${DESTDIR}${sproot}${dep}/library.so" addlibdpath="$addlibdpath -L${DESTDIR}${sproot}${dep}/library.so" fi done < package/deps-build fi # Find a C compiler to use if test -n "$target" && test x${build} != x${target} ; then cross=${target}- else cross= fi echo "Checking for C compiler..." trycc ${CC} if test -n "$CC_AUTO" ; then b=`basename "$CC"` adjust_cross=false if test "$b" != "$CC" ; then adjust_cross=true echo "$0: warning: compiler $CC is declared with its own path. If it's not accessible via PATH, you will need to pass AR, RANLIB and STRIP make variables to the make invocation." 1>&2 fi if test -n "$cross" ; then if test "$b" = "${b##$cross}" ; then echo "$0: warning: compiler $CC is declared as a cross-compiler for target $target but does not start with prefix ${cross}" 1>&2 elif $adjust_cross ; then cross=`dirname "$CC"`/"$cross" fi fi fi trycc ${cross}gcc trycc ${cross}clang trycc ${cross}cc test -n "$CC_AUTO" || { echo "$0: cannot find a C compiler" ; exit 1 ; } echo " ... $CC_AUTO" echo "Checking whether C compiler works... " echo "typedef int x;" > "$tmpc" if $CC_AUTO $CPPFLAGS_AUTO $CPPFLAGS $CPPFLAGS_POST $CFLAGS_AUTO $CFLAGS $CFLAGS_POST -c -o "$tmpo" "$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 $allpic ; then tryflag CPPFLAGS_AUTO -fPIC fi spawn_lib=$(cat $sysdeps/spawn.lib) socket_lib=$(cat $sysdeps/socket.lib) sysclock_lib=$(cat $sysdeps/sysclock.lib) timer_lib=$(cat $sysdeps/timer.lib) util_lib=$(cat $sysdeps/util.lib) 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 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 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 if $allstatic ; then LDFLAGS_NOSHARED="${LDFLAGS_NOSHARED}${addlibspath}" tryldflag LDFLAGS_NOSHARED -Wl,--gc-sections else LDFLAGS_NOSHARED="${LDFLAGS_NOSHARED}${addlibdpath}" fi echo "Creating config.mak..." cmdline=$(quote "$0") for i ; do cmdline="$cmdline $(quote "$i")" ; done exec 3>&1 1>config.mak cat << EOF # This file was generated by: # $cmdline # Any changes made here will be lost if configure is re-run. target := $target package := $package prefix := $prefix exec_prefix := $exec_prefix dynlibdir := $dynlibdir libexecdir := $libexecdir bindir := $bindir libdir := $libdir includedir := $includedir sysdeps := $sysdeps slashpackage := $slashpackage sproot := $sproot version := $version home := $home exthome := $exthome SPAWN_LIB := ${spawn_lib} SOCKET_LIB := ${socket_lib} SYSCLOCK_LIB := ${sysclock_lib} TIMER_LIB := ${timer_lib} UTIL_LIB := ${util_lib} CC := $CC_AUTO CPPFLAGS_AUTO := $CPPFLAGS_AUTO CPPFLAGS := $CPPFLAGS $CPPFLAGS_POST CFLAGS_AUTO := $CFLAGS_AUTO CFLAGS := $CFLAGS $CFLAGS_POST LDFLAGS_AUTO := $LDFLAGS_AUTO LDFLAGS := $LDFLAGS $LDFLAGS_POST LDFLAGS_SHARED := $LDFLAGS_SHARED LDFLAGS_NOSHARED := $LDFLAGS_NOSHARED CROSS_COMPILE := $cross vpath lib%.a$vpaths vpath lib%.so$vpathd EOF if $allstatic ; then echo ".LIBPATTERNS := lib%.a" echo "DO_ALLSTATIC := 1" else echo ".LIBPATTERNS := lib%.so" fi if $static ; then echo "DO_STATIC := 1" else echo "DO_STATIC :=" fi if $shared ; then echo "DO_SHARED := 1" else echo "DO_SHARED :=" fi if $allpic ; then echo "STATIC_LIBS_ARE_PIC := 1" else echo "STATIC_LIBS_ARE_PIC :=" fi if $usensss ; then echo "LIBNSSS := -lnsss" echo "MAYBEPTHREAD_LIB := -lpthread" else echo "LIBNSSS :=" echo "MAYBEPTHREAD_LIB :=" fi if $pposix ; then echo "PEDANTIC_POSIX := 1" else echo "PEDANTIC_POSIX :=" 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." execline-2.8.2.0/doc/000077500000000000000000000000001416030414000142135ustar00rootroot00000000000000execline-2.8.2.0/doc/background.html000066400000000000000000000032101416030414000172140ustar00rootroot00000000000000 execline: the background command

execline
Software
skarnet.org

The background program

background launches a command in the background, then goes on with the execution flow.

Interface

In an execlineb script:

     background [ -d ] { prog1... } prog2...
  • background reads a prog1... command in a block and unquotes it.
  • It spawns a child executing prog1....
  • It sets the ! environment variable to the pid of the prog1... process.
  • It then execs into prog2....

Options

  • -d : doublefork. If the -d option is set, prog1... will run as a grandchild of background.

Notes

  • background prog1... "" prog2... is equivalent to sh -c 'prog1... & ; exec prog2...'.
execline-2.8.2.0/doc/backtick.html000066400000000000000000000057171416030414000166660ustar00rootroot00000000000000 execline: the backtick command

execline
Software
skarnet.org

The backtick program

backtick runs a program and stores its output in an environment variable, then executes another program.

Interface

In an execlineb script:

     backtick [ -i | -I | -x | -D default ] [ -N | -n ] [ -E | -e ] variable { prog1... } prog2...
  • backtick reads prog1... in a block and unquotes it.
  • It runs prog1... as a child process and saves its output in memory. This output must not contain a null character.
  • backtick execs into prog2..., with variable added to the environment with prog1...'s output as a value.

Options

  • -N : store prog1...'s output as is, including the last newline, if any.
  • -n : chomp an ending newline off prog1...'s output. This is the default.
  • -e : no autoimport. This is the default.
  • -E : autoimport. Instead of exec'ing into prog2..., exec into importas -ui variable variable prog2.... This substitutes variable into the command line instead of putting it into the environment.

The other options tell backtick what to do if prog1...'s output is not suitable as the contents of an environment variable (i.e. it contains a null character) or if prog1... crashes or exits nonzero:

  • -i : backtick exits with an approximation of prog1's exit code, or 124 if prog1 wrote a null character. This is the default.
  • -I: the value of variable is set to whatever the start of prog1...'s output is, up to the first null character, or to whatever prog1... wrote before crashing; chomping is applied if required; then execution proceeds.
  • -x : variable is removed from the environment, and execution proceeds.
  • -D default : the value of variable is set to default, and execution proceeds.
execline-2.8.2.0/doc/case.html000066400000000000000000000146701416030414000160240ustar00rootroot00000000000000 execline: the case command

execline
Software
skarnet.org

The case program

case compares a value against a series of regular expressions, and executes into a program depending on the first expression the value matches.

Interface

In an execlineb script:

     case [ -S | -s ] [ -E | -e ] [ -i ] [ -n | -N ] value
     {
       [ regex { prog... } ]
       [ regex { prog... } ]
       ...
     }
     progdefault...
  • case reads an argument value and a sequence of directives in a block.
  • Each directive is a regular expression followed by a block.
  • case matches value against the regular expressions in the order they are given.
  • As soon as value matches a regex, case executes into the prog... command line that immediately follows the matched regex.
  • If value matches no regex, case eventually execs into progdefault..., or exits 0 if progdefault... is empty.

Options

  • -s : Shell matching. The regex words will not be interpreted as regular expressions, but as shell expressions to be interpreted via fnmatch(). The other options also change meanings, see the Shell matching section below.
  • -S : Regular expression matching. This is the default. This section, and all of the sections below except the Shell matching one, assumes that it is the case.
  • -e : Interpret the regex words as basic regular expressions.
  • -E : Interpret the regex words as extended regular expressions. This is the default.
  • -i : Perform case-insensitive matches.
  • -N : Make the matching expression and subexpressions available to prog's environment. See the "Subexpression matching" section below.
  • -n : Do not transmit the matching expression and subexpressions to prog... via the environment. This is the default.

Subexpression matching

If the -N option has been given, and value matches a regex, then case will run prog with a modified environment:

  • The 0 variable will contain the regex that value matched.
  • The # variable will contain the number of subexpressions in regex.
  • For every integer i between 1 and the number of subexpressions (included), the variable i contains the part of value that matched the ith subexpression in regex.

To retrieve that information into your command line in an execline script, you can use the elgetpositionals program.

An example

Consider the following script; say it's named match.

#!/bin/execlineb -S1
emptyenv
case -N -- $1
{
  "([fo]+)bar(baz)" { /usr/bin/env }
}

Running match foooobarbaz will print the following lines, corresponding to the output of the /usr/bin/env command:

#=2
0=([fo]+)bar(baz)
1=foooo
2=baz

Shell matching

If the -s option has been given to case, then the regex words are not interpreted as regular expressions, but as shell patterns, as is performed by the shell's case conditional construct. This has the following consequences:

  • Subexpression matching is always disabled.
  • prog... is always executed with an unmodified environment.
  • The options to the case command change meanings: instead of controlling how the regex regular expressions are interpreted by the regcomp() primitive, they now control how value is matched against the regex patterns (which are not regular expressions!) via the fnmatch() primitive. Namely:
    • -e : Treat a backslash as an ordinary character; do not allow character escaping in patterns. (This sets the FNM_NOESCAPE flag.)
    • -E : Allow backslash escaping in patterns. This is the default. (This clears the FNM_NOESCAPE flag.)
    • -i : Treat a period (.) as a special character for matching (set FNM_PERIOD). By default, the period is not a special character (FNM_PERIOD is cleared).
    • -N : Treat patterns as pathnames: make slashes character special. (This sets the FNM_PATHNAME flag.)
    • -n : Do not treat patterns as pathnames (clear the FNM_PATHNAME flag). This is the default.

Notes

  • value must match regex as a full word. If only a substring of value matches regex, it is not considered a match.
  • If value matches no regex, progdefault... is always executed with an unmodified environment, whether subexpression matching has been requested or not.
execline-2.8.2.0/doc/componentsb.txt000066400000000000000000000031441416030414000173050ustar00rootroot00000000000000#!/command/execlineb -P # This execlineb script will sleep for 1 second, then print some # silly things on the standard output. foreground # an unquoted string, evaluated to: foreground { # A single opening brace, not included in the argv sleep 1 # Two unquoted strings, evaluated to " sleep" and " 1" # (without the quotation marks). } # A single closing brace, evaluated to the empty word "echo" # this is a quoted string. It will evaluate to the word: echo foo\ bar\ zoinx # This is one word, since the spaces are escaped "foo bar zoinx" # This is exactly the same word, written another way " # this is not a comment, since it is inside a quoted string # This is not a comment either \" # nor is this " # but this is one "\0x41\66\0103D\n" # This is the string ABCD followed by a newline. # Be careful: the newline will be part of the word. \n # this is not a newline, but the single word: n $23 # This will NOT be replaced by anything with execline-1.y, unless # substitution is explicitly asked for in the script. # The dollar is no special character for the execline binary. baz"$1"qux # This will evaluate to the word baz$1qux baz\$1qux # Same here baz$1qux # Same here in execline-1.y ${PATH} # This will NOT be replaced by execline ; use the importas command # if you need the $PATH value. 'this is not a string' # it will be parsed as five separate words "\ " # This will be parsed as the empty word. A (backslash, newline) # sequence inside a quoted string is entirely removed. execline-2.8.2.0/doc/define.html000066400000000000000000000024221416030414000163330ustar00rootroot00000000000000 execline: the define command

execline
Software
skarnet.org

The define program

define replaces a literal with a value, then executes another program.

Interface

     define [ -s ] [ -C | -c ] [ -N | -n ] [ -d delim ] variable value prog...
execline-2.8.2.0/doc/dieshdiedie.html000066400000000000000000000312151416030414000173430ustar00rootroot00000000000000 execline: why execline and not sh

execline
Software
skarnet.org

Why not just use /bin/sh?

Security

One of the most frequent sources of security problems in programs is parsing. Parsing is a complex operation, and it is easy to make mistakes while designing and implementing a parser. (See what Dan Bernstein says on the subject, section 5.)

But shells parse all the time. Worse, the essence of the shell is parsing: the parser and the runner are intimately interleaved and cannot be clearly separated, thanks to the specification. The shell performs several kinds of expansions, automatic filename globbing, and automatic word splitting, in an unintuitive order, requiring users to memorize numerous arbitrary quoting rules in order to achieve what they want. Pages abound where common mistakes are listed, more often than not leading to security holes. Did you know that "$@" is a special case of double quoting, because it will split the arguments into several words, whereas every other use of double quotes in a shell is meant to prevent splitting?

execlineb parses the script only once: when reading it. The parser has been designed to be simple and systematic, to reduce the potential for bugs - which you just cannot do with a shell. After execlineb has split up the script into words, no other parsing phase will happen, unless the user explicitly requires it. Positional parameters, when used, are never split, even if they contain spaces or newlines, unless the user explicitly requires it. Users control exactly what is split, what is done, and how.

Portability

The shell language was designed to make scripts portable across various versions of Unix. But it is actually really hard to write a portable shell script. There are dozens of distinct sh flavours, not even counting the openly incompatible csh approach and its various tcsh-like followers. The ash, bash, ksh and zsh shells all exhibit a different behaviour, even when they are run with the so-called compatibility mode. From what I have seen on various experiments, only zsh is able to follow the specification to the letter, at the expense of being big and complex to configure. This is a source of endless problems for shell script writers, who should be able to assume that a script will run everywhere, but cannot in practice. Even a simple utility like test cannot be used safely with the normalized options, because most shells come with a builtin test that does not respect the specification to the letter. And let's not get started about echo, which has its own set of problems. Rich Felker has a page listing tricks to use to write portable shell scripts. Writing a portable script should not be that hard.

execline scripts are portable. There is no complex syntax with opportunity to have an undefined or nonportable behaviour. The execline package is portable across platforms: there is no reason for vendors or distributors to fork their own incompatible version. Scripts will not break from one machine to another; if they do, it's not a "portability problem", it's a bug. You are then encouraged to find the program that is responsible for the different behaviour, and send a bug-report to the program author - including me, if the relevant program is part of the execline distribution.

A long-standing problem with Unix scripts is the shebang line, which requires an absolute path to the interpreter. Scripts are only portable as is if the interpreter can be found at the same absolute path on every system. With /bin/sh, it is almost the case (Solaris manages to get it wrong by having a non-POSIX shell as /bin/sh and requiring something like #!/usr/xpg4/bin/sh to get a POSIX shell to interpret your script). Other scripting languages are not so lucky: perl can be /bin/perl, /usr/bin/perl, /usr/local/bin/perl or something else entirely. For those cases, some people advocate the use of env: #!/usr/bin/env perl. But first, env can only find interpreters that can be found via the user's PATH environment variable, which defeats the purpose of having an absolute path in the shebang line in the first place; and second, this only displaces the problem: the env utility does not have a guaranteed absolute path. /usr/bin/env is the usual convention, but not a strong guarantee: it is valid for systems to have /bin/env instead, for instance.

execline suffers from the same issues. #!/bin/execlineb ? #!/usr/bin/execlineb ? This is the only portability problem that you will find with execline, and it is common to every script language.

The real solution to this portability problem is a convention that guarantees fixed absolute paths for executables, which the FHS does not do. The slashpackage convention is such an initiative, and is well-designed; but as with every convention, it only works if everyone follows it, and unfortunately, slashpackage has not found many followers. Nevertheless, like every skarnet.org package, execline can be configured to follow the slashpackage convention.

Simplicity

I originally wanted a shell that could be used on an embedded system. Even the ash shell seemed big, so I thought of writing my own. Hence I had a look at the sh specification... and ran away screaming. This specification is insane. It goes against every good programming practice; it seems to have been designed only to give headaches to wannabe sh implementors.

POSIX cannot really be blamed for that: it only normalizes existing, historical behaviour. One can argue whether it is a good idea to normalize atrocious behaviour for historical reasons, as is the case with the infamous gets function, but this is the way it is.

The fact remains that modern shells have to be compatible with that historical nonsense and that makes them big and complex at best, or incompatible and ridden with bugs at worst. An OpenBSD developer said to me, when asked about the OpenBSD /bin/sh: "It works, but it's far from not being a nightmare".

Nobody should have nightmare-like software on their system. Unix is simple. Unix was designed to be simple. And if, as Dennis Ritchie said, "it takes a genius to understand the simplicity", that's because incompetent people took advantage of the huge Unix flexibility to write insanely crappy or complex software. System administrators can only do a decent job when they understand how the programs they run are supposed to work. People are slowly starting to grasp this (or are they? We finally managed to get rid of sendmail and BIND, but GNU/Linux users seem happy to welcome the era of D-Bus and systemd. Will we ever learn?) - but even sh, a seemingly simple and basic Unix program, is hard to understand when you lift the cover.

So I decided to forego sh entirely and take a new approach. So far it has been working. The execline specification is simple, and, as I hope to have shown, easy to implement without too many bugs or glitches.

Performance

Since it was made to run on an embedded system, execline was designed to be light in memory usage. And it is.

  • No overhead due to interactive support.
  • No overhead due to unneeded features. Since every command performs its task then executes another command, all occupied resources are instantly freed. By contrast, a shell stays in memory during the whole execution time.
  • Very limited use of the C library. Only the C interface to the kernel's system calls, and some very basic functions like malloc(), are used in the C library. In addition to avoiding the horrible interfaces like stdio and the legacy libc bugs, this approach makes it easy to statically compile execline - you will want to do that on an embedded system, or just to gain performance.

You can have hundreds of execline scripts running simultaneously on an embedded box. Not exactly possible with a shell.

For scripts that do not require many computations that a shell can do without calling external programs, execline is faster than the shell. Unlike sh's one, the execline parser is simple and straightforward; actually, it's more of a lexer than a parser, because the execline language has been designed to be LL(1) - keep it simple, stupid. execline scripts get analysed and launched practically without a delay.

  • The best use case of execline is a linear, straightforward script, a simple command line that does not require the shell's processing power. In that case, execline will skip the shell's overhead and win big time on resource usage and execution speed.
  • For longer scripts that fork a few commands, with a bit of control flow, on average, an execline script will run at roughly the same speed as the equivalent shell script, while using less resources.
  • The worst use case of execline is when the shell is used as a programming language, and the script loops over complex internal constructs that execline is unable to replicate without forking. In that case, execline will waste a lot of time in fork/exec system calls that the shell does not have to perform, and be noticeably slower. execline has been designed as a scripting language, not as a programming language: it is efficient at being the glue that ties together programs doing a job, not at implementing a program's logic.

execline limitations

  • execline can only handle scripts that fit in one argv. Unix systems have a limit on the argv+envp size; execline cannot execute scripts that are bigger than this limit.
  • execline commands do not perform signal handling. It is not possible to trap signals efficiently inside an execline script. The trap binary, part of the execline suite, provides a signal management primitive, but it is more limited and slower than its equivalent shell construct.
  • Due to the execline design, maintaining a state is difficult. Information has to transit via environment variables or temporary files, which makes commands like loopwhilex a bit painful to handle.
  • Despite all its problems, the main shell advantage (apart from being available on every Unix platform, that is) is that it is often convenient. Shell constructs can be terse and short, where execline constructs will be verbose and lengthy.
  • An execline script is generally heavier on execve() than the average shell script - notably in programs where the shell can use builtins. This can lead to a performance loss, especially when executed programs make numerous calls to the dynamic linker: the system ends up spending a lot of time resolving dynamic symbols. If it is a concern to you, you should try and statically compile the execline package, to eliminate the dynamic resolution costs. Unless you're heavily looping around execve(), the remaining costs will be negligible.
execline-2.8.2.0/doc/dollarat.html000066400000000000000000000057301416030414000167100ustar00rootroot00000000000000 execline: the dollarat command

execline
Software
skarnet.org

The dollarat program

dollarat prints the positional parameters of an execline script.

Interface

     dollarat [ -n ] [ -0 | -d delimchar ]
  • dollarat reads the number n of "positional parameters" in the # environment variable. If that variable is not set or does not contain a valid n, dollarat exits 100.
  • dollarat prints the value of the 1 environment variable, then delimchar, then the value of the 2 environment variable... and so on until n. If one of these variables is not set, dollarat exits 100.
  • If everything runs OK, dollarat exits 0. This makes it one of the rare "exiting" execline commands.

Options

  • -n : chomp. Do not print the last delimchar.
  • -d delimchar : use the character delimchar as separator between the arguments. Default: \n. If delimchar has more than one character, only the first one is used. If delimchar is the empty string, then dollarat will output the positional parameters as a sequence of netstrings (and the -n option will be ignored).
  • -0 : use the null character as separator. If this option and the -d option are given concurrently, the rightmost one wins. Warning: -0 should only be used to feed data to programs that know how to handle null-separated lists.

Notes

  • You can use dollarat -d "" along with the forbacktickx command to reliably loop over the positional parameters:
     #!/command/execlineb
     forbacktickx -d "" ARG { dollarat -d "" }
     dosomething $ARG
    
    will call dosomething in turn on each argument to the script. That will work even if those arguments contain spaces, newlines, or other fancy characters.
  • Alternatively, instead of encoding data into a netstring, you can use a null-separated list, which will work the same way:
     #!/command/execlineb
     forbacktickx -0 ARG { dollarat -0 }
     dosomething $ARG
    
execline-2.8.2.0/doc/el_pushenv.html000066400000000000000000000121101416030414000172440ustar00rootroot00000000000000 execline: pushing and popping the environment

execline
Software
skarnet.org

Pushing and popping the environment

The execlineb launcher can store positional parameters, i.e. arguments given to your script, into the environment. The # variable contains the number of arguments; the 0 variable contains the name of your execline script; the 1 variable contains the first argument; and so on.

Up to execline-1.04, this could create problems with nested scripts: the inner script would overwrite the outer script's parameters, and there was no way to get them back. In particular, writing execline commands in the execline language via the runblock command was impossible.

To solve that issue, execline now implements a kind of environment stack. When execlineb reads the arguments, it does not overwrite the positional parameters, but pushes them on a stack:

  • # will be set to the current number of arguments
  • but if a variable named # existed before, it is renamed #:1
  • and if a variable named #:1 also existed, it is renamed #:2
  • ... and so on until #:n+1 doesn't exist.

Same goes for the other positional parameters.

The script then runs; and commands such as elgetpositionals use the current frame of positional parameters, without paying attention to the deeper levels.

When you are done with the arguments, it is advisable to drop the current frame, and pop the environment stack to get it back to its previous state:

  • # will be unset
  • but if #:1 exists, it will be renamed #
  • and if #:2 exists, it will be renamed #:1
  • ... and so on until #:n+1 doesn't exist.

Again, same goes for the other positional parameters.
The
runblock command will perform that pop operation automatically; the standard "manual" way to perform it is to use the emptyenv -P command.

A pop example

Suppose you want to run the long-lived program prog after printing the list of its arguments.

 #!/command/execlineb
 elgetpositionals
 foreground { echo $0 $@ }
 prog $@

will work, but will pollute prog's environment with a set of positional parameters that have no meaning to it. A better script is:

 #!/command/execlineb
 elgetpositionals
 foreground { echo $0 $@ }
 emptyenv -P
 prog $@

which will run prog with the same environment as the script's caller.

Substituting positional parameters without touching the environment

Most of the time, you just need to substitute the positional parameters in your execline script, and don't need to go through the whole elgetpositionals and emptyenv chain. execline comes with an integrated substitution mechanism, that does not touch the environment at all: the -S n option.

Scripts beginning with:

#!/command/execlineb -Sn
foobar...

are equivalent to:

#!/command/execlineb
elgetpositionals -Pn
emptyenv -P
foobar...

So, to summarize, from most efficient (but less flexible) to least efficient (but more flexible):

  • Use execlineb -P if you don't need positional parameters at all; for instance, in s6 or runit run scripts.
  • Use execlineb -Sn if you need only simple positional parameter substitution in your script - no shift or elgetopt, no importas 1 1.
  • Use execlineb -p, then elgetpositionals if you don't mind overwriting the current stack of positional parameters.
  • Use execlineb, then elgetpositionals, then emptyenv -P if you need the full power of positional parameter handling.
execline-2.8.2.0/doc/el_semicolon.html000066400000000000000000000074031416030414000175550ustar00rootroot00000000000000 execline: block management

execline
Software
skarnet.org

Blocks

A command line (and thus an execline script) is one-dimensional. But a Unix execution flow can be two-dimensional: when two instructions are sequenced, for instance. In that case, we need a way to extract two command lines from one argv. That is precisely what blocks are made for.

execline commands that need more than one linear set of arguments use blocks. For instance, the foreground command needs to spawn a first process, then execute into a second one. It reads the command line for the first process from a block, and the command line for the second process from the rest of the argv. In the following script:

 #!/command/execlineb
 foreground { echo 1 } echo 2

echo 1 is read from a block and spawned; then echo 2 is executed.

execlineb syntax

In execlineb scripts, blocks are delimited by braces. They can be nested.

argv syntax

execlineb reads and parses the script, and converts it into an argv (a simple Unix command line) with a different syntax for blocks. In an argv, blocks are not delimited by braces; they are made of quoted arguments and terminated by an empty word (""). A quoted argument begins with a space. Nested blocks are represented by arguments being quoted several times, i.e. having several spaces in front of them; an empty word inside a block gets quoted too, i.e. it will be represented as a series of spaces.

Actually, the block-reading commands know nothing about braces; they only understand the "quoted arguments + empty word" syntax. So if you want to use foreground from your shell to sequence echo 1 and echo 2, you will have to write

 $ foreground ' echo' ' 1' '' echo 2

You do not really need to quote every argument inside a block in that simple case. The following command works as well:

 $ foreground echo 1 '' echo 2

However, this is bad practice, because it leads to a security hole: commands that perform substitution inside a block may produce empty words, which may modify your script's execution flow.

 $ define FOO '' foreground ' echo' ' ${FOO}' ' rm' ' -rf' ' /' '' echo blah

is safe, whereas

 $ define FOO '' foreground echo '${FOO}' rm -rf / '' echo blah

has very much unwanted results. (Don't try this at home.)

You can use the EXECLINE_STRICT environment variable to check proper block quoting. If that variable contains 1, commands that read blocks will print a warning message every time they find an unquoted argument inside a block. If that variable contains 2 or a bigger integer, commands will print an error message and die on unquoted arguments.
You can use execlineb's -w or -W switch to set EXECLINE_STRICT to 1 or 2.

execline-2.8.2.0/doc/el_substitute.html000066400000000000000000000227041416030414000200010ustar00rootroot00000000000000 execline: variable substitution

execline
Software
skarnet.org

Variable substitution

In a shell, when you write

 $ A='foobar' ; echo $A

the echo command is given the argument foobar. The foobar value has been substituted for the A variable.

Although execline maintains no state, and thus has no real variables, it provides such a substitution facility via substitution commands, namely:

A substitution command takes a key, i.e. a string (which can contain any character but $, { and }, although it is recommended to use only alphanumerical characters), and a way to compute a value.

Basics

  • If the substitution key is foo, then the substitution command will look for every occurrence of ${foo} or $foo in the rest of its argv. Note that ${foo}bar matches, but $foobar does not. To be safe, always use the syntax with braces, unless $foo is a word on its own.
  • Every match is then replaced with the value.

The simplest example is the following:

#!/command/execlineb
define FOO blah
echo $FOO

which will replace the FOO key with the blah value, then execute the echo command. So that script will print blah on stdout.

Quoting

execline allows you to write literal ${foo} constructs even when the foo variable is being substituted, thanks to a quoting mechanism. Brace (pun intended) yourself: the following is the most complex part of the whole language.

Rationale

If we want to be able to have a literal ${foo}, then:

  • The ${foo} sequence will mean one of two things: be substituted, or don't be substituted.
  • The default (unquoted) action should be: substitute.
  • A sequence that means "do not substitute" should be able to appear literally. The quote character should also be able to appear literally before a sequence that means "substitute". (Tricky, eh?)
  • There should be as few quote characters as possible, to avoid shell-like quoting nightmares.

Syntax

Rule:

  • The backslash (\) is a quote character for substitution commands.
  • The following rule applies only if the foo key is explicitly used in a substitution command. If no command tries to substitute anything for foo, sequences like ${foo} and preceding backslashes are left untouched.
  • (Substitute.) If ${foo} is preceded by 2*n backslashes (an even number), the whole sequence will be replaced with n backslashes, followed by the substituted value.
  • (Do not substitute.) If ${foo} is preceded by 2*n+1 backslashes (an odd number), the whole sequence will be replaced with n backslashes, followed by the literal ${foo}.

And now, the catch: the execlineb launcher, as well as the shell, interprets backslashes as escape characters. To make a word that contains a backlash, you need to write two backslashes in your execline script or shell command line. That means that the whole number of backslashes you must write before your ${foo} sequence must be doubled for the substitution command to read the proper number of backslashes and perform its work correctly.
Once you keep that in mind, the quoting rule is logical.

Example

The quoting rule is best illustrated with the following example, where the A key is substituted, and the $B sequences mean nothing special.

#!/command/execlineb
define A val
foreground { echo $A \\$A \\\\$A \\\\\\$A \\\\\\\\$A \\\\\\\\\\$A }
             echo $B \\$B \\\\$B \\\\\\$B \\\\\\\\$B \\\\\\\\\\$B

prints

val $A \val \$A \\val \\$A
$B \$B \\$B \\\$B \\\\$B \\\\\$B

Phew.

Value transformations

A value can go through several transformations before it is substituted. It can be crunched, chomped, and/or split.

Substitution of split values

A split value for FOO means that a word containing ${FOO} will be replaced by zero, one, or (usually) more than one word. The value actually means a list of values.

The rule is: substituting a list of values (v1, v2, ...) for a key A is the same as listing the substitutions of every value vi for A.
For instance,

#!/command/execlineb
define -s FOO "v1 v2 v3" echo prefix-${FOO}-postfix

will substitute three values for $FOO: v1, v2 and v3. So the echo command will be called with three arguments: prefix-v1-postfix, prefix-v2-postfix, and prefix-v3-postfix.

(Implementation note: the fact that word prefixes are kept is what makes execline's subtitutions secure. Blocks are implemented via prefix space characters; a substitution occurring inside a block will always produce words beginning with the right amount of spaces, thus substituted values cannot prematurely terminate a block.)

Recursive substitutions

A direct consequence of that rule is that substitutions will be performed recursively if more than one key appears in one word and the values for those keys are split. Parallel substitutions are performed from left to right. For instance, in

#!/command/execlineb
define -s B "1 2 3" echo ${B}x${B}

the ${B}x${B} word will be replaced with nine words: 1x1, 1x2, 1x3, 2x1, 2x2, 2x3, 3x1, 3x2, and 3x3, in that order.
Here is an example with two distinct substitutions in parallel:

#!/command/execlineb
multisubstitute
{
  define -s A "a b c d"
  define -s B "1 2 3"
}
echo ${A}x${B}

The ${A}x${B} word will be replaced with twelve words: ax1, ax2, ax3, bx1, bx2, bx3, cx1, cx2, cx3, dx1, dx2, and dx3, in that order. You can check that the order of the define directives in multisubstitute does not matter.

If the left-to-right order does not suit you, then you should perform serial substitutions. For instance, the previous script can be replaced with

#!/command/execlineb
define -s B "1 2 3"
define -s A "a b c d"
echo ${A}x${B}

and will substitute ${B} first, then ${A}. So it will print

ax1 bx1 cx1 dx1 ax2 bx2 cx2 dx2 ax3 bx3 cx3 dx3

in that order.

Not for the faint of heart

If you think you have mastered the art of execline substitution, then you can try to do better than these people:

execline-2.8.2.0/doc/el_transform.html000066400000000000000000000153401416030414000175770ustar00rootroot00000000000000 execline: value transformation

execline
Software
skarnet.org

Value transformation

You can apply 3 kinds of transformations to a value which is to be substituted for a variable: crunching, chomping and splitting. They always occur in that order.

Delimiters

The transformations work around delimiters. Delimiters are the semantic bounds of the "words" in your value. You can use any character (except the null character, which you cannot use in execline scripts) as a delimiter, by giving a string consisting of all the delimiters you want as the argument to the -d option used by substitution commands. By default, the string " \n\r\t" is used, which means that the default delimiters are spaces, newlines, carriage returns and tabs.

(The forstdin command is a small exception: by default, it only recognizes newlines as delimiters.)

Crunching

You can tell the substitution command to merge sets of consecutive delimiters into a single delimiter. For instance, to replace three consecutive spaces, or a space and 4 tab characters, with a single space. This is called crunching, and it is done by giving the -C switch to the substitution command. The remaining delimiter will always be the first in the sequence. Chomping is off by default, or if you give the -c switch.

Crunching is mainly useful when also splitting.

Chomping

Sometimes you don't want the last delimiter in a value. Chomping deletes the last character of a value if it is a delimiter. It is requested by giving the -n switch to the substitution command. You can turn it off by giving the -N switch. It is off by default unless mentioned in the documentation page of specific binaries. Note that chomping always happens after crunching, which means you can use crunching+chomping to ignore, for instance, a set of trailing spaces.

Splitting

In a shell, when you write

 $ A='foo bar' ; echo $A

the echo command is given two arguments, foo and bar. The $A value has been split, and the space between foo and bar acted as a delimiter.

If you want to avoid splitting, you must write something like

 $ A='foo bar' ; echo "$A"

The doublequotes "protect" the spaces. Unfortunately, it's easy to forget them and perform unwanted splits during script execution - countless bugs happen because of the shell's splitting behaviour.

execline provides a splitting facility, with several advantages over the shell's:

  • Splitting is off by default, which means that substitutions are performed as is, without interpreting the characters in the value. In execline, splitting has to be explicitly requested by specifying the -s option to commands that perform substitution.
  • Positional parameters are never split, so that execline scripts can handle arguments the way the user intended to. To split $1, for instance, you have to ask for it specifically:
    #!/command/execlineb -S1
    define -sd" " ARG1S $1
    blah $ARG1S
    
    and $ARG1S will be split using the space character as only delimiter.
  • Any character can be a delimiter.

How it works

  • A substitution command can request that the substitution value be split, via the -s switch.
  • The splitting function parses the value, looking for delimiters. It fills up a structure, marking the split points, and the number n of words the value is to be split into.
    • A word is a sequence of characters in the value terminated by a delimiter. The delimiter is not included in the word.
    • If the value begins with x delimiters, the word list will begin with x empty words.
    • The last sequence of characters in the value will be recognized as a word even if it is not terminated by a delimiter, unless you have requested chomping and there was no delimiter at the end of the value before the chomp operation - in which case that last sequence will not appear at all.
  • The substitution rewrites the argv. A non-split value will be written as one word in the argv; a split value will be written as n separate words.
  • Substitution of split values is performed recursively.

Decoding netstrings

Netstrings are a way to reliably encode strings containing arbitrary characters. execline takes advantage of this to offer a completely safe splitting mechanism. If a substitution command is given an empty delimiter string (by use of the -d "" option), the splitting function will try to interpret the value as a sequence of netstrings, every netstring representing a word. For instance, in the following command line:

 $ define -s -d "" A '1:a,2:bb,0:,7:xyz 123,1: ,' echo '$A'

the echo command will be given five arguments:

  • the "a" string
  • the "bb" string
  • the empty string
  • the "xyz 123" string
  • the " " string (a single space)

However, if the value is not a valid sequence of netstrings, the substitution command will die with an error message.

The dollarat command, for instance, can produce a sequence of netstrings (encoding all the arguments given to an execline script), meant to be decoded by a substitution command with the -d "" option.

execline-2.8.2.0/doc/elgetopt.html000066400000000000000000000041071416030414000167260ustar00rootroot00000000000000 execline: the elgetopt command

execline
Software
skarnet.org

The elgetopt program

elgetopt performs getopt-style parsing on the arguments to an execline script.

Interface

     elgetopt optstring prog...
  • elgetopt expects to find a valid number n of arguments in the # environment variable, and n+1 environment variables 0, 1, ..., n. It exits 100 if it is not the case.
  • elgetopt pushes environment variables starting with ELGETOPT_. To get the previous values back, use emptyenv -o.
  • elgetopt looks into 1, 2... for options, as specified by optstring, which is a standard getopt string.
  • If the -c switch is recognized, elgetopt sets the ELGETOPT_c environment variable. The value of that variable is the argument to the -c switch if it has one, and 1 otherwise.
  • After setting all recognized options, elgetopt makes new #, 1, 2... "positional parameters" with what remains.
  • elgetopt then execs into prog....

Notes

  • GNU-style options are not supported.
execline-2.8.2.0/doc/elgetpositionals.html000066400000000000000000000065241416030414000204750ustar00rootroot00000000000000 execline: the elgetpositionals command

execline
Software
skarnet.org

The elgetpositionals program

elgetpositionals substitutes the positional parameters of an execline script.

Interface

     elgetpositionals [ -P sharp ] prog...
  • elgetpositionals reads the number n of "positional parameters" in the # environment variable. If that variable is not set or does not contain a valid n, elgetpositionals exits 100.
  • elgetpositionals performs some substitutions in parallel on prog...:
    • key: #, value: n
    • key: 0, value: the value of the 0 environment variable
    • key: 1, value: the value of the 1 environment variable
    • ... and so on until n (or sharp if it is greater than n). Those values are never transformed.
    • key: @, value: all values of the variables from 1 to n. This value is split into n words.
    If a variable between 0 and n does not exist, elgetpositionals exits 100.

Options

  • -P sharp : substitute at least sharp+1 positional parameters, from 0 to max(n, sharp). If n<sharp, positional parameters between n+1 and sharp are replaced with the empty string. Not having the -P switch is equivalent to having -P 0.

Notes

  • A typical argument-taking execline script will often begin this way:
     #!/command/execlineb
     elgetopt optstring
     elgetpositionals
     prog...
    
  • If you are performing other substitutions that do not depend on the positional parameters, think about replacing the elgetpositionals call with a multisubstitute call containing the elgetpositionals directive.
  • If you are going to use the shift command, it is best to use importas to substitute the first positional parameters, then use shift, then elgetpositionals. That way, $@ will correctly be replaced by the remaining arguments. More generally, you should try to use elgetpositionals as late as possible.
  • Use execlineb's -S switch instead of elgetpositionals whenever you can. It is more efficient.
execline-2.8.2.0/doc/elglob.html000066400000000000000000000050231416030414000163450ustar00rootroot00000000000000 execline: the elglob command

execline
Software
skarnet.org

The elglob program

elglob performs globbing on a pattern, then executes another program.

Interface

     elglob [ -v ] [ -w ] [ -s ] [ -m ] [ -e ] [ -0 ] variable pattern prog...
  • elglob performs globbing on pattern.
  • It then performs variable substitution on prog..., using variable as key and the result of the globbing as value. The value is always split: it contains as many words as they are matches for the globbing pattern.
  • elglob then execs into the modified prog....

Options

  • -v : verbose. If there is a problem while globbing, print a warning message on stderr.
  • -w : strict. If there is a problem while globbing, die immediately. This is harsh - you probably don't need that option.
  • -s : sort the matches. By default, the results are left unsorted.
  • -m : mark. Append a slash to each word that corresponds to a directory.
  • -e : no escape. Treat backslashes in pattern literally; do not allow quoting of metacharacters in pattern via backslashes. Warning: the execlineb launcher uses the backslash as their own escape character - if you want a backslash to be passed to elglob, do not forget to double it.
  • -0 : null globbing. By default, if pattern matches nothing, it will be substituted as is (verbatim in one word). With this option, if pattern matches nothing, it will be properly substituted as zero word.
execline-2.8.2.0/doc/emptyenv.html000066400000000000000000000037441416030414000167600ustar00rootroot00000000000000 execline: the emptyenv program

execline
Software
skarnet.org

The emptyenv program

emptyenv empties the current environment, or cleans it up; then executes a program.

Interface

     emptyenv [ -p ] prog...
     emptyenv -c prog...
     emptyenv [ -o ] [ -P ] prog...

By default, emptyenv unsets all environment variables, then execs into prog with its arguments. Options control which environment variables are unset.

Options

  • -p : keep the PATH environment variable.
  • -c : clean up. Do not empty the environment. Instead, remove every variable used internally by the execline programs, to avoid any interference with or information leakage to external programs.
  • -o : pop environment variables starting with ELGETOPT_. You might want to do this before executing a final program from a script that uses elgetopt.
  • -P : pop environment variables starting with #, 0 to 9, and EXECLINE_. You might want to do this before executing a final program from a script launched by execlineb.
execline-2.8.2.0/doc/envfile.html000066400000000000000000000101141416030414000165260ustar00rootroot00000000000000 execline: the envfile program

execline
Software
skarnet.org

The envfile program

envfile reads a file containing variable assignments, adds the variables to the environment, then executes a program.

Interface

     envfile [ -i | -I ] file prog...

envfile reads file and adds the key-value pairs defined in file to the environment. Then it execs into prog..., i.e. the rest of its command line, with the modified environment.

Exit codes

  • 1: syntax error in file
  • 100: wrong usage
  • 111: system call failed
  • 126: execve() on prog failed (unknown reason)
  • 127: execve() on prog failed (prog could not be found)

0 is not listed because on success, envfile does not exit: it execs into prog.

Options

  • -i : strict. If file does not exist, exit 111 with an error message. This is the default.
  • -I : loose. If file does not exist, exec into prog without modifying the environment.

File syntax

file is a text file containing lines of the form key = value. Whitespace is permitted before and after key, and before or after value.

Empty lines, or lines containing only whitespace, are ignored. Lines beginning with # (possibly after some whitespace) are ignored (and typically used for comments). Leading and trailing whitespace is stripped from values; but a value can be double-quoted, which allows for inclusion of leading and trailing whitespace.

A non-commented line that ends with a backslash ("\") is concatenated with the following one, and the newline character is ignored. If a backslashed newline happens before the start of a value, then the whitespace at the beginning of the new line will be part of the value (i.e. leading whitespace on a new line is not stripped).

C escapes, including hexadecimal and octal sequences, are supported in quoted values. Unicode codepoint sequences are not supported. It is possible to include a newline in a quoted value by using \n; but including newlines in environment variables is not recommended.

If value is empty, key is still added to the environment, with an empty value. If you do not want key to be added to the environment at all, comment out the line. envfile does not offer a way to remove variables from the environment.

The envfile format is largely compatible with systemd's EnvironmentFile format, which allows for the reuse of such files outside of systemd.

Notes

  • If file is - then envfile reads and parses its standard input instead. To read a file literally named -, you can use ./- for instance.
  • The variables that can be defined with envfile are purposefully restricted. If you need more expressive power for your variable names, or for your values, you should use an envdir instead: see s6-envdir.
execline-2.8.2.0/doc/exec.html000066400000000000000000000032731416030414000160320ustar00rootroot00000000000000 execline: the exec program

execline
Software
skarnet.org

The exec program

exec executes the command line it is given.

Interface

     exec [ -c ] [ -l ] [ -a argv0 ] prog...

exec execs into prog.... It does nothing else.
Without options, exec can be seen as the execline NOP.

Options

  • -c : empty the environment. prog is executed with no environment variables. Warning: prog will run with an empty PATH, so make sure it does not rely on it.
  • -l : login. Prepends prog's argv[0] with a dash.
  • -a argv0 : argv0. Replace prog's argv[0] with argv0. This is done before adding a dash, if the -l option is also present.

The exec command, along with its options, is designed to emulate the standard exec shell builtin, which replaces the shell with the command it is given.

execline-2.8.2.0/doc/execline-cd.html000066400000000000000000000033151416030414000172630ustar00rootroot00000000000000 execline: the execline-cd command

execline
Software
skarnet.org

The execline-cd program

execline-cd changes the current working directory to a given directory, then executes a program.

Interface

     execline-cd dir prog...

execline-cd performs a chdir() system call on dir, then execs into prog....

Notes

  • By default, execline-cd can also be invoked as cd: there is a cd program which is a symbolic link to execline-cd.
  • When execline has been configured with the --enable-pedantic-posix option, the cd binary is a symbolic link to the posix-cd binary instead, so a cd command in an execline script will invoke posix-cd instead of execline-cd.
  • Existing scripts that call cd will keep working no matter the chosen configuration.
execline-2.8.2.0/doc/execline-shell.html000066400000000000000000000034211416030414000200020ustar00rootroot00000000000000 execline: the execline-shell script

execline
Software
skarnet.org

The execline-shell script

execline-shell executes $HOME/.execline-shell if available (or /bin/sh otherwise) with the arguments it is given.

Interface

     /etc/execline-shell
  • execline-shell transforms itself into ${HOME}/.execline-shell $@.
  • ${HOME}/.execline-shell must be readable and executable by the user. It must exec into an interactive shell with $@ as its argument.

Notes

  • execline-shell is meant to be used as the SHELL environment variable value. It allows one to specify their favourite shell and shell configuration in any language, since the ${HOME}/.execline-shell file can be any executable program. ${HOME}/.execline-shell can be seen as a portable .whateverrc file.
  • As an administrator-modifiable configuration file, execline-shell is provided in execline's examples/etc/ subdirectory, and should be copied by the administrator to /etc.
execline-2.8.2.0/doc/execline-startup.html000066400000000000000000000043061416030414000204000ustar00rootroot00000000000000 execline: the execline-startup script

execline
Software
skarnet.org

The execline-startup script

execline-startup performs some system-specific login initialization, then executes ${HOME}/.execline-loginshell.

Interface

     /etc/execline-startup
  • execline-startup sets the SHELL environment variable to /etc/execline-shell. It then performs some system-specific initialization, and transforms itself into ${HOME}/.execline-loginshell $@ if available (and /etc/execline-shell otherwise).
  • ${HOME}/.execline-loginshell must be readable and executable by the user. It must exec into $SHELL $@.

Notes

  • execline-startup is an execlineb script; hence, it is readable and modifiable. It is meant to be modified by the system administrator to perform system-specific login-time initialization.
  • As a modifiable configuration file, execline-startup is provided in execline's examples/etc/ subdirectory, and should be copied by the administrator to /etc.
  • execline-startup is meant to be used as a login shell. System administrators should manually add /etc/execline-startup to the /etc/shells file. The /etc/execline-startup file itself plays the role of the /etc/profile file, and ${HOME}/.execline-loginshell plays the role of the ${HOME}/.profile file.
execline-2.8.2.0/doc/execline-umask.html000066400000000000000000000027371416030414000200240ustar00rootroot00000000000000 execline: the execline-umask command

execline
Software
skarnet.org

The execline-umask program

execline-umask sets the umask (file creation mask), then executes a program.

Interface

     execline-umask mask prog...

execline-umask sets the current umask to mask, then execs into prog....

Notes

  • By default, at execline installation time, a umask symbolic link is created, pointing to execline-umask.
  • When execline has been configured with the --enable-pedantic-posix option, the umask symbolic link points to the posix-umask binary instead.
  • Existing execline scripts calling umask will keep working no matter the chosen configuration.
execline-2.8.2.0/doc/execlineb.html000066400000000000000000000240451416030414000170440ustar00rootroot00000000000000 execline: the execlineb command

execline
Software
skarnet.org

The execlineb program

execlineb reads and executes a script.
It is a command launcher: it reads a file, turns that file into a command line, then executes into that command line.

Interface

     execlineb [ -q | -w | -W ] [ -p | -P | -S nmin | -s nmin ] -c script [ args... ]

or

     execlineb [ -q | -w | -W ] [ -p | -P | -S nmin | -s nmin ] scriptfile [ args... ]

or in an executable file:

#!/command/execlineb [ -qwWpPSnmin ]
script

Parsing phase.

  • execlineb reads and parses the script it is given. It exits 100 on a syntax error and 111 on a temporary error. It makes an argv, i.e. a system command line, with the parsed script. If the argv is empty, execlineb exits 0.

Environment management phase.

  • Pushing the current stack frame. If none of the -p, -P, -S or -s options are set: execlineb pushes the current positional parameters, i.e. environment variables that start with #, 0, 1, ..., 9. To get the previous values back, use emptyenv -P.
  • Setting the new stack frame. If none of the -P, -S or -s options are set:
    • execlineb sets the # environment variable to the number n of args it is given.
    • It sets the 0 environment variable to the name of the script - or to the execlineb invocation name if the -c option is used.
    • It sets the 1, 2, ... n environment variables to the different args.

Execution phase.

  • execlineb executes into the argv it has built from the script. There is only one command line for the whole script: the execlineb binary is a launcher, whose sole purpose is to execute into that command line. It does not stay in memory like a traditional interpreter would.

Options

  • -c script : execute script, do not look for a file.

See below for the other options.

Syntax of scripts

An execlineb script is a string that must not contain the null character. execlineb parses it and divides it into words. The parser recognizes the following components:

  • whitespace is defined as spaces, tabs, newlines and carriage returns. Words are always separated by whitespace.
  • A quoted string begins with a doublequote (") and ends with another doublequote. Quoted doublequotes must be prefixed by a backslash (\). Quoted strings always evaluate to exactly one word. For instance, "" evaluates to the empty word.
  • The \a, \b, \t, \n, \v, \f, and \r sequences are recognized in quoted strings, and are converted to the ASCII numbers 7, 8, 9, 10, 11, 12 and 13 respectively.
  • Inside a quoted string, backslashed newlines disappear completely.
  • \0xab sequences are recognized in quoted strings and evaluate to ASCII hexadecimal number ab.
  • \0abc sequences are recognized in quoted strings and evaluate to ASCII octal number abc.
  • \abc sequences are recognized in quoted strings and evaluate to ASCII decimal number abc. a must not be zero.
  • A comment starts with a # and ends with the line. Comments are not recognized inside quoted strings.
  • Anything else is an unquoted string, that can evaluate to zero or more words.
  • Any character can be escaped in unquoted strings by prepending it with a backslash. It works the same way in quoted strings, except for the special sequences described above.

You can see an example of distinct execlineb components here.

In addition to that simple lexing, execlineb performs the following higher-level parsing:

  • A word consisting of a single opening brace ({) increments an internal level counter, blevel, and disappears from the argv. Quoted open braces do not have that behaviour.
  • A word consisting of a single closing brace (}) decrements blevel, and is replaced with the empty word. Quoted closing braces do not have that behaviour.
  • If execlineb finds that braces are unmatched (i.e. blevel goes below 0 during the parsing, or is not 0 at the end of the script), it exits 100 with an error message.
  • execlineb automatically quotes blocks. Which means that every time it finds a word, it prepends it with blevel spaces.

For proper execution, the sequence of words must follow the execline grammar.

Options for block syntax checking

External execline commands that read blocks, like foreground, use the EXECLINE_STRICT environment variable: if it is set to 1, they will print a warning message on stderr if they find their blocks not to be properly quoted. If it is set to 2, they will also die. If it is set to 0, or unset, they won't complain at all.

Normally the EXECLINE_STRICT environment variable is inherited from the caller. You can force it unset, set to 1, or set to 2 by giving respectively the -q, -w or -W option to execlineb.

The EXECLINE_STRICT variable (as well as the -q, -w and -W options to execlineb) will also modify the behaviour of the -S nmin and -s nmin options when execlineb is called with less than nmin positional parameters:

  • If EXECLINE_STRICT is 0: the script will run silently, and missing positional parameters, up to nmin, will be substituted with the empty word.
  • If EXECLINE_STRICT is 1 or unset: same, but the script will print a warning message rather than run silently.
  • If EXECLINE_STRICT is 2: the script will exit with an error message.

Options for environment management

Normally, execline scripts are reentrant: environment variables potentially overwritten by execlineb, such as # or 0, are pushed. This is the standard, safe behaviour. Nevertheless, it is rather costly, and may be unneeded for small scripts: for those cases, execline comes with two options that bypass the environment management. Be warned that the purpose of these options is optimization, and you should not use them if you're not familiar with the way execlineb uses the environment to store positional parameters. Alternatively, there's also an integrated substitution mechanism that doesn't make use of the environment at all.

  • The -p option will bypass the push phase: the current frame of positional parameters will be overwritten. The script will not be reentrant.
  • The -P option will bypass positional parameter handling completely: the environment will not be pushed, and positional parameters will be ignored. execlineb -P -c "script" is equivalent to, but more efficient than, execlineb -c "emptyenv -P script". You should use the -P option only in standalone scripts that take no arguments, such as s6's or runit's run scripts.
  • The -S nmin option will substitute the positional parameters - up to at least nmin - but will not push nor set environment variables. execlineb -S3 -c "script" is equivalent to, but more efficient than, execlineb -c "elgetpositionals -P3 emptyenv -P script". See the details.
  • The -s nmin option behaves just like the -S option, except that it defines $@ as the rest of the command line after nmin arguments have been removed.

Current limitations

execlineb builds and executes a unique argv with the script: hence scripts are subject to OS-dependent limitations such as the kernel buffer size for argv and envp - at least 64 kB on most systems. This means that execlineb cannot execute arbitrarily large scripts. Be careful with deeply nested scripts too: without the -p/-P/-S/-s option, each execlineb invocation uses up some space in the environment.

execline-2.8.2.0/doc/exit.html000066400000000000000000000021271416030414000160540ustar00rootroot00000000000000 execline: the exit program

execline
Software
skarnet.org

The exit program

exit exits with a given exit code.

Interface

     exit [ n ]

exit exits with the exit code n, or 0 if n is not given (in which case it's the same as true). If n is not a number, exit exits 100.

Notes

exit is a standard shell builtin, with the same function.

execline-2.8.2.0/doc/exitcodes.html000066400000000000000000000100741416030414000170720ustar00rootroot00000000000000 execline: exit codes

execline
Software
skarnet.org

How to propagate exit codes up a process dynasty

Say we have a parent process P, child of a grandparent process G, spawning a child process C and waiting for it. Either C dies normally with an exit code from 0 to 255, or it is killed by a signal. How can we make sure that P reports to G what happened to C, with as much precision as possible?

The problem is, there's more information in a wstat (the structure filled in by waitpid()) than a process can report by simply exiting. P could exit with the same exit code as C, but then what should it do if C has been killed by a signal?

An idea is to have P kill itself with the same signal that killed C. But that's actually not right, because P itself could be killed by a signal from another source, and G needs that information. "P has been killed by a signal" and "C has been killed by a signal" are two different pieces of information, so they should not be reported in the same way.

So, any way you look at it, there is always more information than we can report.

Shells have their own convention for reporting crashes, but since any exit code greater than 127 is reported as is, the information given by the shell is unreliable: "child exited 129" and "child was killed by SIGHUP" are indistinguishable. When shells get nested, all bets are off - the information conveyed by exit codes becomes devoid of meaning pretty fast. We need something better.

execline's solution

execline commands such as if, that can report a child's exit code, proceed that way when they're in the position of P:

  • If C was killed by a signal: P exits 128 plus the signal number.
  • If C exited 128 or more: P exits 128.
  • Else, P exits with the same code as C.

Rationale:

  • 128+ exit codes are extremely rare and should report really problematic conditions; commands usually exit 127 or less. If C exits 128+, it's more important to convey the information "something really bad happened, but the C process itself was not killed by a signal" than the exact nature of the event.
  • Commands following that convention can be nested. If P exits 129+, G knows that C was killed by a signal. If G also needs to report that to its parent, it will exit 128: G's parent will not know the signal number, but it will know that P reported 128 or more, so either C or a scion of C had problems.
  • Exact information is reported in the common case.

Summary of common exit codes for execline programs

  • 0: success. This code is rarely encountered, because most execline programs chainload into something else when they succeed, instead of exiting 0.
  • 100: wrong usage
  • 111: system call failed
  • 126: unable to chainload into another program (any other error than ENOENT)
  • 127: unable to chainload into another program (executable not found)
execline-2.8.2.0/doc/export.html000066400000000000000000000022721416030414000164250ustar00rootroot00000000000000 execline: the export program

execline
Software
skarnet.org

The export program

export sets an environment variable to a given value, then executes a program.

Interface

     export var value prog...

export sets the var environment variable to the string value, then execs into prog with its arguments.

  • var must be given without a dollar!
  • var must not contain the character = .
execline-2.8.2.0/doc/fdblock.html000066400000000000000000000031431416030414000165060ustar00rootroot00000000000000 execline: the fdblock program

execline
Software
skarnet.org

The fdblock program

fdblock sets or unsets the O_NONBLOCK flag on a given file descriptor (which makes reading or writing non-blocking or blocking), then executes a program.

Interface

     fdblock [ -n ] fd prog...

fdblock makes the file descriptor number fd blocking, no matter what its previous state was. It then execs into prog with its arguments.

Options

  • -n : non-blocking. Sets fd to non-blocking mode instead of blocking mode. If used on stdin (0) or stdout (1), this option will make a lot of command-line programs behave improperly, because most simple command-line programs only support blocking stdin and stdout. Make sure you know what you are doing.

Notes

  • fdblock has no portable shell equivalent.
execline-2.8.2.0/doc/fdclose.html000066400000000000000000000022301416030414000165150ustar00rootroot00000000000000 execline: the fdclose program

execline
Software
skarnet.org

The fdclose program

fdclose closes a given file descriptor, then executes a program.

Interface

     fdclose fd prog...

fdclose closes the file descriptor number fd, then execs into prog with its arguments.

Notes

  • fdclose n prog... is roughly equivalent to sh -c 'exec prog... n<&-'
execline-2.8.2.0/doc/fdmove.html000066400000000000000000000040221416030414000163570ustar00rootroot00000000000000 execline: the fdmove program

execline
Software
skarnet.org

The fdmove program

fdmove moves or copies a given file descriptor, then executes a program.

Interface

     fdmove [ -c ] fdto fdfrom prog...

fdmove moves the file descriptor number fdfrom, to number fdto, then execs into prog with its arguments. If fdto is open, fdmove closes it before moving fdfrom to it.

Options

  • -c : duplicate fdfrom to fdto instead of moving it; do not close fdfrom.

Notes

  • fdmove a b prog... is roughly equivalent to sh -c 'exec prog... a>&b b<&-'. It means: if you write to fd a now, it will have the same effect as writing to fd b beforehand, and you cannot write to fd b anymore.
  • fdmove -c a b prog... is roughly equivalent to sh -c 'exec prog... a>&b'. It means: you can now write to fd a, and also still write to fd b, and both will have the same effect as writing to fd b beforehand.
  • It also works with file descriptors that are open for reading!
execline-2.8.2.0/doc/fdreserve.html000066400000000000000000000044461416030414000170760ustar00rootroot00000000000000 execline: the fdreserve program

execline
Software
skarnet.org

The fdreserve program

fdreserve updates the environment with file descriptors that are guaranteed safe to use, then executes a program.

Interface

     fdreserve n prog...
  • fdreserve tries to reserve n file descriptors.
  • fdreserve sets the FD0, FD1, ..., FDn-1 environment variables: each FDi contains a valid file descriptor, that can be safely opened.
  • fdreserve then execs into prog with its arguments.

Common use

fdreserve can be used when you do not want to hardcode file descriptors in your scripts. For instance, to create a pipe, you could use:

 #!/command/execlineb
 fdreserve 2
 multisubstitute
 {
   importas fdr FD0
   importas fdw FD1
 }
 piperw $fdr $fdw
 prog...

Warning: fdreserve does not allocate descriptors, it merely returns descriptors that are free at the time it is run. A program like

 #!/command/execlineb
 fdreserve 3
 multisubstitute
 {
   importas fdr FD0
   importas fdw FD1
 }
 piperw $fdr $fdw
 fdreserve 1
 multisubstitute
 {
   importas oldfd FD2
   importas newfd FD0
 }
 prog...

may fail, because oldfd and newfd may be the same. To avoid that, you should make sure that all descriptors returned by fdreserve are actually allocated before calling fdreserve again. (Thanks to Paul Jarc for having spotted that case.)

execline-2.8.2.0/doc/fdswap.html000066400000000000000000000021501416030414000163630ustar00rootroot00000000000000 execline: the fdswap program

execline
Software
skarnet.org

The fdswap program

fdswap swaps two file descriptors, then executes a program.

Interface

     fdswap fd1 fd2 prog...

fdswap swaps file descriptors numbered fd1 and fd2, then execs into prog with its arguments.

Notes

  • fdswap has no portable shell equivalent.
execline-2.8.2.0/doc/forbacktickx.html000066400000000000000000000113231416030414000175530ustar00rootroot00000000000000 execline: the forbacktickx command

execline
Software
skarnet.org

The forbacktickx program

forbacktickx runs a program and uses its output as loop elements to run another program.

Interface

In an execlineb script:

     forbacktickx [ -E | -e ] [ -p | -o okcodes | -x breakcodes ] [ -N | -n ] [ -C | -c ] [ -0 | -d delim ] variable { gen... } loop...
  • forbacktickx reads a block, gen..., and unquotes it.
  • It runs gen... as a child process. gen's output must not contain a null character.
  • It reads gen's output as it needs, splitting it automatically.
  • For every argument x in the split output, forbacktickx runs loop... as a child process, with variable=x added to its environment.
  • forbacktickx then exits 0.

Options

  • -p : parallel mode. Do not wait for a loop... instance to finish before spawning the next one. forbacktickx will still wait for all instances of loop to terminate before exiting, though.
  • -o okcodes : okcodes must be a comma-separated list of exit codes. If the -p flag hasn't been given and loop exits with one of the codes in okcodes, forbacktickx will run the following instances of the loop, but if the exit code is not listed in okcodes, forbacktickx will exit immediately with an approximation of the same exit code.
  • -x breakcodes : like the previous option, but with inverted meaning - the listed exit codes are codes that will make forbacktickx break the loop and exit, and the unlisted exit codes will make it keep looping.
  • -e : no autoimport. This is the default.
  • -E : autoimport. Instead of spawning loop..., spawn importas -ui variable variable loop.... This substitutes variable into the command line instead of putting it into the environment.

Other options are similar (in name and functionality) to the switches passed to control a substitution mechanism, on purpose; however, forbacktickx does not call the substitution mechanism and has its own semantics for those options.

  • -N : store the whole line in variable, including the terminating newline (or other delimiter).
  • -n : chomp a terminating delimiter from the line from stdin before storing it into variable. This is the default.
  • -C : crunch. If there is an empty line (i.e. that only contains a delimiter), do not call loop. If this option is given, and chomping is active, and the last line of stdin is not terminated by a delimiter, then this last line will not be processed.
  • -c : do not crunch, call loop even if the line is empty. This is the default.
  • -0 : accept null characters on its stdin, using them as delimiters. If this option and a -d option are used simultaneously, the rightmost one wins.
  • -d delim : use the characters in string delim as delimiters for a line. Default is "\n", meaning the input is only split on newlines.

Notes

  • You can start loop... with "importas -u variable variable" to perform variable substitution.
  • forbacktickx is now implemented as a wrapper around the pipeline and forstdin commands, with calls to fdmove to ensure that loop... is called with the proper standard input.
execline-2.8.2.0/doc/foreground.html000066400000000000000000000042661416030414000172630ustar00rootroot00000000000000 execline: the foreground command

execline
Software
skarnet.org

The foreground program

foreground executes a sequence of commands.

Interface

In an execlineb script:

     foreground { prog1... } prog2...
  • foreground reads prog1 in a block. It forks and executes it, then waits for it to complete.
  • foreground sets the ? environment variable to the exit code of prog1. If prog1... was killed by a signal, the ? value is 256 plus the signal number.
  • foreground then execs into prog2....

Notes

  • foreground is the basic sequence operator: it takes two commands and executes them one by one. execline scripts require it to wrap external commands that exit instead of natively supporting the "perform some action, then execute some other program" model.
  • foreground prog1... "" prog2... is equivalent to sh -c 'prog1... ; exec prog2...'.
  • 256 and above are not valid exit codes for commands, so when the ? environment variable contains 256 or more, it means that the previous command was killed by a signal. There is no ambiguity here, and ? reports exactly what happened to the previous command; foreground does not exit, so there is no need for exit code approximation.
execline-2.8.2.0/doc/forstdin.html000066400000000000000000000103031416030414000167260ustar00rootroot00000000000000 execline: the forstdin command

execline
Software
skarnet.org

The forstdin program

forstdin uses its input as loop elements to run another program.

Interface

In an execlineb script:

     forstdin [ -E | -e ] [ -p | -o okcodes | -x breakcodes ] [ -N | -n ] [ -C | -c ] [ -0 | -d delim ] variable loop...
  • forstdin reads its standard input as it becomes available, splitting it on every line automatically.
  • For every argument x in the split output, forstdin runs loop... as a child process, with variable=x added to its environment.
  • forstdin then exits 0 if it has read something on stdin, and 1 if it hasn't read anything.

Options

  • -p : parallel mode. Do not wait for a loop... instance to finish before spawning the next one. forstdin will still wait for all instances of loop to terminate before exiting, though.
  • -o okcodes : okcodes must be a comma-separated list of exit codes. If the -p flag hasn't been given and loop exits with one of the codes in okcodes, forstdin will run the following instances of the loop, but if the exit code is not listed in okcodes, forstdin will exit immediately with an approximation of the same exit code.
  • -x breakcodes : like the previous option, but with inverted meaning - the listed exit codes are codes that will make forstdin break the loop and exit, and the unlisted exit codes will make it keep looping.
  • -e : no autoimport. This is the default.
  • -E : autoimport. Instead of spawning loop..., spawn importas -ui variable variable loop.... This substitutes variable into the command line instead of putting it into the environment.

Other options are similar (in name and functionality) to the switches passed to control a substitution mechanism, on purpose; however, forstdin does not call the substitution mechanism and has its own semantics for those options.

  • -N : store the whole line in variable, including the terminating newline (or other delimiter).
  • -n : chomp a terminating delimiter from the line from stdin before storing it into variable. This is the default. Note that if chomping is active, and the last line of stdin is not terminated by a delimiter, then this last line will not be processed.
  • -C : crunch. If there is an empty line (i.e. that only contains a delimiter), do not call loop.
  • -c : do not crunch, call loop even if the line is empty. This is the default.
  • -0 : accept null characters on its stdin, using them as delimiters. If this option and a -d option are used simultaneously, the rightmost one wins.
  • -d delim : use the characters in string delim as delimiters for a line. Default is "\n", meaning the input is only split on newlines.

Notes

  • You can start loop... with "importas -u variable variable" to perform variable substitution.
execline-2.8.2.0/doc/forx.html000066400000000000000000000057511416030414000160670ustar00rootroot00000000000000 execline: the forx command

execline
Software
skarnet.org

The forx program

forx runs a loop.

Interface

In an execlineb script:

     forx [ -E | -e ] [ -p ] [ -o okcodes | -x breakcodes ] variable { args... } loop...
  • forx reads a block and unquotes it. That block contains a list of args.
  • For each argument x in args..., forx runs loop as a child process, with variable=x added to its environment.
  • forx then exits 0.

Options

  • -o okcodes : okcodes must be a comma-separated list of exit codes. If loop exits with one of the codes in okcodes, forx will run the following instances of the loop, but if the exit code is not listed in okcodes, forx will exit immediately with an approximation of the same exit code.
  • -x breakcodes : like the previous option, but with inverted meaning - the listed exit codes are codes that will make forx break the loop and exit, and the unlisted exit codes will make it keep looping.
  • -p : run in parallel. Do not wait for an instance of loop... to exit before spawning the next one. forx will still wait for all instances of loop to terminate before exiting 0. If the -o option has been given, forx will exit 0 if all of the exit codes are in the values listed in the okcodes list, else it will exit 1. If the -x option has been given, forx will exit 0 if none of the exit codes are in the values listed in the breakcodes list, else it will exit 1.
  • -e : no autoimport. This is the default.
  • -E : autoimport. Instead of spawning loop..., spawn importas -ui variable variable loop.... This substitutes variable into the command line instead of putting it into the environment.

Notes

  • You can start loop with "importas -u variable variable" if you want variable substitution.
execline-2.8.2.0/doc/getcwd.html000066400000000000000000000036421416030414000163630ustar00rootroot00000000000000 execline: the getcwd program

execline
Software
skarnet.org

The getcwd program

getcwd stores its current working directory into a given environment variable, then executes a program.

Interface

     getcwd [ -E | -e ] var prog...

getcwd stores a fully resolved absolute path (i.e. without any .. or symbolic link components) to its current working directory into the var variable, then execs into prog with its arguments.

Options

  • -e : no autoimport. This is the default.
  • -E : autoimport. Instead of exec'ing into prog..., exec into importas -ui var var prog.... This substitutes var into the command line instead of putting it into the environment.

Notes

  • var must be given without a dollar!
  • var must not contain =.
  • Unlike the pwd POSIX command, getcwd does not depend on the PWD environment variable and will exhibit a consistent behaviour no matter the environment.
execline-2.8.2.0/doc/getpid.html000066400000000000000000000030121416030414000163510ustar00rootroot00000000000000 execline: the getpid program

execline
Software
skarnet.org

The getpid program

getpid stores its process ID in a given environment variable, then executes a program.

Interface

     getpid [ -E | -e ] var prog...

getpid stores its PID in the var variable, then execs into prog with its arguments.

Options

  • -e : no autoimport. This is the default.
  • -E : autoimport. Instead of exec'ing into prog..., exec into importas -ui var var prog.... This substitutes var into the command line instead of putting it into the environment.

Notes

  • var must be given without a dollar!
  • var must not contain =.
execline-2.8.2.0/doc/grammar.html000066400000000000000000000150321416030414000165300ustar00rootroot00000000000000 execline: language design and grammar

execline
Software
skarnet.org

The execline language design and grammar

execline principles

Here are some basic Unix facts:

Knowing that, and wanting lightweight and efficient scripts, I wondered: "Why should the interpreter stay in memory while the script is executing? Why not parse the script once and for all, put it all into one argv, and just execute into that argv, relying on external commands (which will be called from within the script) to control the execution flow?"

execline was born.

  • execline is the first script language to rely entirely on chain loading. An execline script is a single argv, made of a chain of programs designed to perform their action then exec() into the next one.
  • The execlineb command is a launcher: it reads and parses a text file, converting it to an argv, then executes into that argv. It does nothing more.
  • Straightforward scripts like nice -10 echo blah will be run just as they are, without the shell overhead. Here is what the script could look like:
    #!/command/execlineb -P
    nice -10
    echo blah
    
  • More complex scripts will include calls to other execline commands, which are meant to provide some control over the process state and execution flow from inside an argv.

Grammar of an execline script

An execline script can be parsed as follows:

 <instruction> = <> | external options <arglist> <instruction> | builtin options <arglist> <blocklist> <instruction>
 <arglist> = <> | arg <arglist>
 <blocklist> = <> | <block> <blocklist>
 <block> = { <arglist> } | { <instrlist> }
 <instrlist> = <> | <instruction> <instrlist>

(This grammar is ambivalent, but much simpler to understand than the non-ambivalent ones.)

execline features

execline commands can perform some transformations on their argv, to emulate some aspects of a shell. Here are descriptions of these features:

execline-2.8.2.0/doc/heredoc.html000066400000000000000000000030671416030414000165200ustar00rootroot00000000000000 execline: the heredoc program

execline
Software
skarnet.org

The heredoc program

heredoc runs a command with a certain string fed to a file descriptor.

Interface

     heredoc [ -d ] fd string prog...
  • heredoc execs into prog... with string available on the fd file descriptor.
  • string must not contain a null character.

Options

  • -d : run the process feeding string to fd as a grandchild of heredoc. This is meant to prevent a zombie from hanging around if prog... has read string and fails to wait for its children.

Notes

  • heredoc is meant to be used in place of the shell << construct, which includes here-documents into scripts.
execline-2.8.2.0/doc/homeof.html000066400000000000000000000020301416030414000163510ustar00rootroot00000000000000 execline: the homeof program

execline
Software
skarnet.org

The homeof program

homeof prints the home directory of a user.

Interface

     homeof user

homeof finds the name of user's home directory, writes it on stdout, then exits 0. If an error occurs, it prints nothing on stdout but exits 111 with an explanatory message on stderr.

execline-2.8.2.0/doc/if.html000066400000000000000000000047661416030414000155140ustar00rootroot00000000000000 execline: the if command

execline
Software
skarnet.org

The if program

if performs conditional execution.

Interface

In an execlineb script:

     if [ -X ] [ -n ] [ -t | -x exitcode ] { prog1... } prog2...
  • if reads prog1... in a block. It forks and executes it, then waits for it to complete.
  • If prog1 crashes, if prints an error message then exits 128 plus the number of the signal that killed prog1.
  • If prog1 exits with a non-zero code, if exits with an approximation of that code.
  • Else if execs into prog2.

Options

  • -X : treat a crash of prog1 as a non-zero ("false") exit. This is mostly useful in combination with -n.
  • -n : negate the test. If prog1 exits true, then if will exit 1; else it will exec into prog2.
  • -x exitcode : if if needs to exit, it will exit exitcode instead of whatever else it would have exited.
  • -t : if if needs to exit, it will exit 0. This is equivalent to -x 0.

Notes

  • if will exit if prog1... exits false. To use it in an execline script that must run prog3... no matter the result of the test, use a foreground wrapper:
     foreground { if { prog1... } prog2... } prog3... 
    (in execlineb syntax)
  • if prog1... "" prog2... is equivalent to sh -c 'prog1... && exec prog2...'.
execline-2.8.2.0/doc/ifelse.html000066400000000000000000000035211416030414000163510ustar00rootroot00000000000000 execline: the ifelse command

execline
Software
skarnet.org

The ifelse program

ifelse performs conditional execution, with two branches.

Interface

In an execlineb script:

     ifelse [ -X ] [ -n ] { prog1... } { prog2... } prog3...
  • ifelse reads prog1... in a block. It forks and executes it, then waits for it to complete.
  • If prog1 crashes, ifelse prints an error message and exits 128 plus the number of the signal that killed prog1.
  • If prog1 exits with a return code equal to 0, ifelse execs into prog2.
  • Else ifelse execs into prog3.

Options

  • -n : negate the test.
  • -X : do not die if prog1 crashes; treat a crash as a non-zero ("false") exit.

Notes

  • ifelse prog1... "" prog2... "" prog3... is roughly equivalent to sh -c 'prog1... && exec prog2... || exec prog3...'.
execline-2.8.2.0/doc/ifte.html000066400000000000000000000041371416030414000160350ustar00rootroot00000000000000 execline: the ifte command

execline
Software
skarnet.org

The ifte program

ifte performs a conditional alternative.

Interface

In an execlineb script:

     ifte [ -X ] [ -n ] { progthen... } { progelse... } progif...
  • ifte reads progthen... and progelse... in two consecutive blocks.
  • ifte runs progif... as a child process and waits for it to complete.
  • If progif... crashes (i.e. is killed by a signal), ifte prints an error message, then exits 128 plus the number of the signal that killed progif.
  • If progif... exits zero, ifte execs into progthen..., else it execs into progelse....

Options

  • -X : do not exit if progif crashes; instead, proceed as if the test had returned false.
  • -n : negate the test. progthen... will be run iff progif... exits nonzero.

Notes

ifte is a simpler version of ifthenelse. It performs only conditional execution, not instruction sequence.

"ifthenelse { progif } { progthen } { progelse } remainder" is the equivalent of "foreground { ifte { progthen } { progelse } progif } remainder".

execline-2.8.2.0/doc/ifthenelse.html000066400000000000000000000040061416030414000172270ustar00rootroot00000000000000 execline: the ifthenelse command

execline
Software
skarnet.org

The ifthenelse program

ifthenelse performs a conditional alternative.

Interface

In an execlineb script:

     ifthenelse [ -X ] [ -s ] { progif... } { progthen... } { progelse... } prog...
  • ifthenelse reads progif..., progthen... and progelse... in 3 consecutive blocks.
  • ifthenelse runs progif... as a child process and waits for it to complete.
  • If progif... crashes (i.e. is killed by a signal), ifthenelse prints an error message, then exits 128 plus the number of the signal that killed progif.
  • If progif... exits zero, ifthenelse runs progthen... as a child process, else it runs progelse....
  • ifthenelse waits for its child to complete and puts the exit status in the ? environment variable. It then execs into prog....

Options

  • -X : if progif crashes, do not exit; proceed as if it had returned false.
  • -s : magic scoping hack. This option does powerful but ugly things, and is left undocumented on purpose.
execline-2.8.2.0/doc/importas.html000066400000000000000000000055721416030414000167500ustar00rootroot00000000000000 execline: the importas program

execline
Software
skarnet.org

The importas program

importas replaces a literal with the value of an environment variable, then executes another program.

Interface

     importas [ -i | -D default ] [ -u ] [ -s ] [ -C | -c ] [ -N | -n ] [ -d delim ] variable envvar prog...
  • importas fetches the value of envvar in the environment. If neither the -D nor the -i option is given, and envvar is undefined, no word is returned (that is different from the empty word).
  • importas then performs variable substitution on prog..., with variable as key and that string as value.
  • importas then execs into the modified prog....

Options

  • -D default : If this option is given and envvar is undefined, substitute default for the value of variable instead of no word. For instance, to substitute the empty word, use -D "".
  • -i : Insist. If envvar is undefined, importas will not do anything; instead, it will exit 100 with an error message. This has precedence over any -D option.
  • -u : Unexport. envvar will be removed from the environment after the substitution. importas -u variable envvar is equivalent to importas variable envvar unexport envvar.
  • Other options are used to control the substitution mechanism.

Notes

  • When envvar is undefined, and the -D option is not given, any variable substitution with variable as the key will return no word; that is true even when the ${variable} form to be substituted happens in the middle of a word (with a prefix and/or a postfix), which means the whole word will be deleted. If this is not the behaviour you want, use the -D option.
execline-2.8.2.0/doc/index.html000066400000000000000000000216701416030414000162160ustar00rootroot00000000000000 execline: a small scripting language

Software
skarnet.org

execline

What is it?

execline is a (non-interactive) scripting language, like sh - but its syntax is quite different from a traditional shell syntax. The execlineb program is meant to be used as an interpreter for a text file; the other commands are essentially useful inside an execlineb script.

execline is as powerful as a shell: it features conditional loops, getopt-style option handling, filename globbing, and more. Meanwhile, its syntax is far more logic and predictable than the shell's syntax, and has no security issues.


Installation

Requirements

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

The following optional dependencies are also supported:

  • If you're using musl and want nsswitch-like functionality: nsss version 0.2.0.1 or later (build-time and boot-time)

Licensing

execline is free software. It is available under the ISC license.

Download

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

Special note

Before version 2.0.0.0, execline used the slashpackage convention by default. This is not the case anymore; nevertheless, the examples in this documentation still use #!/command/execlineb as their shebang line, and assume that the execline binaries are available in /command. Adapt them according to your installation: the shebang lines for your system might be something like #!/bin/execlineb, or #!/usr/bin/execlineb, or #!/usr/local/bin/execlineb, or something else entirely.


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. They exit 127 if they're trying to execute into a program and cannot find it, and 126 if they fail to execute into a program for another reason.

(Script parser / launcher)

(Process state control)

(Basic block management)

(Variable management)

(Loops)

(Positional parameters and options management)

(Miscellaneous)

Provided scripts: example .profile replacement

Fun stuff

Related resources

execline manual pages

execline discussion

  • execline is discussed on the skaware mailing-list.
execline-2.8.2.0/doc/loopwhilex.html000066400000000000000000000045251416030414000173010ustar00rootroot00000000000000 execline: the loopwhilex command

execline
Software
skarnet.org

The loopwhilex program

loopwhilex performs a conditional loop.

Interface

     loopwhilex [ -n ] [ -o okcodes | -x breakcodes ] prog...
  • loopwhilex runs prog... as a child process and waits for it to complete.
  • As long as prog exits zero, loopwhile runs it again.
  • loopwhilex then exits with an approximation of the last prog invocation's exit code.

Options

  • -o okcodes : okcodes must be a comma-separated list of exit codes. loopwhilex will keep looping as long as prog exits with one of the codes in okcodes.
  • -x breakcodes : like the previous option, but with inverted meaning - the listed exit codes are codes that will break the loop and exit, and the unlisted exit codes will keep the loop running.
  • -n : negate the test. This option is now redundant, and may disappear soon.

Notes

  • loopwhilex prog... is equivalent to loopwhilex -n -x 0 prog... and loopwhilex -o 0 prog...
  • Be careful: execline maintains no state, in particular it uses no real variables, and environment will be of no use here since every instance of prog... runs as a separate child process. To avoid being stuck in an infinite loop, prog... should modify some external state - for instance, the filesystem.
execline-2.8.2.0/doc/multidefine.html000066400000000000000000000055271416030414000174170ustar00rootroot00000000000000 execline: the multidefine command

execline
Software
skarnet.org

The multidefine program

multidefine splits a value and defines several variables at once, then executes another program.

Interface

In an execlineb script:

     multidefine [ -0 ] [ -r ] [ -C | -c ] [ -N | -n ] [ -d delim ] value { variables... } prog...
  • multidefine reads a block containing a list of variables. That block must not be empty.
  • multidefine splits value, and performs other operations depending on the given options.
  • multidefine performs parallel substitution on prog..., using all of the variables in the block as keys. The first word in the split value is assigned to the first variable, the second word is assigned to the second variable, and so on. Every variable is substituted with exactly one word.
  • If a variable is the empty word, then the word in the split value corresponding to its position is not substituted. So you can use empty words to pad the list of variables and only perform substition on the relevant fields.
  • multidefine then execs into the modified prog....

Options

  • -0 : if there are more variables in the block than there are words in the split value, the excess variables will be replaced with zero word. Without this option, the excess variables are replaced with the empty word.
  • -r : behave similarly to the "read" shell command. If there are more words in the split value than there are variables in the block, the last variable will be replaced with all the remaining words (and will be split). Without this option, the last variable is replaced with a single word, and the excess words are lost.
  • Other options are used to control the substitution mechanism. Note that the value is always split.
execline-2.8.2.0/doc/multisubstitute.html000066400000000000000000000065401416030414000203740ustar00rootroot00000000000000 execline: the multisubstitute command

execline
Software
skarnet.org

The multisubstitute program

multisubstitute performs several substitutions at once in its argv, then executes another program.

Interface

In an execlineb script:

     multisubstitute
     {
       [ define [ -N | -n ] [ -s ] [ -C | -c ] [ -d delim ] variable value ]
       [ importas [ -i | -D default ] [ -N | -n ] [ -s ] [ -C | -c ] [ -d delim ] variable envvar ]
       [ elglob [ -v ] [ -w ] [ -s ] [ -m ] [ -e ] [ -0 ] variable pattern ]
       [ elgetpositionals [ -P sharp ] ]
       [ multidefine value { variable... } ]
       ...
     }
     prog...
  • multisubstitute reads a block containing a series of substitution commands. It performs all those substitutions on prog... in parallel. Check the relevant documentation page to learn about the syntax of each substitution command.
  • multisubstitute then execs into the modified prog....

Options

  • If an importas directive was given with the -i option, and the looked up variable is undefined, multisubstitute will exit 100.

Rationale

Security

multisubstitute can be used to avoid unwanted serial substitutions. Consider the following script:

 #!/command/execlineb
 export A wrong
 define B ${A}
 importas A A
 echo ${B}

Running it will print wrong, because A is substituted after B. On the contrary, the following script:

 #!/command/execlineb
 export A wrong
 multisubstitute
 {
   define B ${A}
   importas A A
 }
 echo ${B}

will print ${A}, because A and B are substituted at the same time. Serial substitution may be what you want - but when in doubt, always perform parallel substitution.

Efficiency

Substitution is a costly mechanism: the whole argv is read three times and rewritten twice. Serial substitution multiplies the cost by the number of substitutions, whereas parallel substitution pays the price only once.

Credits

Paul Jarc first originated the idea of the multisubstitute command and a possible syntax.

execline-2.8.2.0/doc/pipeline.html000066400000000000000000000040721416030414000167110ustar00rootroot00000000000000 execline: the pipeline command

execline
Software
skarnet.org

The pipeline program

pipeline runs two commands with a pipe between them.

Interface

In an execlineb script:

     pipeline [ -d ] [ -r | -w ] { prog1... } prog2...
  • pipeline reads prog1... in a block and unquotes it.
  • It runs prog1... as a child process and execs into prog2..., with a pipe between prog1's stdout and prog2's stdin.
  • prog1's pid is available in prog2 as the ! environment variable.

Options

  • -d : run prog1... as a grandchild of pipeline. This is meant to prevent a zombie from hanging around if prog2... fails to wait for its children.
  • -r : make prog1... the writer and prog2... the reader. This is the default.
  • -w : make prog1... the reader and prog2... the writer.

Notes

  • You can easily create a chain of pipes: execlineb -Pc 'pipeline { a } pipeline { b } c' is roughly equivalent to sh -c 'exec a | b | c', except that shells usually run c as a child process like a and b, and exec has no effect.
execline-2.8.2.0/doc/piperw.html000066400000000000000000000020511416030414000164050ustar00rootroot00000000000000 execline: the piperw command

execline
Software
skarnet.org

The piperw program

piperw creates a pipe (an anonymous one), then executes a program.

Interface

     piperw fdr fdw prog...

piperw creates a pipe with descriptor fdw as the writing end and descriptor fdr as the reading end. It then execs into prog with its arguments.

execline-2.8.2.0/doc/posix-cd.html000066400000000000000000000047161416030414000166370ustar00rootroot00000000000000 execline: the posix-cd command

execline
Software
skarnet.org

The posix-cd program

posix-cd changes the current working directory to a given directory, then executes a program.

Interface

     posix-cd [ -L | -P ] dir prog...

posix-cd changes the current working directory to dir according to the POSIX specification for a cd external utility. Then, if prog... is not empty, it execs into it.

Notes

  • When execline has been configured with the --enable-pedantic-posix option, the cd command is a symbolic link to it. So scripts calling cd will use posix-cd. When this configuration option has not been given, cd is a symbolic link to execline-cd.
  • posix-cd fully conforms to the POSIX specification. When prog... is not empty, the behaviour of a cd utility is not specified by POSIX, so posix-cd extends the spec to be actually useful and usable in an execline program with the same interface as the regular execline cd command.
  • Nobody ever executes or needs the external version (i.e. not a shell builtin) of the POSIX cd command. Compared to execline's regular cd binary, execline-cd, posix-cd is uselessly bloated and slow. The only reason it exists is that some distributions refuse to package execline correctly unless it is strictly POSIX-compliant; the --enable-pedantic-posix configure option is there to satisfy their requirements.
execline-2.8.2.0/doc/posix-umask.html000066400000000000000000000053651416030414000173720ustar00rootroot00000000000000 execline: the posix-umask command

execline
Software
skarnet.org

The posix-umask program

posix-umask changes its file mode creation mask, then executes a program.

Interface

     posix-umask [ -S ] [ mask ] [ prog... ]

When called with no argument, posix-umask prints the value of the file mode creation mask of the invoking process, then exits 0.

When called with a mask argument, posix-umask changes its file mode creation mask; then, if prog... is not empty, it execs into it.

posix-umask interprets mask as specified by the POSIX specification for a umask external utility.

Notes

  • When execline has been configured with the --enable-pedantic-posix option, the umask command is a symbolic link to it. So scripts calling umask will use posix-umask. When this configuration option has not been given, umask is a symbolic link to execline-umask.
  • posix-umask fully conforms to the POSIX specification. When prog... is not empty, the behaviour of a umask utility is not specified by POSIX, so posix-umask extends the spec to be actually useful and usable in an execline program with the same interface as the regular execline umask command.
  • Nobody ever executes or needs the external version (i.e. not a shell builtin) of the POSIX umask command. Compared to execline's regular umask binary, execline-umask, posix-umask is uselessly bloated and slow. The only reason it exists is that some distributions refuse to package execline correctly unless it is strictly POSIX-compliant; the --enable-pedantic-posix configure option is there to satisfy their requirements.
execline-2.8.2.0/doc/quine-dam.txt000066400000000000000000000101551416030414000166360ustar00rootroot00000000000000#! /command/execlineb -P # Public Domain. # See comments below. # (Search for "HERE".) # define -sCd "\n" lns " ${p} ${bubble} is the end of the quine's data. ${p} They represent the following code, with various quotations: ${p} ${b} (backslash) is represented as ${d}${ob}b${cb} ${p} ${q} (double quote) is represented as ${d}${ob}q${cb} ${p} ${p} (sharp/pound/shibboleth/whatever) is represented as ${d}${ob}p${cb} ${p} ${ob} (open brace) is represented as ${d}${ob}ob${cb} ${p} ${cb} (closed brace) is represented as ${d}${ob}cb${cb} ${p} ${d} (dollar) is represented as ${d}${ob}d${cb} ${p} ${bubble} (the magic word) is represented as ${d}${ob}bubble${cb} ${p} (The point of the magic word is to allow the reader ${p} to conveniently skip over the large data section.) ${p} ${p} Now we have the quine's code! ${p} ${p} First, print the lines that come before the data. foreground ${ob} printf %s ${b}${p}${b}!${q} ${q} ${cb} foreground ${ob} printf %s${b}${b}n ${q}/command/execlineb -P${q} ${cb} foreground ${ob} printf %s${b}${b}n ${b}${p}${q} Public Domain.${q} ${cb} foreground ${ob} printf %s${b}${b}n ${b}${p}${q} See comments below.${q} ${cb} foreground ${ob} printf %s ${b}${p}${q} (Search for ${q} ${cb} foreground ${ob} printf %s${b}${b}n ${b}${q}${bubble}${b}${q}.) ${cb} foreground ${ob} printf %s${b}${b}n ${b}${p} ${cb} foreground ${ob} printf %s ${q}define -sCd ${b}${q}${b}${b}n${b}${q} lns ${b}${q}${q} ${cb} ${p} Next, print the data themselves, as data. for lin ${ob} ${d}${ob}lns${cb} ${cb} ${ob} multisubstitute ${ob} define b ${d}${ob}b${cb} define q ${d}${ob}q${cb} define p ${d}${ob}p${cb} define ob ${d}${ob}ob${cb} define cb ${d}${ob}cb${cb} define d ${d}${ob}d${cb} define bubble ${d}${ob}bubble${cb} define intron ${d}${ob}intron${cb} ${cb} printf ${b}${b}n%s ${d}${ob}lin${cb} ${cb} foreground ${ob} printf %s${b}${b}n ${b}${q} ${cb} ${p} Finally, use the data to print the code! for lin ${ob} ${d}${ob}lns${cb} ${cb} ${ob} multisubstitute ${ob} define b ${b}${b} define q ${b}${q} define p ${b}${p} define ob ${b}${ob} define cb ${b}${cb} define d ${d} define bubble ${bubble} define intron ${q}${intron}${q} ${cb} printf %s${b}${b}n ${d}${ob}lin${cb} ${cb} ${p} That's all, folks! - Well, that wasn't so hard, was it? ${p} (This quine was written by - see ${p} ${p} for more information on quines and how to write them.)" # HERE is the end of the quine's data. # They represent the following code, with various quotations: # \ (backslash) is represented as ${b} # " (double quote) is represented as ${q} # # (sharp/pound/shibboleth/whatever) is represented as ${p} # { (open brace) is represented as ${ob} # } (closed brace) is represented as ${cb} # $ (dollar) is represented as ${d} # HERE (the magic word) is represented as ${bubble} # (The point of the magic word is to allow the reader # to conveniently skip over the large data section.) # # Now we have the quine's code! # # First, print the lines that come before the data. foreground { printf %s \#\!" " } foreground { printf %s\\n "/command/execlineb -P" } foreground { printf %s\\n \#" Public Domain." } foreground { printf %s\\n \#" See comments below." } foreground { printf %s \#" (Search for " } foreground { printf %s\\n \"HERE\".) } foreground { printf %s\\n \# } foreground { printf %s "define -sCd \"\\n\" lns \"" } # Next, print the data themselves, as data. for lin { ${lns} } { multisubstitute { define b ${b} define q ${q} define p ${p} define ob ${ob} define cb ${cb} define d ${d} define bubble ${bubble} define intron ${intron} } printf \\n%s ${lin} } foreground { printf %s\\n \" } # Finally, use the data to print the code! for lin { ${lns} } { multisubstitute { define b \\ define q \" define p \# define ob \{ define cb \} define d $ define bubble HERE define intron "NOTICE HOW THIS SENTENCE APPEARS ONLY ONCE IN THIS QUINE?" } printf %s\\n ${lin} } # That's all, folks! - Well, that wasn't so hard, was it? # (This quine was written by - see # # for more information on quines and how to write them.) execline-2.8.2.0/doc/quine-jriou.txt000066400000000000000000000022441416030414000172250ustar00rootroot00000000000000#!/command/execlineb define A "#!/command/execlineb" define B "fine G $ foreground { echo ${C} } echo -n foreground ${D} define C ${E}${C}${R}foreground ${D} echo ${G}${D}A${H} ${H}${R}foreground ${D} echo define A ${G}${D}C${H}${G}${D}A${H}${G}${D}C${H} ${H}${R}echo -n define B ${G}${D}C${H} ${H}${R}foreground ${D} echo -n ${G}${D}B${H} ${H}${R}foreground ${D} multisubstitute ${D} define C ${E}${C} define D ${E}${D}${R}define E ${E}${E}${R}define H ${E}${H} define R ${C}${R}${C} ${H} de } echo ${B}" foreground { define C \" foreground { echo ${A} } foreground { echo define A ${C}${A}${C} } echo -n define B ${C} } foreground { echo -n ${B} } foreground { multisubstitute { define C \" define D \{ define E \\ define H \} define R " " } define G $ foreground { echo ${C} } echo -n foreground ${D} define C ${E}${C}${R}foreground ${D} echo ${G}${D}A${H} ${H}${R}foreground ${D} echo define A ${G}${D}C${H}${G}${D}A${H}${G}${D}C${H} ${H}${R}echo -n define B ${G}${D}C${H} ${H}${R}foreground ${D} echo -n ${G}${D}B${H} ${H}${R}foreground ${D} multisubstitute ${D} define C ${E}${C} define D ${E}${D}${R}define E ${E}${E}${R}define H ${E}${H} define R ${C}${R}${C} ${H} de } echo ${B} execline-2.8.2.0/doc/quine-prj-2.txt000066400000000000000000000003271416030414000170270ustar00rootroot00000000000000#!/command/execlineb define e "#!/command/execlineb define e ${q}${E}${q} multisubstitute { define q ${b}${q} define b ${b}${b} define E $e } echo $e" multisubstitute { define q \" define b \\ define E $e } echo $e execline-2.8.2.0/doc/quine-prj-3.txt000066400000000000000000000003171416030414000170270ustar00rootroot00000000000000#!/command/execlineb -P define e "#!/command/execlineb -P define e ${q}${E}${q} export E $e define q ${b}${q} define b ${b}${b} importas E E echo $e" export E $e define q \" define b \\ importas E E echo $e execline-2.8.2.0/doc/quine-prj.txt000066400000000000000000000003011416030414000166600ustar00rootroot00000000000000#!/command/execlineb define e "#!/command/execlineb define e $q${E}${q} env e=$e define q ${b}${q} define b ${b}${b} importas E e echo $e" env e=$e define q \" define b \\ importas E e echo $e execline-2.8.2.0/doc/redirfd.html000066400000000000000000000071151416030414000165240ustar00rootroot00000000000000 execline: the redirfd command

execline
Software
skarnet.org

The redirfd program

redirfd redirects a given file descriptor to a file, then executes a program.

Interface

     redirfd [ -r | -w | -u | -a | -x ] [ -n ] [ -b ] fd file prog...

redirfd redirects the file descriptor number fd to file, then execs into prog....

Options

One and only one of the -r, -w, -u, -a, or -x options must be given; the -n and -b options may be added in any case.

  • -r : open file for reading.
  • -w : open file for writing, truncating it if it already exists.
  • -u : open file for reading and writing.
  • -a : open file for appending, creating it if it doesn't exist.
  • -x : open file for writing, creating it, failing if it already exists.
  • -n : open file in non-blocking mode.
  • -b : change mode of file after opening it: to non-blocking mode if the -n option was not given, to blocking mode if it was.

Notes

  • redirfd -r n file prog... is roughly equivalent to sh -c 'exec prog... n<file'
  • redirfd -w n file prog... is roughly equivalent to sh -c 'exec prog... n>file'
  • redirfd -u n file prog... is roughly equivalent to sh -c 'exec prog... n<>file'
  • redirfd -a n file prog... is roughly equivalent to sh -c 'exec prog... n>>file'
  • redirfd -x n file prog... has no portable shell equivalent.

Special fifo handling

The -n and -b options are especially useful with named pipes.

  • Opening a fifo for reading, blocking if there is no writer: redirfd -r n fifo prog...
  • Opening a fifo for reading, with instant success even if there is no writer, and blocking at the first attempt to read from it: redirfd -r -nb n fifo prog...
  • Opening a fifo for writing, blocking if there is no reader: redirfd -w n fifo prog...
  • Opening a fifo for writing, with instant success even if there is no reader: redirfd -w -nb n fifo prog.... Warning: the first attempt to write to the fifo will raise a SIGPIPE if there is still no reader at that time. The named pipe semantics normally do not allow a fifo to be open for writing without a reading end, and you should know what you are doing if you're using redirfd this way.
execline-2.8.2.0/doc/runblock.html000066400000000000000000000053501416030414000167230ustar00rootroot00000000000000 execline: the runblock program

execline
Software
www.skarnet.org

The runblock program

runblock's purpose is to help you write execline commands in the execline language. It can only be used inside an execline script. If the script has been given blocks as arguments, runblock allows you to execute one of the blocks individually. It also allows you to give those blocks as a set of arguments to another command.

Interface

     runblock [ -P ] [ -n argshift ] [ -r ] n cmd...
  • runblock skips the first argshift positional parameters. It does that to allow you to design commands that take simple arguments and blocks.
  • Then runblock looks for and parses blocks in the positional parameters.
  • If the -r option is present: runblock skips n blocks and execs into the remaining arguments.
  • Else it skips n-1 blocks and execs into the nth one.
  • If cmd... is not empty, then instead of directly executing the block or the remainder, runblock appends the selected set of arguments to the cmd... command line.
  • Normally runblock pops its environment frame before executing. If the -P option has been given, it does not pop.
  • Of course, if the block structure doesn't match, runblock exits 100 with an error message.

Example: implementing the ifelse command

Suppose that we want to implement the ifelse command as an execline script, using the ifte command. runblock allows us to do it in a simple way:

 #!/command/execlineb
 ifte { runblock 2 } { runblock -r 2 } runblock 1

That's it.

Credits

The runblock idea, as well as the ifelse idea, comes from Paul Jarc.

execline-2.8.2.0/doc/shift.html000066400000000000000000000046251416030414000162250ustar00rootroot00000000000000 execline: the shift program

execline
Software
www.skarnet.org

The shift program

shift shifts the positional parameters of an execline script.

Interface

     shift [ -n argn ] [ -b blockn ] prog...
  • shift shifts argn positional parameters, then blockn blocks. It then execs prog....
  • By default, argn and blockn are both zero; but if neither the -n nor the -b option is given, then argn is 1 and blockn is 0.

Details

  • shift reads the number of "positional parameters" in the # environment variable. Let n be that number.
  • If the # environment variable is not set or does not contain a valid number, or one of the 0, 1, ..., n environment variables is not set, shift exits 100 with an error message.
  • shift calculates a shift value m, corresponding to argn arguments followed by enough arguments to make blockn blocks.
  • It shifts the positional parameters m times: the value of the m+1 variable becomes the value of the 1 variable, m+2 becomes 2 and so on, and # is set to n-m (floored at zero).
  • shift then execs into prog....

Notes

  • shift is a standard shell builtin. Be careful if you want to use it outside of an execline script.
  • The -b option is only useful to implement execline commands in the execline language. You shouldn't normally have to use it.
execline-2.8.2.0/doc/trap.html000066400000000000000000000077311416030414000160570ustar00rootroot00000000000000 execline: the trap command

execline
Software
skarnet.org

The trap program

trap traps signals and runs a variety of commands according to the signals it catches.

Interface

In an execlineb script:

     trap [ -x ]
     {
       [ SIGTERM { progsigterm... } ]
       [ quit { progsigquit... } ]
       [ 1 { progsighup... } ]
       [ default { progdefault... } ]
       ...
     }
     prog...
  • trap reads a sequence of directives in a block. It expects at least one directive.
  • Each directive is a keyword followed by a block.
  • The keyword can be the special word timeout, a signal name (case-insensitive, with or without the SIG prefix), or a signal number. The block following it is a command line to run when the specified event occurs.
  • trap sets traps for the various directives it reads. A trap for SIGTERM will be triggered when the trap program receives a SIGTERM. A default trap will be used for any signal that is not caught by another trap.
  • It spawns a child executing prog....
  • It sets the ! environment variable to the pid of the prog... process, and the SIGNAL environment variable to the trapped signal.
  • Whenever it catches a signal, it spawns the program described in the corresponding directive. It will not spawn a program for the same signal twice: if the first subprocess is still active when another instance of the same signal arrives, this second instance is ignored.
  • When prog... exits, trap exits with an approximation of the same exit code.

Options

  • -x : forward signals. If this option is given, any signal that trap receives and that is not explicitly trapped will be sent to prog. By default, trap does not forward any signals, and does not ignore them either - for instance a SIGTERM, unless caught by a SIGTERM directive, will kill the trap process (and leave prog running). With the -x option, without a SIGTERM directive, a SIGTERM will still be caught by trap, that will send it to prog. Note that if a default directive is present, this option does nothing.

Notes

  • Programs defined in command line directives can start with importas ! ! to retrieve the pid of prog in $!. If they need the signal number, which can be the case in default directives, they can for instance use multisubstitute { importas ! ! importas SIGNAL SIGNAL } to get both $! and $SIGNAL substitutions.
  • The -x option is basically a shortcut for a default { multisubstitute { importas ! ! importas SIGNAL SIGNAL } kill -$SIGNAL $! } directive.
  • trap is a standard shell builtin, with similar functionality. It is more idiomatic, and probably more efficient, to use that builtin in shell scripts, and to only use the trap program in execline scripts.
execline-2.8.2.0/doc/tryexec.html000066400000000000000000000036241416030414000165710ustar00rootroot00000000000000 execline: the tryexec command

execline
Software
skarnet.org

The tryexec program

tryexec executes into a command line, with a fallback.

Interface

In an execlineb script:

     tryexec [ -n ] [ -c ] [ -l ] [ -a argv0 ] { prog1... } prog2...
  • tryexec reads prog1... in a block. It then executes into it, completely forgetting prog2...
  • If for some reason the execve() fails - for instance, a non-executable prog1 - then tryexec executes into prog2... instead.

Options

  • -n : reverse prog1... and prog2...'s role. The latter becomes the main execution path and the former becomes the fallback.

The -c, -l and -a options have the same semantics as with the exec program.

Notes

  • tryexec prog1... "" prog2... would be equivalent to sh -c 'exec prog1... || exec prog2...', if such a shell construct existed. Unfortunately, the shell language does not offer that functionality.
execline-2.8.2.0/doc/unexport.html000066400000000000000000000022721416030414000167700ustar00rootroot00000000000000 execline: the unexport command

execline
Software
skarnet.org

The unexport program

unexport removes a variable from the environment, then executes a program.

Interface

     unexport var prog...

unexport removes the var variable from the environment, then execs into prog with its arguments.

Notes

  • Unsetting var is quite different from setting it to an empty value. Shell scripts usually won't make the distinction; execline does.
execline-2.8.2.0/doc/upgrade.html000066400000000000000000000234511416030414000165350ustar00rootroot00000000000000 execline: how to upgrade

execline
Software
skarnet.org

What has changed in execline

in 2.8.2.0

  • skalibs dependency bumped to 2.11.1.0.
  • nsss optional dependency bumped to 0.2.0.1.
  • New options to case.

in 2.8.1.0

  • skalibs dependency bumped to 2.11.0.0.
  • New binary: case.

in 2.8.0.1

  • skalibs dependency bumped to 2.10.0.3.

in 2.8.0.0

  • skalibs dependency bumped to 2.10.0.2.
  • backtick options have changed slightly, and now propagates subprocess failure by default.

in 2.7.0.1

  • skalibs dependency bumped to 2.10.0.1.

in 2.7.0.0

  • skalibs dependency bumped to 2.10.0.0.
  • nsss optional dependency bumped to 0.1.0.0.
  • forstdin now exits 1 on immediate EOF, and only splits on newlines by default.
  • forbacktickx, which is a wrapper around forstdin, gets the same changes.
  • Input-processing binaries (not substitution binaries!) now chomp by default.
  • New -N option to deactivate chomping.
  • New default directive to trap, replacing the timeout one, which was ill-suited to that program.

in 2.6.1.1

  • skalibs dependency bumped to 2.9.3.0.

in 2.6.1.0

  • The envfile format has changed. It is now more expressive and largely compatible with systemd's EnvironmentFile format. The new format is a superset of the old one, so old envfiles should still be understood by the new binary.

in 2.6.0.2

  • No functional changes

in 2.6.0.1

  • skalibs dependency bumped to 2.9.2.1.

in 2.6.0.0

  • skalibs dependency bumped to 2.9.2.0.
  • dollarat now has its -0 and -d priority unified. (Rightmost priority.)
  • runblock now accepts a command line prefix, given as runblock's own command line.
  • New binary: posix-umask.
  • cd has been renamed execline-cd.
  • umask has been renamed execline-umask.
  • At installation time, cd and umask symbolic links are created, pointing to either the posix- or execline- -prefixed version of the commands, depending on whether the --enable-pedantic-posix option was given or not.

in 2.5.3.0

  • skalibs dependency bumped to 2.9.1.0.
  • --enable-pedantic-posix configure option added.
  • posix-cd binary added.
  • wait binary made POSIX-compliant.

in 2.5.2.0

  • skalibs dependency bumped to 2.9.0.0.

in 2.5.1.0

  • skalibs dependency bumped to 2.8.0.0.
  • New command: envfile.
  • Everything now builds as PIC by default no matter the toolchain's settings. Use the --disable-all-pic configure option to build executables and static libraries as non-PIC.

in 2.5.0.1

  • skalibs dependency bumped to 2.7.0.0
  • Optional nsss support added.

in 2.5.0.0

  • skalibs dependency bumped to 2.6.4.0
  • The import command has been removed.

in 2.3.0.4

  • skalibs dependency bumped to 2.6.2.0

in 2.3.0.3

  • skalibs dependency bumped to 2.6.0.1

in 2.3.0.2

  • skalibs dependency bumped to 2.6.0.0
  • Commands now exit 127 (not found) or 126 (other error) if they cannot exec into a program they're supposed to.
  • The import command will likely disappear very soon. Please switch to importas as soon as possible!

in 2.3.0.1

  • skalibs dependency bumped to 2.5.1.0

in 2.3.0.0

  • skalibs dependency bumped to 2.5.0.0
  • import is now marked as obsolescent. It is recommanded to use the importas command instead.

in 2.2.0.0

in 2.1.5.0

  • skalibs dependency bumped to 2.3.10.0

in 2.1.4.5

  • skalibs dependency bumped to 2.3.8.3

in 2.1.4.4

  • No functional changes

in 2.1.4.3

  • No functional changes

in 2.1.4.2

  • GNU make dependency pushed back to 3.81
  • skalibs dependency bumped to 2.3.8.0

in 2.1.4.1

  • skalibs dependency bumped to 2.3.7.1

in 2.1.4.0

  • New EXECLINE_BLOCK_END_STRING and EXECLINE_BLOCK_QUOTE_STRING macros
  • New command: withstdinas. It's a simplification of backtick, which is now implemented as a combination of pipeline and withstdinas.
  • Other new command: getcwd.

in 2.1.3.1

  • skalibs dependency bumped to 2.3.6.1

in 2.1.3.0

  • skalibs dependency bumped to 2.3.6.0
  • New configure option: --shebangdir for script creation automation.

in 2.1.2.2

  • skalibs dependency bumped to 2.3.5.1

in 2.1.2.1

  • Bugfix release, no changes

in 2.1.2.0

  • skalibs dependency bumped to 2.3.4.0
  • new command: trap

in 2.1.1.1

  • skalibs dependency bumped to 2.3.3.0
  • execlineb parser made into a library function, for easier inclusion in other programs

in 2.1.1.0

in 2.1.0.0

  • skalibs dependency bumped to 2.3.1.0
  • foreground now sets the ? environment variable to 256 plus the signal number when its block was killed by a signal (in previous releases it used 126).
  • New rules for exit codes of forx, loopwhilex, forbacktickx
  • New -e option to loopwhilex, deprecating the -x option.

in 2.0.2.1

  • skalibs dependency bumped to 2.3.0.0

in 2.0.2.0

  • skalibs dependency bumped to 2.2.1.0
  • New command: fdswap
  • New -D option to backtick

in 2.0.1.1

  • skalibs dependency bumped to 2.2.0.0
  • Parallel build fix

in 2.0.1.0

  • skalibs dependency bumped to 2.1.0.0
  • -u option added to import and importas

in 2.0.0.0

  • The build system has completely changed. It is now a standard ./configure && make && sudo make install build system. See the enclosed INSTALL file for details.
  • slashpackage is not activated by default.
  • shared libraries are neither built nor used by default.
  • skalibs dependency bumped to 2.0.0.0
  • The obsolete -E option to backtick, forx and forbacktickx is not supported anymore.
  • multisubstitute does not support the "backtick" directive anymore.
execline-2.8.2.0/doc/wait.html000066400000000000000000000046371416030414000160570ustar00rootroot00000000000000 execline: the wait command

execline
Software
skarnet.org

The wait program

wait waits for a set of children, then executes a program.

Interface

In an execlineb script:

     wait [ -I | -i ] [ -r | -t timeout ] { [ pids... ] } prog...
  • wait reads a list of pids in a (possibly empty) block, and unquotes it.
  • wait waits for every child whose pid is listed in pids.... If pids... is an empty list, it waits for every child process it has.
  • wait then execs into prog....

Options

  • -r : equivalent to -t 0. Do not pause: only reap processes that are already dead when wait is invoked.
  • -t timeout : wait for a maximum of timeout milliseconds. If there still are living processes among pids... (or among wait's children if pids... is an empty list), after timeout milliseconds, they will not be reaped.
  • -I : loose. If wait times out while waiting for children to die, it will still exec into prog.... This is the default.
  • -i : strict. If wait times out, it will print an error message and exit 1.

Notes

  • For POSIX compatibility, wait also works when it cannot find a block. In that case, all its command line is interpreted as pids... arguments and it does not execute into a program. Instead, it exits with a conforming exit code.
execline-2.8.2.0/doc/withstdinas.html000066400000000000000000000051571416030414000174520ustar00rootroot00000000000000 execline: the withstdinas command

execline
Software
skarnet.org

The withstdinas program

withstdinas reads the entirety of its standard input in an environment variable, and runs another program with that additional environment variable.

Interface

In an execlineb script:

     withstdinas [ -i | -I | -D default ] [ -N | -n ] [ -E | -e ] variable prog...
  • withstdinas reads its stdin until EOF.
  • It then execs into prog..., with variable added to the environment; the value of variable is what was read on stdin.

Options

  • -N : do not chomp an ending newline off stdin.
  • -n : chomp an ending newline off stdin. This is the default.
  • -e : no autoimport. This is the default.
  • -E : autoimport. Instead of exec'ing into prog..., exec into importas -ui variable variable prog.... This substitutes variable into the command line instead of putting it into the environment.

The other options tell withstdinas what to do if its input is not suitable as the contents of an environment variable, i.e. it contains a null character:

  • -i : withstdinas exits 1.
  • -I : variable is removed from the environment, and execution proceeds.
  • -D default : the value of variable is set to default, and execution proceeds.
  • neither of those options: the value of variable is set to whatever the start of the input is, up to the first null character; and execution proceeds.

Notes

  • You can start prog... with "importas -u variable variable" to perform variable substitution.
execline-2.8.2.0/examples/000077500000000000000000000000001416030414000152645ustar00rootroot00000000000000execline-2.8.2.0/examples/etc/000077500000000000000000000000001416030414000160375ustar00rootroot00000000000000execline-2.8.2.0/examples/etc/env-startup/000077500000000000000000000000001416030414000203275ustar00rootroot00000000000000execline-2.8.2.0/examples/etc/env-startup/EDITOR000066400000000000000000000000031416030414000212310ustar00rootroot00000000000000vi execline-2.8.2.0/examples/etc/env-startup/GZIP000066400000000000000000000000041416030414000210150ustar00rootroot00000000000000-r9 execline-2.8.2.0/examples/etc/env-startup/LESS000066400000000000000000000000221416030414000210120ustar00rootroot00000000000000-fMqrIX -b16 -z-2 execline-2.8.2.0/examples/etc/env-startup/LESSCHARSET000066400000000000000000000000051416030414000220250ustar00rootroot00000000000000utf8 execline-2.8.2.0/examples/etc/env-startup/MAIL000066400000000000000000000000001416030414000207620ustar00rootroot00000000000000execline-2.8.2.0/examples/etc/env-startup/PAGER000066400000000000000000000000051416030414000211030ustar00rootroot00000000000000less execline-2.8.2.0/examples/etc/env-startup/PATH000066400000000000000000000000351416030414000210040ustar00rootroot00000000000000/usr/local/bin:/usr/bin:/bin execline-2.8.2.0/examples/etc/env-startup/SHELL000066400000000000000000000000241416030414000211150ustar00rootroot00000000000000/etc/execline-shell execline-2.8.2.0/examples/etc/execline-shell000077500000000000000000000005541416030414000206720ustar00rootroot00000000000000#!/bin/execlineb -S0 backtick -n defaulthome { if -nt { backtick -n defaultuser { id -un } importas -u defaultuser defaultuser importas -D $defaultuser USER USER redirfd -w 2 /dev/null homeof ${USER} } s6-echo / } importas -u defaulthome defaulthome importas -D $defaulthome HOME HOME tryexec { ${HOME}/.execline-shell $@ } /bin/sh $@ execline-2.8.2.0/examples/etc/execline-startup000077500000000000000000000004271416030414000212640ustar00rootroot00000000000000#!/bin/execlineb -S0 /bin/multisubstitute { importas -i HOME HOME importas -i LOGNAME LOGNAME } /bin/export USER ${LOGNAME} /bin/s6-envdir /etc/env-startup /bin/fdblock 0 /bin/fdblock 1 /bin/fdblock 2 /bin/tryexec { ${HOME}/.execline-loginshell $@ } /etc/execline-shell $@ execline-2.8.2.0/package/000077500000000000000000000000001416030414000150415ustar00rootroot00000000000000execline-2.8.2.0/package/deps-build000066400000000000000000000000631416030414000170130ustar00rootroot00000000000000/package/prog/skalibs /package/admin/nsss $usensss execline-2.8.2.0/package/deps.mak000066400000000000000000000345231416030414000164750ustar00rootroot00000000000000# # This file has been generated by tools/gen-deps.sh # src/execline/background.o src/execline/background.lo: src/execline/background.c src/include/execline/execline.h src/execline/backtick.o src/execline/backtick.lo: src/execline/backtick.c src/include/execline/execline.h src/execline/case.o src/execline/case.lo: src/execline/case.c src/include/execline/execline.h src/execline/define.o src/execline/define.lo: src/execline/define.c src/include-local/exlsn.h src/execline/dollarat.o src/execline/dollarat.lo: src/execline/dollarat.c src/execline/elgetopt.o src/execline/elgetopt.lo: src/execline/elgetopt.c src/include/execline/execline.h src/execline/elgetpositionals.o src/execline/elgetpositionals.lo: src/execline/elgetpositionals.c src/include-local/exlsn.h src/execline/elglob.o src/execline/elglob.lo: src/execline/elglob.c src/include-local/exlsn.h src/execline/emptyenv.o src/execline/emptyenv.lo: src/execline/emptyenv.c src/include/execline/execline.h src/execline/envfile.o src/execline/envfile.lo: src/execline/envfile.c src/execline/exec.o src/execline/exec.lo: src/execline/exec.c src/execline/execline-cd.o src/execline/execline-cd.lo: src/execline/execline-cd.c src/execline/execline-umask.o src/execline/execline-umask.lo: src/execline/execline-umask.c src/execline/execlineb.o src/execline/execlineb.lo: src/execline/execlineb.c src/include/execline/execline.h src/include-local/exlsn.h src/execline/exit.o src/execline/exit.lo: src/execline/exit.c src/execline/export.o src/execline/export.lo: src/execline/export.c src/execline/fdblock.o src/execline/fdblock.lo: src/execline/fdblock.c src/execline/fdclose.o src/execline/fdclose.lo: src/execline/fdclose.c src/execline/fdmove.o src/execline/fdmove.lo: src/execline/fdmove.c src/execline/fdreserve.o src/execline/fdreserve.lo: src/execline/fdreserve.c src/execline/fdswap.o src/execline/fdswap.lo: src/execline/fdswap.c src/execline/forbacktickx.o src/execline/forbacktickx.lo: src/execline/forbacktickx.c src/include/execline/config.h src/include/execline/execline.h src/execline/foreground.o src/execline/foreground.lo: src/execline/foreground.c src/include/execline/execline.h src/execline/forstdin.o src/execline/forstdin.lo: src/execline/forstdin.c src/include/execline/execline.h src/execline/forx.o src/execline/forx.lo: src/execline/forx.c src/include/execline/config.h src/include/execline/execline.h src/execline/getcwd.o src/execline/getcwd.lo: src/execline/getcwd.c src/include/execline/execline.h src/execline/getpid.o src/execline/getpid.lo: src/execline/getpid.c src/include/execline/execline.h src/execline/heredoc.o src/execline/heredoc.lo: src/execline/heredoc.c src/execline/homeof.o src/execline/homeof.lo: src/execline/homeof.c src/execline/if.o src/execline/if.lo: src/execline/if.c src/include/execline/execline.h src/execline/ifelse.o src/execline/ifelse.lo: src/execline/ifelse.c src/include/execline/execline.h src/execline/ifte.o src/execline/ifte.lo: src/execline/ifte.c src/include/execline/execline.h src/execline/ifthenelse.o src/execline/ifthenelse.lo: src/execline/ifthenelse.c src/include/execline/execline.h src/execline/importas.o src/execline/importas.lo: src/execline/importas.c src/include-local/exlsn.h src/execline/loopwhilex.o src/execline/loopwhilex.lo: src/execline/loopwhilex.c src/include/execline/execline.h src/execline/multidefine.o src/execline/multidefine.lo: src/execline/multidefine.c src/include-local/exlsn.h src/execline/multisubstitute.o src/execline/multisubstitute.lo: src/execline/multisubstitute.c src/include/execline/execline.h src/include-local/exlsn.h src/execline/pipeline.o src/execline/pipeline.lo: src/execline/pipeline.c src/include/execline/execline.h src/execline/piperw.o src/execline/piperw.lo: src/execline/piperw.c src/execline/redirfd.o src/execline/redirfd.lo: src/execline/redirfd.c src/execline/runblock.o src/execline/runblock.lo: src/execline/runblock.c src/include/execline/execline.h src/execline/shift.o src/execline/shift.lo: src/execline/shift.c src/include/execline/execline.h src/execline/trap.o src/execline/trap.lo: src/execline/trap.c src/include/execline/execline.h src/execline/tryexec.o src/execline/tryexec.lo: src/execline/tryexec.c src/include/execline/execline.h src/execline/unexport.o src/execline/unexport.lo: src/execline/unexport.c src/execline/wait.o src/execline/wait.lo: src/execline/wait.c src/include/execline/config.h src/include/execline/execline.h src/execline/withstdinas.o src/execline/withstdinas.lo: src/execline/withstdinas.c src/include/execline/execline.h src/libexecline/el_execsequence.o src/libexecline/el_execsequence.lo: src/libexecline/el_execsequence.c src/include/execline/execline.h src/libexecline/el_getstrict.o src/libexecline/el_getstrict.lo: src/libexecline/el_getstrict.c src/include/execline/execline.h src/libexecline/el_modif_and_exec.o src/libexecline/el_modif_and_exec.lo: src/libexecline/el_modif_and_exec.c src/include/execline/config.h src/include/execline/execline.h src/libexecline/el_modif_and_spawn.o src/libexecline/el_modif_and_spawn.lo: src/libexecline/el_modif_and_spawn.c src/include/execline/config.h src/include/execline/execline.h src/libexecline/el_parse.o src/libexecline/el_parse.lo: src/libexecline/el_parse.c src/include/execline/execline.h src/libexecline/el_parse_from_buffer.o src/libexecline/el_parse_from_buffer.lo: src/libexecline/el_parse_from_buffer.c src/include/execline/execline.h src/libexecline/el_parse_from_string.o src/libexecline/el_parse_from_string.lo: src/libexecline/el_parse_from_string.c src/include/execline/execline.h src/libexecline/el_popenv.o src/libexecline/el_popenv.lo: src/libexecline/el_popenv.c src/include/execline/execline.h src/libexecline/el_pushenv.o src/libexecline/el_pushenv.lo: src/libexecline/el_pushenv.c src/include/execline/execline.h src/libexecline/el_semicolon.o src/libexecline/el_semicolon.lo: src/libexecline/el_semicolon.c src/include/execline/execline.h src/libexecline/el_spawn0.o src/libexecline/el_spawn0.lo: src/libexecline/el_spawn0.c src/include/execline/config.h src/include/execline/execline.h src/libexecline/el_spawn1.o src/libexecline/el_spawn1.lo: src/libexecline/el_spawn1.c src/include/execline/config.h src/include/execline/execline.h src/libexecline/el_substandrun.o src/libexecline/el_substandrun.lo: src/libexecline/el_substandrun.c src/include-local/exlsn.h src/libexecline/el_substandrun_str.o src/libexecline/el_substandrun_str.lo: src/libexecline/el_substandrun_str.c src/include/execline/execline.h src/include-local/exlsn.h src/libexecline/el_substitute.o src/libexecline/el_substitute.lo: src/libexecline/el_substitute.c src/include/execline/execline.h src/libexecline/el_transform.o src/libexecline/el_transform.lo: src/libexecline/el_transform.c src/include/execline/execline.h src/libexecline/el_vardupl.o src/libexecline/el_vardupl.lo: src/libexecline/el_vardupl.c src/include/execline/execline.h src/libexecline/exlp.o src/libexecline/exlp.lo: src/libexecline/exlp.c src/include/execline/execline.h src/include-local/exlsn.h src/libexecline/exlsn_define.o src/libexecline/exlsn_define.lo: src/libexecline/exlsn_define.c src/include/execline/execline.h src/include-local/exlsn.h src/libexecline/exlsn_elglob.o src/libexecline/exlsn_elglob.lo: src/libexecline/exlsn_elglob.c src/include/execline/execline.h src/include-local/exlsn.h src/libexecline/exlsn_exlp.o src/libexecline/exlsn_exlp.lo: src/libexecline/exlsn_exlp.c src/include-local/exlsn.h src/libexecline/exlsn_free.o src/libexecline/exlsn_free.lo: src/libexecline/exlsn_free.c src/include-local/exlsn.h src/libexecline/exlsn_importas.o src/libexecline/exlsn_importas.lo: src/libexecline/exlsn_importas.c src/include/execline/execline.h src/include-local/exlsn.h src/libexecline/exlsn_main.o src/libexecline/exlsn_main.lo: src/libexecline/exlsn_main.c src/include/execline/execline.h src/include-local/exlsn.h src/libexecline/exlsn_multidefine.o src/libexecline/exlsn_multidefine.lo: src/libexecline/exlsn_multidefine.c src/include/execline/execline.h src/include-local/exlsn.h src/posix/posix-cd.o src/posix/posix-cd.lo: src/posix/posix-cd.c src/posix/posix-umask.o src/posix/posix-umask.lo: src/posix/posix-umask.c background: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} background: src/execline/background.o ${LIBEXECLINE} backtick: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} backtick: src/execline/backtick.o ${LIBEXECLINE} case: EXTRA_LIBS := -lskarnet case: src/execline/case.o ${LIBEXECLINE} define: EXTRA_LIBS := -lskarnet define: src/execline/define.o ${LIBEXECLINE} dollarat: EXTRA_LIBS := -lskarnet dollarat: src/execline/dollarat.o elgetopt: EXTRA_LIBS := -lskarnet elgetopt: src/execline/elgetopt.o ${LIBEXECLINE} elgetpositionals: EXTRA_LIBS := -lskarnet elgetpositionals: src/execline/elgetpositionals.o ${LIBEXECLINE} elglob: EXTRA_LIBS := -lskarnet elglob: src/execline/elglob.o ${LIBEXECLINE} emptyenv: EXTRA_LIBS := -lskarnet emptyenv: src/execline/emptyenv.o ${LIBEXECLINE} envfile: EXTRA_LIBS := -lskarnet envfile: src/execline/envfile.o exec: EXTRA_LIBS := -lskarnet exec: src/execline/exec.o execline-cd: EXTRA_LIBS := -lskarnet execline-cd: src/execline/execline-cd.o execline-umask: EXTRA_LIBS := -lskarnet execline-umask: src/execline/execline-umask.o execlineb: EXTRA_LIBS := -lskarnet execlineb: src/execline/execlineb.o ${LIBEXECLINE} exit: EXTRA_LIBS := -lskarnet exit: src/execline/exit.o export: EXTRA_LIBS := -lskarnet export: src/execline/export.o fdblock: EXTRA_LIBS := -lskarnet fdblock: src/execline/fdblock.o fdclose: EXTRA_LIBS := -lskarnet fdclose: src/execline/fdclose.o fdmove: EXTRA_LIBS := -lskarnet fdmove: src/execline/fdmove.o fdreserve: EXTRA_LIBS := -lskarnet fdreserve: src/execline/fdreserve.o fdswap: EXTRA_LIBS := -lskarnet fdswap: src/execline/fdswap.o forbacktickx: EXTRA_LIBS := -lskarnet forbacktickx: src/execline/forbacktickx.o foreground: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} foreground: src/execline/foreground.o ${LIBEXECLINE} forstdin: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} forstdin: src/execline/forstdin.o ${LIBEXECLINE} forx: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} forx: src/execline/forx.o ${LIBEXECLINE} getcwd: EXTRA_LIBS := -lskarnet getcwd: src/execline/getcwd.o ${LIBEXECLINE} getpid: EXTRA_LIBS := -lskarnet getpid: src/execline/getpid.o ${LIBEXECLINE} heredoc: EXTRA_LIBS := -lskarnet heredoc: src/execline/heredoc.o homeof: EXTRA_LIBS := -lskarnet ${MAYBEPTHREAD_LIB} homeof: src/execline/homeof.o ${LIBNSSS} if: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} if: src/execline/if.o ${LIBEXECLINE} ifelse: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} ifelse: src/execline/ifelse.o ${LIBEXECLINE} ifte: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} ifte: src/execline/ifte.o ${LIBEXECLINE} ifthenelse: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} ifthenelse: src/execline/ifthenelse.o ${LIBEXECLINE} importas: EXTRA_LIBS := -lskarnet importas: src/execline/importas.o ${LIBEXECLINE} loopwhilex: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} loopwhilex: src/execline/loopwhilex.o ${LIBEXECLINE} multidefine: EXTRA_LIBS := -lskarnet multidefine: src/execline/multidefine.o ${LIBEXECLINE} multisubstitute: EXTRA_LIBS := -lskarnet multisubstitute: src/execline/multisubstitute.o ${LIBEXECLINE} pipeline: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} pipeline: src/execline/pipeline.o ${LIBEXECLINE} piperw: EXTRA_LIBS := -lskarnet piperw: src/execline/piperw.o redirfd: EXTRA_LIBS := -lskarnet redirfd: src/execline/redirfd.o runblock: EXTRA_LIBS := -lskarnet runblock: src/execline/runblock.o ${LIBEXECLINE} shift: EXTRA_LIBS := -lskarnet shift: src/execline/shift.o ${LIBEXECLINE} trap: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} trap: src/execline/trap.o ${LIBEXECLINE} tryexec: EXTRA_LIBS := -lskarnet tryexec: src/execline/tryexec.o ${LIBEXECLINE} unexport: EXTRA_LIBS := -lskarnet unexport: src/execline/unexport.o wait: EXTRA_LIBS := -lskarnet wait: src/execline/wait.o ${LIBEXECLINE} withstdinas: EXTRA_LIBS := -lskarnet withstdinas: src/execline/withstdinas.o ${LIBEXECLINE} ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),) libexecline.a.xyzzy: src/libexecline/el_execsequence.o src/libexecline/el_getstrict.o src/libexecline/el_modif_and_exec.o src/libexecline/el_modif_and_spawn.o src/libexecline/el_parse.o src/libexecline/el_parse_from_buffer.o src/libexecline/el_parse_from_string.o src/libexecline/el_popenv.o src/libexecline/el_pushenv.o src/libexecline/el_semicolon.o src/libexecline/el_spawn0.o src/libexecline/el_spawn1.o src/libexecline/el_substandrun.o src/libexecline/el_substandrun_str.o src/libexecline/el_substitute.o src/libexecline/el_transform.o src/libexecline/el_vardupl.o src/libexecline/exlsn_define.o src/libexecline/exlsn_elglob.o src/libexecline/exlsn_importas.o src/libexecline/exlsn_multidefine.o src/libexecline/exlsn_exlp.o src/libexecline/exlsn_main.o src/libexecline/exlsn_free.o src/libexecline/exlp.o else libexecline.a.xyzzy: src/libexecline/el_execsequence.lo src/libexecline/el_getstrict.lo src/libexecline/el_modif_and_exec.lo src/libexecline/el_modif_and_spawn.lo src/libexecline/el_parse.lo src/libexecline/el_parse_from_buffer.lo src/libexecline/el_parse_from_string.lo src/libexecline/el_popenv.lo src/libexecline/el_pushenv.lo src/libexecline/el_semicolon.lo src/libexecline/el_spawn0.lo src/libexecline/el_spawn1.lo src/libexecline/el_substandrun.lo src/libexecline/el_substandrun_str.lo src/libexecline/el_substitute.lo src/libexecline/el_transform.lo src/libexecline/el_vardupl.lo src/libexecline/exlsn_define.lo src/libexecline/exlsn_elglob.lo src/libexecline/exlsn_importas.lo src/libexecline/exlsn_multidefine.lo src/libexecline/exlsn_exlp.lo src/libexecline/exlsn_main.lo src/libexecline/exlsn_free.lo src/libexecline/exlp.lo endif libexecline.so.xyzzy: EXTRA_LIBS := -lskarnet libexecline.so.xyzzy: src/libexecline/el_execsequence.lo src/libexecline/el_getstrict.lo src/libexecline/el_modif_and_exec.lo src/libexecline/el_modif_and_spawn.lo src/libexecline/el_parse.lo src/libexecline/el_parse_from_buffer.lo src/libexecline/el_parse_from_string.lo src/libexecline/el_popenv.lo src/libexecline/el_pushenv.lo src/libexecline/el_semicolon.lo src/libexecline/el_spawn0.lo src/libexecline/el_spawn1.lo src/libexecline/el_substandrun.lo src/libexecline/el_substandrun_str.lo src/libexecline/el_substitute.lo src/libexecline/el_transform.lo src/libexecline/el_vardupl.lo src/libexecline/exlsn_define.lo src/libexecline/exlsn_elglob.lo src/libexecline/exlsn_importas.lo src/libexecline/exlsn_multidefine.lo src/libexecline/exlsn_exlp.lo src/libexecline/exlsn_main.lo src/libexecline/exlsn_free.lo src/libexecline/exlp.lo posix-cd: EXTRA_LIBS := -lskarnet posix-cd: src/posix/posix-cd.o posix-umask: EXTRA_LIBS := -lskarnet posix-umask: src/posix/posix-umask.o execline-2.8.2.0/package/info000066400000000000000000000001141416030414000157130ustar00rootroot00000000000000package=execline version=2.8.2.0 category=admin package_macro_name=EXECLINE execline-2.8.2.0/package/modes000066400000000000000000000013471416030414000161000ustar00rootroot00000000000000background 0755 backtick 0755 case 0755 define 0755 dollarat 0755 elgetopt 0755 elgetpositionals 0755 elglob 0755 execline-cd 0755 execline-umask 0755 emptyenv 0755 envfile 0755 exec 0755 exit 0755 execlineb 0755 export 0755 fdblock 0755 fdclose 0755 fdreserve 0755 fdmove 0755 fdswap 0755 forbacktickx 0755 foreground 0755 forstdin 0755 forx 0755 getcwd 0755 getpid 0755 heredoc 0755 homeof 0755 if 0755 ifelse 0755 ifte 0755 ifthenelse 0755 importas 0755 loopwhilex 0755 multidefine 0755 multisubstitute 0755 piperw 0755 pipeline 0755 posix-cd 0755 posix-umask 0755 redirfd 0755 runblock 0755 shift 0755 trap 0755 tryexec 0755 unexport 0755 wait 0755 withstdinas 0755 execline-2.8.2.0/package/targets.mak000066400000000000000000000017501416030414000172070ustar00rootroot00000000000000BIN_TARGETS := \ background \ backtick \ case \ define \ dollarat \ elgetopt \ elgetpositionals \ elglob \ emptyenv \ envfile \ exec \ execlineb \ execline-cd \ execline-umask \ exit \ export \ fdblock \ fdclose \ fdmove \ fdswap \ fdreserve \ forbacktickx \ foreground \ forstdin \ forx \ getcwd \ getpid \ heredoc \ homeof \ if \ ifelse \ ifte \ ifthenelse \ importas \ loopwhilex \ multidefine \ multisubstitute \ pipeline \ piperw \ posix-cd \ posix-umask \ redirfd \ runblock \ shift \ trap \ tryexec \ unexport \ wait \ withstdinas LIBEXEC_TARGETS := LIB_DEFS := EXECLINE=execline ifeq ($(PEDANTIC_POSIX),1) PEDANTIC_PREFIX := posix else PEDANTIC_PREFIX := execline endif EXTRA_TARGETS := cd umask $(DESTDIR)$(bindir)/cd: $(DESTDIR)$(bindir)/$(PEDANTIC_PREFIX)-cd exec ./tools/install.sh -l $(PEDANTIC_PREFIX)-cd $(DESTDIR)$(bindir)/cd $(DESTDIR)$(bindir)/umask: $(DESTDIR)$(bindir)/$(PEDANTIC_PREFIX)-umask exec ./tools/install.sh -l $(PEDANTIC_PREFIX)-umask $(DESTDIR)$(bindir)/umask execline-2.8.2.0/patch-for-solaris000077500000000000000000000007511416030414000167340ustar00rootroot00000000000000#!/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 execline-2.8.2.0/src/000077500000000000000000000000001416030414000142355ustar00rootroot00000000000000execline-2.8.2.0/src/execline/000077500000000000000000000000001416030414000160315ustar00rootroot00000000000000execline-2.8.2.0/src/execline/background.c000066400000000000000000000025751416030414000203250ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #define USAGE "background [ -d ] { command... }" int main (int argc, char const **argv, char const *const *envp) { pid_t pid ; int argc1 ; int df = 0 ; PROG = "background" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "d", &l) ; if (opt == -1) break ; switch (opt) { case 'd' : df = 1 ; break ; default : strerr_dieusage(100, USAGE) ; } } argc -= l.ind ; argv += l.ind ; } argc1 = el_semicolon(argv) ; if (!argc1) strerr_dief1x(100, "empty block") ; if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ; if (argc1 + 1 == argc) df = 0 ; argv[argc1] = 0 ; if (df) { pid = doublefork() ; switch (pid) { case -1: strerr_diefu1sys(111, "doublefork") ; case 0: PROG = "background (grandchild)" ; xexec0_e(argv, envp) ; } } else { pid = el_spawn0(argv[0], argv, envp) ; if (!pid) strerr_diefu2sys(111, "spawn ", argv[0]) ; } if (argc1 + 1 == argc) return 0 ; { char fmt[PID_FMT + 2] = "!=" ; size_t i = 2 ; i += pid_fmt(fmt+i, pid) ; fmt[i++] = 0 ; xmexec_en(argv + argc1 + 1, envp, fmt, i, 1) ; } } execline-2.8.2.0/src/execline/backtick.c000066400000000000000000000051041416030414000177500ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include #include #define USAGE "backtick [ -i | -I | -x | -D default ] [ -N | -n ] [ -E | -e ] var { prog... } remainder..." #define dieusage() strerr_dieusage(100, USAGE) int main (int argc, char const **argv, char const *const *envp) { subgetopt localopt = SUBGETOPT_ZERO ; int argc1, fdwstat ; stralloc value = STRALLOC_ZERO ; char const *var ; char const *val ; int insist = 2, chomp = 1, doimport = 0 ; char const *def = 0 ; PROG = "backtick" ; for (;;) { int opt = subgetopt_r(argc, argv, "iINnxD:Ee", &localopt) ; if (opt < 0) break ; switch (opt) { case 'i' : insist = 2 ; break ; case 'I' : insist = 0 ; break ; case 'N' : chomp = 0 ; break ; case 'n' : chomp = 1 ; break ; case 'x' : insist = 1 ; def = 0 ; break ; case 'D' : insist = 1 ; def = localopt.arg ; break ; case 'E' : doimport = 1 ; break ; case 'e' : doimport = 0 ; break ; default : dieusage() ; } } argc -= localopt.ind ; argv += localopt.ind ; if (argc < 2) dieusage() ; if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ; argc-- ; var = *argv++ ; argc1 = el_semicolon(argv) ; if (!argc1) strerr_dief1x(100, "empty block") ; if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ; argv[argc1] = 0 ; { pid_t pid = child_spawn1_pipe(argv[0], argv, envp, &fdwstat, 1) ; if (!pid) strerr_diefu2sys(111, "spawn ", argv[0]) ; if (!slurp(&value, fdwstat) || !stralloc_0(&value)) strerr_diefu1sys(111, "slurp") ; close(fdwstat) ; if (wait_pid(pid, &fdwstat) < 0) strerr_diefu1sys(111, "wait_pid") ; } val = value.s ; if (wait_status(fdwstat)) { if (insist >= 2) strerr_dief1x(wait_estatus(fdwstat), WIFSIGNALED(fdwstat) ? "child process crashed" : "child process exited non-zero") ; else if (insist) val = def ; } else if (strlen(value.s) < value.len - 1) { if (insist >= 2) strerr_dief1x(124, "child process output contained a null character") ; else if (insist) { val = def ; strerr_warnw1x("child process output contained a null character") ; } else value.len = strlen(value.s) + 1 ; } else insist = 0 ; if (!insist && chomp && (value.s[value.len - 2] == '\n')) value.s[--value.len - 1] = 0 ; el_modif_and_exec(argv + argc1 + 1, var, val, doimport) ; } execline-2.8.2.0/src/execline/case.c000066400000000000000000000101261416030414000171100ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include #include #define USAGE "case [ -s | -S ] [ -e | -E ] [ -n | -N ] [ -i ] value { re1 { prog1... } re2 { prog2... } ... } progdefault... " #define dieusage() strerr_dieusage(100, USAGE) static void execit (char const *const *argv, char const *expr, char const *s, regmatch_t const *pmatch, size_t n) gccattr_noreturn ; static void execit (char const *const *argv, char const *expr, char const *s, regmatch_t const *pmatch, size_t n) { if (n) { size_t exprlen = strlen(expr) ; size_t fmtlen = exprlen + 6 ; for (size_t i = 1 ; i < n ; i++) fmtlen += uint_fmt(0, i) + 2 + pmatch[i].rm_eo - pmatch[i].rm_so ; { size_t m = 0 ; char fmt[fmtlen] ; fmt[m++] = '#' ; fmt[m++] = '=' ; m += uint_fmt(fmt + m, n-1) ; fmt[m++] = 0 ; fmt[m++] = '0' ; fmt[m++] = '=' ; memcpy(fmt + m, expr, exprlen + 1) ; m += exprlen + 1 ; for (size_t i = 1 ; i < n ; i++) { m += uint_fmt(fmt + m, i) ; fmt[m++] = '=' ; memcpy(fmt + m, s + pmatch[i].rm_so, pmatch[i].rm_eo - pmatch[i].rm_so) ; m += pmatch[i].rm_eo - pmatch[i].rm_so ; fmt[m++] = 0 ; } xmexec0_n(argv, fmt, fmtlen, n+1) ; } } else xexec0(argv) ; } int main (int argc, char const **argv, char const *const *envp) { int flagshell = 0 ; int flagextended = 1 ; int flagnosub = 1 ; int flagicase = 0 ; int argc1 ; unsigned int i = 0 ; char const *s ; PROG = "case" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "sSeEnNi", &l) ; if (opt == -1) break ; switch (opt) { case 's' : flagshell = 1 ; break ; case 'S' : flagshell = 0 ; break ; case 'e' : flagextended = 0 ; break ; case 'E' : flagextended = 1 ; break ; case 'N' : flagnosub = 0 ; break ; case 'n' : flagnosub = 1 ; break ; case 'i' : flagicase = 1 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (argc-- < 2) dieusage() ; s = *argv++ ; argc1 = el_semicolon(argv) ; if (argc1 >= argc) strerr_dief1x(100, "unterminated case block") ; while (i < argc1) { char const *expr = argv[i++] ; int argc2 ; if (i == argc1) strerr_dief1x(100, "malformed case block") ; argc2 = el_semicolon(argv + i) ; if (i + argc2 >= argc1) strerr_dief1x(100, "unterminated regex block") ; if (flagshell) { int r = fnmatch(expr, s, (flagextended ? 0 : FNM_NOESCAPE) | (flagicase ? FNM_PERIOD : 0) | (flagnosub ? 0 : FNM_PATHNAME)) ; if (!r) { argv[i + argc2] = 0 ; xexec0(argv + i) ; } else if (r != FNM_NOMATCH) strerr_warnw2x("invalid fnmatch pattern: ", expr) ; } else { regex_t re ; { int r ; size_t len = strlen(expr) ; char tmp[len+3] ; tmp[0] = '^' ; memcpy(tmp + 1, expr, len) ; tmp[1+len] = '$' ; tmp[2+len] = 0 ; r = regcomp(&re, tmp, (flagextended ? REG_EXTENDED : 0) | (flagicase ? REG_ICASE : 0) | (flagnosub ? REG_NOSUB : 0) | REG_NEWLINE) ; if (r) { char buf[256] ; regerror(r, &re, buf, 256) ; strerr_diefu4x(r == REG_ESPACE ? 111 : 100, "regcomp \"^", argv[i], "$\": ", buf) ; } } { regmatch_t pmatch[re.re_nsub && !flagnosub ? re.re_nsub + 1 : 1] ; int r = regexec(&re, s, re.re_nsub + 1, pmatch, 0) ; if (!r) { argv[i + argc2] = 0 ; execit(argv + i, expr, s, pmatch, flagnosub ? 0 : 1 + re.re_nsub) ; } if (r != REG_NOMATCH) { char buf[256] ; regerror(r, &re, buf, 256) ; strerr_diefu6x(111, "match string \"", s, "\" against regex \"", expr, "\": ", buf) ; } } regfree(&re) ; } i += argc2 + 1 ; } xexec0(argv + argc1 + 1) ; } execline-2.8.2.0/src/execline/define.c000066400000000000000000000004521416030414000174300ustar00rootroot00000000000000/* ISC license. */ #include #include "exlsn.h" #define USAGE "define [ -N | -n ] [ -s ] [ -C | -c ] [ -d delim ] key value prog..." int main (int argc, char const **argv, char const *const *envp) { PROG = "define" ; exlsn_main(argc, argv, envp, &exlsn_define, USAGE) ; } execline-2.8.2.0/src/execline/deps-exe/000077500000000000000000000000001416030414000175435ustar00rootroot00000000000000execline-2.8.2.0/src/execline/deps-exe/background000066400000000000000000000000461416030414000216050ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet ${SPAWN_LIB} execline-2.8.2.0/src/execline/deps-exe/backtick000066400000000000000000000000461416030414000212410ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet ${SPAWN_LIB} execline-2.8.2.0/src/execline/deps-exe/case000066400000000000000000000000311416030414000203730ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet execline-2.8.2.0/src/execline/deps-exe/define000066400000000000000000000000311416030414000207120ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet execline-2.8.2.0/src/execline/deps-exe/dollarat000066400000000000000000000000121416030414000212610ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/execline/deps-exe/elgetopt000066400000000000000000000000311416030414000213030ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet execline-2.8.2.0/src/execline/deps-exe/elgetpositionals000066400000000000000000000000311416030414000230450ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet execline-2.8.2.0/src/execline/deps-exe/elglob000066400000000000000000000000311416030414000207240ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet execline-2.8.2.0/src/execline/deps-exe/emptyenv000066400000000000000000000000311416030414000213270ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet execline-2.8.2.0/src/execline/deps-exe/envfile000066400000000000000000000000121416030414000211070ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/execline/deps-exe/exec000066400000000000000000000000121416030414000204030ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/execline/deps-exe/execline-cd000066400000000000000000000000121416030414000216370ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/execline/deps-exe/execline-umask000066400000000000000000000000121416030414000223710ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/execline/deps-exe/execlineb000066400000000000000000000000311416030414000214160ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet execline-2.8.2.0/src/execline/deps-exe/exit000066400000000000000000000000121416030414000204300ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/execline/deps-exe/export000066400000000000000000000000121416030414000210000ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/execline/deps-exe/fdblock000066400000000000000000000000121416030414000210630ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/execline/deps-exe/fdclose000066400000000000000000000000121416030414000210760ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/execline/deps-exe/fdmove000066400000000000000000000000121416030414000207370ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/execline/deps-exe/fdreserve000066400000000000000000000000121416030414000214440ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/execline/deps-exe/fdswap000066400000000000000000000000121416030414000207430ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/execline/deps-exe/forbacktickx000066400000000000000000000000121416030414000221310ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/execline/deps-exe/foreground000066400000000000000000000000461416030414000216400ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet ${SPAWN_LIB} execline-2.8.2.0/src/execline/deps-exe/forstdin000066400000000000000000000000461416030414000213160ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet ${SPAWN_LIB} execline-2.8.2.0/src/execline/deps-exe/forx000066400000000000000000000000461416030414000204440ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet ${SPAWN_LIB} execline-2.8.2.0/src/execline/deps-exe/getcwd000066400000000000000000000000311416030414000207350ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet execline-2.8.2.0/src/execline/deps-exe/getpid000066400000000000000000000000311416030414000207340ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet execline-2.8.2.0/src/execline/deps-exe/heredoc000066400000000000000000000000121416030414000210700ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/execline/deps-exe/homeof000066400000000000000000000000511416030414000207370ustar00rootroot00000000000000${LIBNSSS} -lskarnet ${MAYBEPTHREAD_LIB} execline-2.8.2.0/src/execline/deps-exe/if000066400000000000000000000000461416030414000200640ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet ${SPAWN_LIB} execline-2.8.2.0/src/execline/deps-exe/ifelse000066400000000000000000000000461416030414000207350ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet ${SPAWN_LIB} execline-2.8.2.0/src/execline/deps-exe/ifte000066400000000000000000000000461416030414000204150ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet ${SPAWN_LIB} execline-2.8.2.0/src/execline/deps-exe/ifthenelse000066400000000000000000000000461416030414000216140ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet ${SPAWN_LIB} execline-2.8.2.0/src/execline/deps-exe/importas000066400000000000000000000000311416030414000213160ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet execline-2.8.2.0/src/execline/deps-exe/loopwhilex000066400000000000000000000000461416030414000216600ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet ${SPAWN_LIB} execline-2.8.2.0/src/execline/deps-exe/multidefine000066400000000000000000000000311416030414000217650ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet execline-2.8.2.0/src/execline/deps-exe/multisubstitute000066400000000000000000000000311416030414000227460ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet execline-2.8.2.0/src/execline/deps-exe/pipeline000066400000000000000000000000461416030414000212730ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet ${SPAWN_LIB} execline-2.8.2.0/src/execline/deps-exe/piperw000066400000000000000000000000121416030414000207650ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/execline/deps-exe/redirfd000066400000000000000000000000121416030414000210760ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/execline/deps-exe/runblock000066400000000000000000000000311416030414000212770ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet execline-2.8.2.0/src/execline/deps-exe/shift000066400000000000000000000000311416030414000205750ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet execline-2.8.2.0/src/execline/deps-exe/trap000066400000000000000000000000461416030414000204340ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet ${SPAWN_LIB} execline-2.8.2.0/src/execline/deps-exe/tryexec000066400000000000000000000000311416030414000211430ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet execline-2.8.2.0/src/execline/deps-exe/unexport000066400000000000000000000000121416030414000213430ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/execline/deps-exe/wait000066400000000000000000000000311416030414000204240ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet execline-2.8.2.0/src/execline/deps-exe/withstdinas000066400000000000000000000000311416030414000220210ustar00rootroot00000000000000${LIBEXECLINE} -lskarnet execline-2.8.2.0/src/execline/dollarat.c000066400000000000000000000031111416030414000177730ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include #define USAGE "dollarat [ -n ] [ -0 | -d delimchar ]" int main (int argc, char const *const *argv) { unsigned int n, i = 0 ; char const *x ; char delim = '\n' ; int zero = 0 ; int nl = 1 ; PROG = "dollarat" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "nd:0", &l) ; if (opt == -1) break ; switch (opt) { case 'n' : nl = 0 ; break ; case 'd' : delim = *l.arg ; zero = 0 ; break ; case '0' : zero = 1 ; break ; default : strerr_dieusage(100, USAGE) ; } } argc -= l.ind ; argv += l.ind ; } if (zero) delim = 0 ; x = getenv("#") ; if (!x) strerr_dienotset(100, "#") ; if (!uint0_scan(x, &n)) strerr_dieinvalid(100, "#") ; for (; i < n ; i++) { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, i+1)] = 0 ; x = getenv(fmt) ; if (!x) strerr_dienotset(100, fmt) ; if (delim || zero) { if ((buffer_puts(buffer_1, x) < 0) || (((i < n-1) || nl) && (buffer_put(buffer_1, &delim, 1) < 0))) strerr_diefu1sys(111, "write to stdout") ; } else { size_t written = 0 ; if (!netstring_put(buffer_1, x, strlen(x), &written)) strerr_diefu1sys(111, "write a netstring to stdout") ; } } if (!buffer_flush(buffer_1)) strerr_diefu1sys(111, "write to stdout") ; return 0 ; } execline-2.8.2.0/src/execline/elgetopt.c000066400000000000000000000035101416030414000200170ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include #define USAGE "elgetopt optstring prog..." int main (int argc, char const *const *argv, char const *const *envp) { size_t envlen = env_len(envp) ; stralloc modif = STRALLOC_ZERO ; char const *x = getenv("#") ; unsigned int n, nbak ; PROG = "elgetopt" ; if (argc < 3) strerr_dieusage(100, USAGE) ; if (!x) strerr_dienotset(100, "#") ; if (!uint0_scan(x, &n)) strerr_dieinvalid(100, "#") ; nbak = n++ ; { subgetopt l = SUBGETOPT_ZERO ; char const *args[n+1] ; unsigned int i = 0 ; for ( ; i < n ; i++) { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, i)] = 0 ; args[i] = getenv(fmt) ; if (!args[i]) strerr_dienotset(100, fmt) ; } args[n] = 0 ; for (;;) { char hmpf[11] = "ELGETOPT_?" ; int opt = sgetopt_r(n, args, argv[1], &l) ; if (opt == -1) break ; if (opt == '?') return 1 ; hmpf[9] = opt ; if (!env_addmodif(&modif, hmpf, l.arg ? l.arg : "1")) goto err ; } n -= l.ind ; for (i = 0 ; i < nbak ; i++) { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, i+1)] = 0 ; if (!env_addmodif(&modif, fmt, (i < n) ? args[l.ind + i] : 0)) goto err ; } } { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, n)] = 0 ; if (!env_addmodif(&modif, "#", fmt)) goto err ; } { char const *const list[1] = { "ELGETOPT_" } ; char const *v[envlen] ; if (el_pushenv(&satmp, envp, envlen, list, 1) < 0) goto err ; if (!env_make(v, envlen, satmp.s, satmp.len)) goto err ; xmexec_fm(argv+2, v, envlen, modif.s, modif.len) ; } err: strerr_diefu1sys(111, "update environment") ; } execline-2.8.2.0/src/execline/elgetpositionals.c000066400000000000000000000004211416030414000215570ustar00rootroot00000000000000/* ISC license. */ #include #include "exlsn.h" #define USAGE "elgetpositionals [ -P num ] prog..." int main (int argc, char const **argv, char const *const *envp) { PROG = "elgetpositionals" ; exlsn_main(argc, argv, envp, &exlsn_exlp, USAGE) ; } execline-2.8.2.0/src/execline/elglob.c000066400000000000000000000004521416030414000174420ustar00rootroot00000000000000/* ISC license. */ #include #include "exlsn.h" #define USAGE "elglob [ -v ] [ -w ] [ -s ] [ -m ] [ -e ] [ -0 ] key pattern prog..." int main (int argc, char const **argv, char const *const *envp) { PROG = "elglob" ; exlsn_main(argc, argv, envp, &exlsn_elglob, USAGE) ; } execline-2.8.2.0/src/execline/emptyenv.c000066400000000000000000000047721416030414000200560ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include #include #define USAGE "emptyenv [ -p | -c | -o | -P ] prog..." static void cleanupenv (char const *const *, char const *const *) gccattr_noreturn ; static void cleanupenv (char const *const *argv, char const *const *envp) { stralloc sa = STRALLOC_ZERO ; if (!env_mexec("!", 0) || !env_mexec("?", 0)) goto err ; for (; *envp ; envp++) { char const *s = *envp ; sa.len = 0 ; if (!strncmp(s, "ELGETOPT_", 9) || !strncmp(s, "EXECLINE_", 9) || !strncmp(s, "FD", 2) || (s[0] == '#') || ((s[0] >= '0') && (s[0] <= '9'))) if (!stralloc_catb(&sa, s, str_chr(s, '=')) || !stralloc_0(&sa) || !env_mexec(sa.s, 0)) goto err ; } stralloc_free(&sa) ; xmexec(argv) ; err: strerr_diefu1sys(111, "clean up environment") ; } int main (int argc, char const *const *argv, char const *const *envp) { int flagpath = 0, flagcleanup = 0, flagopt = 0, flagpos = 0 ; PROG = "emptyenv" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "pcoP", &l) ; if (opt == -1) break ; switch (opt) { case 'p' : flagpath = 1 ; break ; case 'c' : flagcleanup = 1 ; break ; case 'o' : flagopt = 1 ; break ; case 'P' : flagpos = 1 ; break ; default : strerr_dieusage(100, USAGE) ; } } argc -= l.ind ; argv += l.ind ; } if (!argc) strerr_dieusage(100, USAGE) ; if (flagcleanup) cleanupenv(argv, envp) ; else if (!flagopt && !flagpos) { char const *newenv[2] = { 0, 0 } ; if (flagpath) for (; *envp ; envp++) if (!strncmp(*envp, "PATH=", 5)) { newenv[0] = *envp ; break ; } xexec_e(argv, newenv) ; } else { static char const *const list[12] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "#", "ELGETOPT_" } ; stralloc sa = STRALLOC_ZERO ; size_t envlen = env_len(envp) ; int n = el_popenv(&sa, envp, envlen, flagpos ? list : list + 11, 11 * flagpos + flagopt) ; if (n < 0) strerr_diefu1sys(111, "pop current execline environment") ; { char const *v[envlen - n + 1] ; if (!env_make(v, envlen-n, sa.s, sa.len)) strerr_diefu1sys(111, "env_make") ; v[envlen-n] = 0 ; xexec_e(argv, v) ; } } } execline-2.8.2.0/src/execline/envfile.c000066400000000000000000000124271416030414000176330ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define USAGE "envfile [ -i | -I ] file prog..." #define dieusage() strerr_dieusage(100, USAGE) #define dienomem() strerr_diefu1sys(111, "stralloc_catb") static void scanoct (stralloc *sa, size_t pos) { unsigned int u ; if (!stralloc_0(sa)) dienomem() ; uint_oscan(sa->s + pos, &u) ; sa->s[pos] = u ; sa->len = pos+1 ; } static inline uint8_t cclass (char c) { switch (c) { case 0 : return 0 ; case '#' : return 1 ; case '\n' : return 2 ; case '=' : return 3 ; case ' ' : case '\t' : case '\f' : case '\r' : return 4 ; case '\\' : return 5 ; case '\"' : return 6 ; case 'a' : case 'b' : case 'f' : return 7 ; case 'n' : case 'r' : case 't' : case 'v' : return 8 ; case '\'' : case '?' : return 9 ; case 'x' : return 10 ; case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : return 11 ; case '8' : case '9' : case 'A' : case 'B' : case 'c' : case 'C' : case 'd' : case 'D' : case 'e' : case 'E' : case 'F' : return 12 ; default : return 13 ; } } static inline char next (char const *file, buffer *b) { char c ; ssize_t r = buffer_get(b, &c, 1) ; if (r < 0) strerr_diefu2sys(111, "read from ", file) ; if (!r) c = 0 ; return c ; } static inline void parse_config (char const *file, buffer *b, stralloc *sa) { static uint16_t const table[14][14] = { { 0x000e, 0x0001, 0x0020, 0x000f, 0x0000, 0x000f, 0x000f, 0x0012, 0x0012, 0x000f, 0x0012, 0x0012, 0x0012, 0x0012 }, { 0x000e, 0x0001, 0x0020, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001 }, { 0x000f, 0x0012, 0x000f, 0x0014, 0x0003, 0x000f, 0x000f, 0x0012, 0x0012, 0x000f, 0x0012, 0x0012, 0x0012, 0x0012 }, { 0x000f, 0x000f, 0x000f, 0x0014, 0x0003, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f }, { 0x004e, 0x0015, 0x0060, 0x0015, 0x0004, 0x0008, 0x0007, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015 }, { 0x004e, 0x0015, 0x0060, 0x0015, 0x0116, 0x0008, 0x0007, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015 }, { 0x00ce, 0x0015, 0x00d0, 0x0015, 0x0016, 0x0008, 0x0007, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015 }, { 0x000f, 0x0017, 0x000f, 0x0017, 0x0017, 0x0009, 0x0005, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017 }, { 0x000f, 0x000f, 0x0025, 0x000f, 0x0015, 0x0015, 0x0015, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f }, { 0x000f, 0x0017, 0x0027, 0x0017, 0x0017, 0x0017, 0x0017, 0x1017, 0x1017, 0x0017, 0x000a, 0x011c, 0x0017, 0x0017 }, { 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x001b, 0x000f, 0x000f, 0x000f, 0x001b, 0x001b, 0x000f }, { 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, 0x0217, 0x000f, 0x000f, 0x000f, 0x0217, 0x0217, 0x000f }, { 0x000f, 0x0417, 0x000f, 0x0417, 0x0417, 0x0409, 0x0405, 0x0417, 0x0417, 0x0417, 0x0417, 0x001d, 0x0417, 0x0417 }, { 0x000f, 0x0417, 0x000f, 0x0417, 0x0417, 0x0409, 0x0405, 0x0417, 0x0417, 0x0417, 0x0417, 0x0817, 0x0417, 0x0417 } } ; unsigned int line = 1 ; size_t mark = 0 ; uint8_t state = 0 ; while (state < 14) { char c = next(file, b) ; uint16_t what = table[state][cclass(c)] ; state = what & 0x0f ; if (what & 0x0400) scanoct(sa, mark) ; if (what & 0x0100) mark = sa->len ; if (what & 0x1000) c = 7 + byte_chr("abtnvfr", 7, c) ; if (what & 0x0010) if (!stralloc_catb(sa, &c, 1)) dienomem() ; if (what & 0x0020) line++ ; if (what & 0x0080) sa->len = mark ; if (what & 0x0040) if (!stralloc_0(sa)) dienomem() ; if (what & 0x0200) { sa->s[sa->len-2] = (fmtscan_num(sa->s[sa->len-2], 16) << 4) + fmtscan_num(sa->s[sa->len-1], 16) ; sa->len-- ; } if (what & 0x0800) scanoct(sa, mark) ; } if (state > 14) { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, line)] = 0 ; strerr_dief4x(1, "in ", file, ": syntax error line ", fmt) ; } } int main (int argc, char const *const *argv) { stralloc modif = STRALLOC_ZERO ; int fd ; char const *name ; int strict = 1 ; PROG = "envfile" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "iI", &l) ; if (opt == -1) break ; switch (opt) { case 'i' : strict = 1 ; break ; case 'I' : strict = 0 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (argc < 2) dieusage() ; if (strcmp(argv[0], "-")) { fd = open_readb(argv[0]) ; name = argv[0] ; } else { fd = 0 ; name = "standard input" ; } if (fd == -1) { if (strict || errno != ENOENT) strerr_diefu2sys(111, "open ", name) ; } else { buffer b ; char buf[BUFFER_INSIZE] ; buffer_init(&b, &buffer_read, fd, buf, BUFFER_INSIZE) ; parse_config(name, &b, &modif) ; fd_close(fd) ; } xmexec_m(argv + 1, modif.s, modif.len) ; } execline-2.8.2.0/src/execline/envfile.txt000066400000000000000000000030041416030414000202170ustar00rootroot00000000000000envfile parser: class | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 st\ev | \0 # \n = space \ " abf nrtv '? x 0-7 89cde other START | n a a a a a a 0 | END COMMENT START X START X X VAR VAR X VAR VAR VAR VAR COMMENT | n 1 | END COMMENT START COMMENT COMMENT COMMENT COMMENT COMMENT COMMENT COMMENT COMMENT COMMENT COMMENT COMMENT VAR | a a a a a a a a 2 | X VAR X EQ WAITEQ X X VAR VAR X VAR VAR VAR VAR WAITEQ | a 3 | X X X EQ WAITEQ X X X X X X X X X EQ | + a + n a a a a a a a a 4 | END VAL START VAL EQ ESC Q VAL VAL VAL VAL VAL VAL VAL VAL | + a + n a m a a a a a a a a 5 | END VAL START VAL SPACE ESC Q VAL VAL VAL VAL VAL VAL VAL SPACE | b + a b + n a a a a a a a a a 6 | END VAL START VAL SPACE ESC Q VAL VAL VAL VAL VAL VAL VAL Q | a a a a a a a a a a 7 | X Q X Q Q QESC VAL Q Q Q Q Q Q Q ESC | n a a a 8 | X X VAL X VAL VAL VAL X X X X X X X QESC | a n a a a a s a s a a m a a a 9 | X Q Q Q Q Q Q Q Q Q HEX0 OCT1 Q Q HEX0 | a a a a | X X X X X X X HEX1 X X X HEX1 HEX1 X HEX1 | a h a h a h b | X X X X X X X Q X X X Q Q X OCT1 | o a o a o a o o o a o a o a o a a o a o a c | X Q X Q Q QESC VAL Q Q Q Q OCT2 Q Q OCT2 | o a o a o a o o o a o a o a o a a O o a o a d | X Q X Q Q QESC VAL Q Q Q Q Q Q Q END = e, X = f 16 states, 9 actions -> 13 bits a 0x0010 add cur n 0x0020 line++ + 0x0040 add \0 (definition complete) b 0x0080 go back to mark m 0x0100 set mark h 0x0200 calc hex o 0x0400 calc oct before a O 0x0800 calc oct after a s 0x1000 turn cur special before a execline-2.8.2.0/src/execline/exec.c000066400000000000000000000021471416030414000171250ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #define USAGE "exec [ -c ] [ -l ] [ -a argv0 ] prog..." int main (int argc, char const **argv, char const *const *envp) { static char const *const zero = 0 ; char const *executable = 0 ; char const *argv0 = 0 ; int dash = 0 ; PROG = "exec" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "cla:", &l) ; if (opt == -1) break ; switch (opt) { case 'c' : envp = &zero ; break ; case 'l' : dash = 1 ; break ; case 'a' : argv0 = l.arg ; break ; default : strerr_dieusage(100, USAGE) ; } } argc -= l.ind ; argv += l.ind ; } if (!argc) strerr_dieusage(100, USAGE) ; executable = argv[0] ; if (argv0) argv[0] = argv0 ; if (dash) { size_t n = strlen(argv[0]) ; char dashed[n+2] ; dashed[0] = '-' ; memcpy(dashed+1, argv[0], n+1) ; argv[0] = (char const *)dashed ; xexec_ae(executable, argv, envp) ; } else xexec_ae(executable, argv, envp) ; } execline-2.8.2.0/src/execline/execline-cd.c000066400000000000000000000005321416030414000203550ustar00rootroot00000000000000/* ISC license. */ #include #include #include #define USAGE "cd path prog..." int main (int argc, char const *const *argv) { PROG = "execline-cd" ; if (argc < 3) strerr_dieusage(100, USAGE) ; if (chdir(argv[1]) == -1) strerr_diefu2sys(111, "chdir to ", argv[1]) ; xexec(argv+2) ; } execline-2.8.2.0/src/execline/execline-umask.c000066400000000000000000000006161416030414000211120ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #define USAGE "umask value prog..." int main (int argc, char const *const *argv) { unsigned int m ; PROG = "execline-umask" ; if (argc < 3) strerr_dieusage(100, USAGE) ; if (!uint_oscan(argv[1], &m)) strerr_dieusage(100, USAGE) ; umask(m) ; xexec(argv+2) ; } execline-2.8.2.0/src/execline/execlineb.c000066400000000000000000000143441416030414000201410ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "exlsn.h" #define USAGE "execlineb [ -p | -P | -S nmin | -s nmin ] [ -q | -w | -W ] [ -c commandline ] script args" static int myexlp (stralloc *sa, char const *const *argv, unsigned int argc, unsigned int nmin, char const *dollar0, int doshift) { exlsn_t info = EXLSN_ZERO ; unsigned int n = argc > nmin ? argc : nmin ; unsigned int i = 0 ; if (!genalloc_ready(elsubst_t, &info.data, 3 + n)) return -1 ; if (!stralloc_ready(&info.vars, 6 + (n << 1))) goto err ; stralloc_catb(&info.vars, "#\0" "0\0@", 6) ; { elsubst_t blah[3] ; char fmt[UINT_FMT] ; blah[0].var = 0 ; blah[0].value = 0 ; blah[0].n = 1 ; if (!stralloc_catb(&info.values, fmt, uint_fmt(fmt, argc)) || !stralloc_0(&info.values)) goto err ; blah[1].var = 2 ; blah[1].value = info.values.len ; blah[1].n = 1 ; if (!stralloc_catb(&info.values, dollar0, strlen(dollar0) + 1)) goto err ; blah[2].var = 4 ; blah[2].value = info.values.len ; blah[2].n = doshift && n == nmin ? 0 : argc ; genalloc_catb(elsubst_t, &info.data, blah, 3) ; } for (; i < n ; i++) { elsubst_t blah = { .var = info.vars.len, .value = info.values.len, .n = 1 } ; char fmt[UINT_FMT] ; if (!stralloc_catb(&info.vars, fmt, uint_fmt(fmt, i+1)) || !stralloc_0(&info.vars)) goto err ; if (!stralloc_catb(&info.values, i < argc ? argv[i] : "", i < argc ? strlen(argv[i]) + 1 : 1)) goto err ; genalloc_append(elsubst_t, &info.data, &blah) ; if (i == nmin && doshift) { elsubst_t *p = genalloc_s(elsubst_t, &info.data) + 2 ; /* hit $@ in-place */ p->value = blah.value ; p->n = argc - nmin ; } } { stralloc dst = STRALLOC_ZERO ; int r = el_substitute(&dst, sa->s, sa->len, info.vars.s, info.values.s, genalloc_s(elsubst_t, &info.data), genalloc_len(elsubst_t, &info.data)) ; if (r < 0) goto err ; exlsn_free(&info) ; stralloc_free(sa) ; *sa = dst ; return r ; } err: exlsn_free(&info) ; return -1 ; } int main (int argc, char const *const *argv, char const *const *envp) { stralloc sa = STRALLOC_ZERO ; stralloc modif = STRALLOC_ZERO ; int nc ; int flagstrict = -1 ; unsigned int nmin = 0 ; char const *stringarg = 0 ; char const *dollar0 = *argv ; unsigned int flagpushenv = 2 ; PROG = "execlineb" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "pPqwWc:S:s:", &l) ; if (opt == -1) break ; switch (opt) { case 'p' : flagpushenv = 1 ; break ; case 'P' : flagpushenv = 0 ; break ; case 'q' : flagstrict = 0 ; break ; case 'w' : flagstrict = 1 ; break ; case 'W' : flagstrict = 2 ; break ; case 'c' : stringarg = l.arg ; break ; case 'S' : case 's' : { if (!uint0_scan(l.arg, &nmin)) strerr_dieusage(100, USAGE) ; flagpushenv = 3 + (opt == 's') ; break ; } default : strerr_dieusage(100, USAGE) ; } } argc -= l.ind ; argv += l.ind ; } if (stringarg) nc = el_parse_from_string(&sa, stringarg) ; else { char buf[BUFFER_INSIZE] ; buffer b ; int fd ; if (!argc--) strerr_dieusage(100, USAGE) ; dollar0 = *argv++ ; fd = openb_read(dollar0) ; if (fd < 0) strerr_diefu3sys(111, "open ", dollar0, " for reading") ; buffer_init(&b, &fd_readv, fd, buf, BUFFER_INSIZE) ; nc = el_parse_from_buffer(&sa, &b) ; fd_close(fd) ; } switch (nc) { case -4: strerr_dief2x(100, "unmatched ", "}") ; case -3: strerr_dief2x(100, "unmatched ", "{") ; case -2: strerr_dief1x(100, "syntax error") ; case -1: strerr_diefu1sys(111, "parse script") ; case 0 : return 0 ; } if (flagstrict >= 0) { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, (unsigned int)flagstrict)] = 0 ; if (!env_addmodif(&modif, "EXECLINE_STRICT", flagstrict ? fmt : 0)) goto errenv ; } else { char const *x = getenv("EXECLINE_STRICT") ; if (x) { unsigned int u ; if (!uint0_scan(x, &u)) { strerr_warnw1x("invalid EXECLINE_STRICT value, unsetting it") ; if (!env_addmodif(&modif, "EXECLINE_STRICT", 0)) goto errenv ; } else flagstrict = u ; } } if (flagpushenv == 3 || flagpushenv == 4) { if (flagstrict && ((unsigned int)argc < nmin)) { char fmtn[UINT_FMT] ; char fmta[UINT_FMT] ; fmtn[uint_fmt(fmtn, nmin)] = 0 ; fmta[uint_fmt(fmta, argc)] = 0 ; if (flagstrict > 1) strerr_dief4x(100, "too few arguments: expecting at least ", fmtn, " but got ", fmta) ; else strerr_warnw4x("too few arguments: expecting at least ", fmtn, " but got ", fmta) ; } nc = myexlp(&sa, argv, argc, nmin, dollar0, flagpushenv == 4) ; if (nc < 0) strerr_diefu1sys(111, "substitute positional parameters") ; if (!nc) return 0 ; flagpushenv = 0 ; } else if (flagpushenv) { char fmt[UINT_FMT] ; unsigned int i = 0 ; fmt[uint_fmt(fmt, argc)] = 0 ; if (!env_addmodif(&modif, "#", fmt) || !env_addmodif(&modif, "0", dollar0)) goto errenv ; for (; i < (unsigned int)argc ; i++) { fmt[uint_fmt(fmt, i+1)] = 0 ; if (!env_addmodif(&modif, fmt, argv[i])) goto errenv ; } } { char const *v[nc+1] ; if (!env_make(v, nc, sa.s, sa.len)) strerr_diefu1sys(111, "make argv") ; v[nc] = 0 ; if (flagpushenv > 1) { static char const *const list[11] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "#" } ; size_t envlen = env_len(envp) ; char const *w[envlen] ; if (el_pushenv(&satmp, envp, envlen, list, 11) < 0 || !env_make(w, envlen, satmp.s, satmp.len)) goto errenv ; xmexec_fm(v, w, envlen, modif.s, modif.len) ; } else if (modif.len) xmexec_em(v, envp, modif.s, modif.len) ; else xexec_e(v, envp) ; } errenv: strerr_diefu1sys(111, "update environment") ; } execline-2.8.2.0/src/execline/exit.c000066400000000000000000000005001416030414000171410ustar00rootroot00000000000000/* ISC license. */ #include #include #include #define USAGE "exit [ exitcode ]" int main (int argc, char const *const *argv) { unsigned int e ; PROG = "exit" ; if (argc < 2) return 0 ; if (!uint0_scan(argv[1], &e)) strerr_dieusage(100, USAGE) ; _exit(e) ; } execline-2.8.2.0/src/execline/export.c000066400000000000000000000011601416030414000175140ustar00rootroot00000000000000/* ISC license. */ #include #include #include #define USAGE "export variable value prog..." int main (int argc, char const *const *argv) { size_t len1 ; PROG = "export" ; if (argc < 4) strerr_dieusage(100, USAGE) ; len1 = strlen(argv[1]) ; if (memchr(argv[1], '=', len1)) strerr_dief2x(100, "invalid variable name: ", argv[1]) ; { size_t len2 = strlen(argv[2]) ; char fmt[len1 + len2 + 2] ; memcpy(fmt, argv[1], len1) ; fmt[len1] = '=' ; memcpy(fmt + len1 + 1, argv[2], len2 + 1) ; xmexec_n(argv+3, fmt, len1 + len2 + 2, 1) ; } } execline-2.8.2.0/src/execline/fdblock.c000066400000000000000000000014751416030414000176100ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #define USAGE "fdblock [ -n ] fd prog..." int main (int argc, char const *const *argv) { unsigned int fd ; int block = 1 ; PROG = "fdblock" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "n", &l) ; if (opt == -1) break ; switch (opt) { case 'n' : block = 0 ; break ; default : strerr_dieusage(100, USAGE) ; } } argc -= l.ind ; argv += l.ind ; } if ((argc < 2) || !uint0_scan(argv[0], &fd)) strerr_dieusage(100, USAGE) ; if ((block ? ndelay_off(fd) : ndelay_on(fd)) < 0) strerr_diefu1sys(111, block ? "ndelay_off" : "ndelay_on") ; xexec(argv+1) ; } execline-2.8.2.0/src/execline/fdclose.c000066400000000000000000000005621416030414000176170ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #define USAGE "fdclose fd prog..." int main (int argc, char const *const *argv) { unsigned int fd ; PROG = "fdclose" ; if ((argc < 3) || !uint0_scan(argv[1], &fd)) strerr_dieusage(100, USAGE) ; fd_close(fd) ; xexec(argv+2) ; } execline-2.8.2.0/src/execline/fdmove.c000066400000000000000000000016001416030414000174520ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #define USAGE "fdmove [ -c ] to from prog..." int main (int argc, char const *const *argv) { unsigned int to, from ; int flagcopy = 0 ; PROG = "fdmove" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "c", &l) ; if (opt == -1) break ; switch (opt) { case 'c' : flagcopy = 1 ; break ; default : strerr_dieusage(100, USAGE) ; } } argc -= l.ind ; argv += l.ind ; } if ((argc < 3) || !uint0_scan(argv[0], &to) || !uint0_scan(argv[1], &from)) strerr_dieusage(100, USAGE) ; if ((flagcopy ? fd_copy(to, from) : fd_move(to, from)) == -1) strerr_diefu4sys(111, "move fd ", argv[1], " to fd ", argv[0]) ; xexec(argv+2) ; } execline-2.8.2.0/src/execline/fdreserve.c000066400000000000000000000031111416030414000201560ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #define USAGE "fdreserve n prog..." #define MAXFDS 1024 unsigned int doit (char *modif, unsigned int i, int fd) { unsigned int pos = 2 ; modif[0] = 'F' ; modif[1] = 'D' ; pos += uint_fmt(modif + pos, i) ; modif[pos++] = '=' ; pos += uint_fmt(modif + pos, (unsigned int)fd) ; modif[pos++] = 0 ; return pos ; } int main (int argc, char const *const *argv) { unsigned int n ; PROG = "fdreserve" ; if ((argc < 3) || !uint0_scan(argv[1], &n)) strerr_dieusage(100, USAGE) ; { struct rlimit lim ; if (getrlimit(RLIMIT_NOFILE, &lim) < 0) strerr_diefu1sys(111, "getrlimit") ; if (n > lim.rlim_cur) strerr_dief1x(100, "too many requested fds") ; } { char modif[12 * n] ; /* enough for n times "FDaaaa=bbbb\0" */ unsigned int j = 0 ; { int fd[n >> 1][2] ; unsigned int i = 0 ; for (; i < (n>>1) ; i++) if (pipe(fd[i]) < 0) strerr_diefu1sys(111, "reserve fds") ; if (n & 1) { int lastfd = openb_read("/dev/null") ; if (lastfd < 0) strerr_diefu1sys(111, "reserve last fd") ; fd_close(lastfd) ; j += doit(modif + j, n-1, lastfd) ; } for (i = 0 ; i < (n>>1) ; i++) { fd_close(fd[i][0]) ; fd_close(fd[i][1]) ; j += doit(modif + j, i<<1, fd[i][0]) ; j += doit(modif + j, (i<<1)|1, fd[i][1]) ; } } xmexec_n(argv+2, modif, j, n) ; } } execline-2.8.2.0/src/execline/fdswap.c000066400000000000000000000007311416030414000174620ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #define USAGE "fdswap fd1 fd2 prog..." int main (int argc, char const *const *argv) { unsigned int fd1, fd2 ; PROG = "fdswap" ; if ((argc < 4) || !uint0_scan(argv[1], &fd1) || !uint0_scan(argv[2], &fd2)) strerr_dieusage(100, USAGE) ; if (fd_move2(fd1, fd2, fd2, fd1) < 0) strerr_diefu1sys(111, "swap fds") ; xexec(argv+3) ; } execline-2.8.2.0/src/execline/forbacktickx.c000066400000000000000000000064601416030414000206550ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include #include #define USAGE "forbacktickx [ -p | -o okcode,okcode,... | -x breakcode,breakcode,... ] [ -E | -e ] [ -N | -n ] [ -C | -c ] [ -0 | -d delim ] var { backtickcmd... } command..." #define dieusage() strerr_dieusage(100, USAGE) int main (int argc, char const *const *argv) { char const *delim = "\n" ; char const *codes = 0 ; int crunch = 0, chomp = 1, not = 1, par = 0, doimport = 0 ; PROG = "forbacktickx" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "pNnCc0d:o:x:Ee", &l) ; if (opt == -1) break ; switch (opt) { case 'p' : par = 1 ; break ; case 'N' : chomp = 0 ; break ; case 'n' : chomp = 1 ; break ; case 'C' : crunch = 1 ; break ; case 'c' : crunch = 0 ; break ; case '0' : delim = 0 ; break ; case 'd' : delim = l.arg ; break ; case 'o' : { unsigned short okcodes[256] ; size_t nbc ; if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ; codes = l.arg ; not = 0 ; break ; } case 'x' : { unsigned short okcodes[256] ; size_t nbc ; if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ; codes = l.arg ; not = 1 ; break ; } case 'E' : doimport = 1 ; break ; case 'e' : doimport = 0 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (argc < 2) dieusage() ; if (!argv[0][0]) dieusage() ; if (!argv[1][0]) strerr_dief1x(100, "empty block") ; { unsigned int m = 0, i = 1 ; int fd = dup(0) ; char const *newargv[argc + 19] ; char fmt[UINT_FMT] ; if (fd < 0) { if (errno != EBADF) strerr_diefu1sys(111, "dup stdin") ; } else fmt[uint_fmt(fmt, (unsigned int)fd)] = 0 ; newargv[m++] = EXECLINE_BINPREFIX "pipeline" ; newargv[m++] = "--" ; while (argv[i] && argv[i][0] != EXECLINE_BLOCK_END_CHAR && (!EXECLINE_BLOCK_END_CHAR || (argv[i][0] && argv[i][1]))) newargv[m++] = argv[i++] ; if (!argv[i]) strerr_dief1x(100, "unterminated block") ; newargv[m++] = "" ; i++ ; newargv[m++] = EXECLINE_BINPREFIX "unexport" ; newargv[m++] = "!" ; newargv[m++] = EXECLINE_BINPREFIX "forstdin" ; newargv[m++] = doimport ? "-E" : "-e" ; if (par) newargv[m++] = "-p" ; newargv[m++] = chomp ? "-n" : "-N" ; if (crunch) newargv[m++] = "-C" ; if (!delim) newargv[m++] = "-0" ; else if (strcmp(delim, "\n")) { newargv[m++] = "-d" ; newargv[m++] = delim ; } if (codes) { newargv[m++] = not ? "-x" : "-o" ; newargv[m++] = codes ; } newargv[m++] = "--" ; newargv[m++] = argv[0] ; if (fd < 0) { newargv[m++] = EXECLINE_BINPREFIX "fdclose" ; newargv[m++] = "0" ; } else { newargv[m++] = EXECLINE_BINPREFIX "fdmove" ; newargv[m++] = "0" ; newargv[m++] = fmt ; } while (argv[i]) newargv[m++] = argv[i++] ; newargv[m++] = 0 ; xexec(newargv) ; } } execline-2.8.2.0/src/execline/foreground.c000066400000000000000000000005401416030414000203460ustar00rootroot00000000000000/* ISC license. */ #include #include int main (int argc, char const **argv, char const *const *envp) { int argc1 ; PROG = "foreground" ; argc1 = el_semicolon(++argv) ; if (argc1 >= --argc) strerr_dief1x(100, "unterminated block") ; argv[argc1] = 0 ; el_execsequence(argv, argv+argc1+1, envp) ; } execline-2.8.2.0/src/execline/forstdin.c000066400000000000000000000100541416030414000200250ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define USAGE "forstdin [ -E | -e ] [ -p | -o okcode,okcode,... | -x breakcode,breakcode,... ] [ -N | -n ] [ -C | -c ] [ -0 | -d delim ] var command..." #define dieusage() strerr_dieusage(100, USAGE) static genalloc pids = GENALLOC_ZERO ; /* pid_t */ static int isok (unsigned short *tab, unsigned int n, int code) { unsigned int i = 0 ; for (; i < n ; i++) if ((unsigned short)code == tab[i]) break ; return i < n ; } static void parallel_sigchld_handler (int sig) { pid_t *tab = genalloc_s(pid_t, &pids) ; size_t len = genalloc_len(pid_t, &pids) ; int wstat ; for (;;) { ssize_t r = wait_pids_nohang(tab, len, &wstat) ; if (r <= 0) break ; tab[r-1] = tab[--len] ; } genalloc_setlen(pid_t, &pids, len) ; (void)sig ; } int main (int argc, char const **argv) { stralloc value = STRALLOC_ZERO ; char const *delim = "\n" ; size_t delimlen = 1 ; size_t nbc = 0 ; unsigned short okcodes[256] ; int crunch = 0, chomp = 1, not = 1, eofcode = 1, doimport = 0 ; PROG = "forstdin" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "pNnCc0d:o:x:Ee", &l) ; if (opt == -1) break ; switch (opt) { case 'p' : { if (!genalloc_ready(pid_t, &pids, 1)) strerr_diefu1sys(111, "genalloc_ready") ; break ; } case 'N' : chomp = 0 ; break ; case 'n' : chomp = 1 ; break ; case 'C' : crunch = 1 ; break ; case 'c' : crunch = 0 ; break ; case '0' : delim = "" ; delimlen = 1 ; break ; case 'd' : delim = l.arg ; delimlen = strlen(delim) ; break ; case 'o' : not = 0 ; if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ; break ; case 'x' : not = 1 ; if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ; break ; case 'E' : doimport = 1 ; break ; case 'e' : doimport = 0 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (argc < 2) dieusage() ; if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ; if (pids.s) { if (!sig_catch(SIGCHLD, ¶llel_sigchld_handler)) strerr_diefu1sys(111, "install SIGCHLD handler") ; } for (;;) { pid_t pid ; value.len = 0 ; if (delimlen) { int r = skagetlnsep(buffer_0, &value, delim, delimlen) ; if (!r) break ; else if (r < 0) { if (errno != EPIPE) strerr_diefu1sys(111, "skagetlnsep") ; if (chomp) break ; } if (crunch && value.len == 1) continue ; if (chomp) value.len-- ; } else { size_t unread = 0 ; if (netstring_get(buffer_0, &value, &unread) <= 0) { if (netstring_okeof(buffer_0, unread)) break ; else strerr_diefu1sys(111, "netstring_get") ; } } eofcode = 0 ; if (!stralloc_0(&value)) strerr_diefu1sys(111, "stralloc_0") ; if (pids.s) sig_block(SIGCHLD) ; pid = el_modif_and_spawn(argv + 1, argv[0], value.s, doimport) ; if (!pid) strerr_diefu2sys(111, "spawn ", argv[1]) ; if (pids.s) { if (!genalloc_append(pid_t, &pids, &pid)) strerr_diefu1sys(111, "genalloc_append") ; sig_unblock(SIGCHLD) ; } else { int wstat ; if (wait_pid(pid, &wstat) < 0) strerr_diefu2sys(111, "wait for ", argv[1]) ; if (not == isok(okcodes, nbc, wait_estatus(wstat))) return wait_estatus(wstat) ; } } if (pids.s) { sigset_t empty ; sigemptyset(&empty) ; sig_block(SIGCHLD) ; for (;;) { if (!pids.len) break ; sigsuspend(&empty) ; } } return eofcode ; } execline-2.8.2.0/src/execline/forx.c000066400000000000000000000055661416030414000171670ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include #include #include #define USAGE "forx [ -E | -e ] [ -p ] [ -o okcode,okcode,... | -x breakcode,breakcode,... ] var { values... } command..." #define dieusage() strerr_dieusage(100, USAGE) static int isok (unsigned short const *tab, unsigned int n, int code) { unsigned int i = 0 ; for (; i < n ; i++) if ((unsigned short)code == tab[i]) break ; return i < n ; } static int waitn_code (unsigned short const *tab, unsigned int nbc, pid_t *pids, unsigned int n, int not) { int ok = 1 ; while (n) { int wstat ; unsigned int i = 0 ; pid_t pid = wait_nointr(&wstat) ; if (pid < 0) return -1 ; for (; i < n ; i++) if (pid == pids[i]) break ; if (i < n) { if (not == isok(tab, nbc, wait_estatus(wstat))) ok = 0 ; pids[i] = pids[--n] ; } } return ok ; } int main (int argc, char const **argv) { char const *var ; unsigned short okcodes[256] ; size_t nbc = 0 ; int flagpar = 0, not = 1, doimport = 0 ; unsigned int argc1 ; PROG = "forx" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "po:x:Ee", &l) ; if (opt == -1) break ; switch (opt) { case 'p' : flagpar = 1 ; break ; case 'o' : not = 0 ; if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ; break ; case 'x' : not = 1 ; if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ; break ; case 'E' : doimport = 1 ; break ; case 'e' : doimport = 0 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (argc < 2) dieusage() ; if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ; var = *argv++ ; argc-- ; argc1 = el_semicolon(argv) ; if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ; if (!argc1 || (argc1 + 1 == argc)) return 0 ; { pid_t pids[flagpar ? argc1 : 1] ; for (unsigned int i = 0 ; i < argc1 ; i++) { pid_t pid = el_modif_and_spawn(argv + argc1 + 1, var, argv[i], doimport) ; if (!pid) strerr_diefu2sys(111, "spawn ", argv[argc1+1]) ; if (flagpar) pids[i] = pid ; else { int wstat ; if (wait_pid(pid, &wstat) == -1) strerr_diefu2sys(111, "wait for ", argv[argc1+1]) ; if (not == isok(okcodes, nbc, wait_estatus(wstat))) return wait_estatus(wstat) ; } } if (flagpar) { int r = waitn_code(okcodes, nbc, pids, argc1, not) ; if (r < 0) strerr_diefu1sys(111, "waitn") ; else if (!r) return 1 ; } } return 0 ; } execline-2.8.2.0/src/execline/getcwd.c000066400000000000000000000017531416030414000174600ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #define USAGE "getcwd [ -E | -e ] variable prog..." #define dieusage() strerr_dieusage(100, USAGE) int main (int argc, char const *const *argv) { int doimport = 0 ; stralloc sa = STRALLOC_ZERO ; PROG = "getcwd" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "Ee", &l) ; if (opt == -1) break ; switch (opt) { case 'E' : doimport = 1 ; break ; case 'e' : doimport = 0 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (argc < 2) dieusage() ; if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ; if (sagetcwd(&sa) < 0 || !stralloc_0(&sa)) strerr_diefu1sys(111, "getcwd") ; el_modif_and_exec(argv + 1, argv[0], sa.s, doimport) ; } execline-2.8.2.0/src/execline/getpid.c000066400000000000000000000016511416030414000174540ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #define USAGE "getpid [ -E | -e ] variable prog..." #define dieusage() strerr_dieusage(100, USAGE) int main (int argc, char const *const *argv) { int doimport = 0 ; char fmt[PID_FMT] ; PROG = "getpid" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "Ee", &l) ; if (opt == -1) break ; switch (opt) { case 'E' : doimport = 1 ; break ; case 'e' : doimport = 0 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (argc < 2) dieusage() ; if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ; fmt[pid_fmt(fmt, getpid())] = 0 ; el_modif_and_exec(argv + 1, argv[0], fmt, doimport) ; } execline-2.8.2.0/src/execline/heredoc.c000066400000000000000000000026601416030414000176120ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include #include #define USAGE "heredoc [ -d ] fd string command..." #define dieusage() strerr_dieusage(100, USAGE) int main (int argc, char const *const *argv) { int df = 0 ; PROG = "heredoc" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "d", &l) ; if (opt == -1) break ; switch (opt) { case 'd' : df = 1 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (argc < 3) dieusage() ; { int fd[2] ; unsigned int fdr ; pid_t pid ; if (!uint0_scan(argv[0], &fdr)) strerr_dieusage(100, USAGE) ; if (pipe(fd) < 0) strerr_diefu1sys(111, "pipe") ; pid = df ? doublefork() : fork() ; switch (pid) { case -1: strerr_diefu2sys(111, df ? "double" : "", "fork") ; case 0: { size_t len = strlen(argv[1]) ; PROG = "heredoc (child)" ; fd_close(fd[0]) ; if (allwrite(fd[1], argv[1], len) < len) strerr_diefu1sys(111, "allwrite") ; return 0 ; } } fd_close(fd[1]) ; if (fd_move(fdr, fd[0]) == -1) strerr_diefu2sys(111, "read on fd ", argv[0]) ; } xexec(argv+2) ; } execline-2.8.2.0/src/execline/homeof.c000066400000000000000000000012221416030414000174470ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #define USAGE "homeof user" int main (int argc, char const *const *argv) { struct passwd *pw ; PROG = "homeof" ; if (argc < 2) strerr_dieusage(100, USAGE) ; pw = getpwnam(argv[1]) ; if (!pw) { if (errno) strerr_diefu2sys(111, "get passwd entry for ", argv[1]) ; else strerr_diefu3x(111, "get passwd entry for ", argv[1], ": no such user") ; } if ((buffer_puts(buffer_1small, pw->pw_dir) < 0) || (buffer_putflush(buffer_1small, "\n", 1) < 0)) strerr_diefu1sys(111, "write to stdout") ; return 0 ; } execline-2.8.2.0/src/execline/if.c000066400000000000000000000031721416030414000165760ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #define USAGE "if [ -n ] [ -X ] [ -t | -x exitcode ] { command... }" #define dieusage() strerr_dieusage(100, USAGE) ; int main (int argc, char const **argv, char const *const *envp) { int argc1, wstat ; pid_t pid ; int not = 0, fixed = 0, flagnormalcrash = 0 ; unsigned short e = 1 ; PROG = "if" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "nXtx:", &l) ; if (opt == -1) break ; switch (opt) { case 'n' : not = 1 ; fixed = 1 ; break ; case 'X' : flagnormalcrash = 1 ; break ; case 't' : e = 0 ; fixed = 1 ; break ; case 'x' : if (!ushort_scan(l.arg, &e)) dieusage() ; fixed = 1 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (e > 255) strerr_dief1x(100, "invalid exit code") ; argc1 = el_semicolon(argv) ; if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ; argv[argc1] = 0 ; pid = el_spawn0(argv[0], argv, envp) ; if (!pid) strerr_diefu2sys(111, "spawn ", argv[0]) ; if (wait_pid(pid, &wstat) == -1) strerr_diefu1sys(111, "wait_pid") ; if (!flagnormalcrash && WIFSIGNALED(wstat)) { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, WTERMSIG(wstat))] = 0 ; strerr_dief2x(128 + WTERMSIG(wstat), "child crashed with signal ", fmt) ; } if (not == !wait_estatus(wstat)) return fixed ? e : wait_estatus(wstat) ; xexec0_e(argv+argc1+1, envp) ; } execline-2.8.2.0/src/execline/ifelse.c000066400000000000000000000031521416030414000174450ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #define USAGE "ifelse [ -n ] [ -X ] { command-if } { command-then... } command-else..." int main (int argc, char const **argv, char const *const *envp) { int argc1, argc2, wstat ; int not = 0, flagnormalcrash = 0 ; pid_t pid ; PROG = "ifelse" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "nX", &l) ; if (opt == -1) break ; switch (opt) { case 'n' : not = 1 ; break ; case 'X' : flagnormalcrash = 1 ; break ; default : strerr_dieusage(100, USAGE) ; } } argc -= l.ind ; argv += l.ind ; } argc1 = el_semicolon(argv) ; if (argc1 >= argc) strerr_dief1x(100, "unterminated if block") ; if (argc1 + 1 == argc) strerr_dief1x(100, "then block required") ; argc2 = el_semicolon(argv + argc1 + 1) ; if (argc1 + argc2 + 1 >= argc) strerr_dief1x(100, "unterminated then block") ; argv[argc1] = 0 ; pid = el_spawn0(argv[0], argv, envp) ; if (!pid) strerr_diefu2sys(111, "spawn ", argv[0]) ; if (wait_pid(pid, &wstat) == -1) strerr_diefu2sys(111, "wait for ", argv[0]) ; argv += ++argc1 ; if (!flagnormalcrash && WIFSIGNALED(wstat)) { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, WTERMSIG(wstat))] = 0 ; strerr_dief2x(128 + WTERMSIG(wstat), "child crashed with signal ", fmt) ; } if (not != !wait_estatus(wstat)) argv[argc2] = 0 ; else argv += argc2+1 ; xexec0_e(argv, envp) ; } execline-2.8.2.0/src/execline/ifte.c000066400000000000000000000037541416030414000171350ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include #define USAGE "ifte [ -X ] [ -n ] { command-then... } { command-else... } command-if..." int main (int argc, char const **argv, char const *const *envp) { int argc1, argc2, wstat ; int not = 0, flagnormalcrash = 0 ; pid_t pid ; PROG = "ifte" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "Xn", &l) ; if (opt == -1) break ; switch (opt) { case 'X' : flagnormalcrash = 1 ; break ; case 'n' : not = 1 ; break ; default : strerr_dieusage(100, USAGE) ; } } argc -= l.ind ; argv += l.ind ; } argc1 = el_semicolon(argv) ; if (argc1 >= argc) strerr_dief1x(100, "unterminated then block") ; if (argc1 + 1 == argc) strerr_dief1x(100, "else block required") ; argc2 = el_semicolon(argv + argc1 + 1) ; if (argc1 + argc2 + 1 >= argc) strerr_dief1x(100, "unterminated else block") ; if (argc1 + argc2 + 2 >= argc) strerr_dief1x(100, "empty command-if") ; pid = el_spawn0(argv[argc1 + argc2 + 2], argv + argc1 + argc2 + 2, envp) ; if (!pid) { if (errno == ENOENT && argv[argc1 + argc2 + 2][0] == ' ') strerr_diefu3x(111, "spawn ", argv[argc1 + argc2 + 2], ": name begins with a space, are you trying to spawn a block as your command-if?") ; else strerr_diefu2sys(111, "spawn ", argv[argc1 + argc2 + 2]) ; } if (wait_pid(pid, &wstat) == -1) strerr_diefu2sys(111, "wait for ", argv[argc1 + argc2 + 2]) ; if (!flagnormalcrash && WIFSIGNALED(wstat)) { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, WTERMSIG(wstat))] = 0 ; strerr_dief2x(128 + WTERMSIG(wstat), "child crashed with signal ", fmt) ; } if (not == !wait_estatus(wstat)) { argv += argc1 + 1 ; argv[argc2] = 0 ; } else argv[argc1] = 0 ; xexec0_e(argv, envp) ; } execline-2.8.2.0/src/execline/ifthenelse.c000066400000000000000000000042661416030414000203330ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #define USAGE "ifthenelse [ -X ] { command-if... } { command-then... } { command-else... } [ remainder... ]" int main (int argc, char const **argv, char const *const *envp) { int argc1, argc2, argc3, wstat ; int magicscope = 0, flagnormalcrash = 0 ; pid_t pid ; PROG = "ifthenelse" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "Xs", &l) ; if (opt == -1) break ; switch (opt) { case 'X' : flagnormalcrash = 1 ; break ; case 's' : magicscope = 1 ; break ; default : strerr_dieusage(100, USAGE) ; } } argc -= l.ind ; argv += l.ind ; } argc1 = el_semicolon(argv) ; if (argc1 >= argc) strerr_dief1x(100, "unterminated if block") ; if (argc1 + 1 == argc) strerr_dief1x(100, "then block required") ; argc2 = el_semicolon(argv + argc1 + 1) ; if (argc1 + argc2 + 1 >= argc) strerr_dief1x(100, "unterminated then block") ; argc3 = el_semicolon(argv + argc1 + argc2 + 2) ; if (argc1 + argc2 + argc3 + 2 >= argc) strerr_dief1x(100, "unterminated else block") ; argv[argc1] = 0 ; pid = el_spawn0(argv[0], argv, envp) ; if (!pid) strerr_diefu2sys(111, "spawn ", argv[0]) ; if (wait_pid(pid, &wstat) == -1) strerr_diefu2sys(111, "wait for ", argv[0]) ; argv += argc1 + 1 ; { char const *const *remainder = argv + argc2 + argc3 + 2 ; if (!flagnormalcrash && WIFSIGNALED(wstat)) { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, WTERMSIG(wstat))] = 0 ; strerr_dief2x(128 + WTERMSIG(wstat), "child crashed with signal ", fmt) ; } if (wait_estatus(wstat)) { argv += argc2 + 1 ; argc2 = argc3 ; } if (magicscope) /* undocumented on purpose: powerful but dangerous */ { unsigned int i = 0 ; for (; remainder[i] ; i++) argv[argc2+i] = remainder[i] ; argv[argc2+i] = 0 ; xexec0_e(argv, envp) ; } else { argv[argc2] = 0 ; el_execsequence(argv, remainder, envp) ; } } } execline-2.8.2.0/src/execline/importas.c000066400000000000000000000005111416030414000200300ustar00rootroot00000000000000/* ISC license. */ #include #include "exlsn.h" #define USAGE "importas [ -i | -D default ] [ -u ] [ -N | -n ] [ -s ] [ -C | -c ] [ -d delim ] key var prog..." int main (int argc, char const **argv, char const *const *envp) { PROG = "importas" ; exlsn_main(argc, argv, envp, &exlsn_importas, USAGE) ; } execline-2.8.2.0/src/execline/loopwhilex.c000066400000000000000000000035001416030414000203650ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #define USAGE "loopwhilex [ -n ] [ -o okcode,okcode,... | -x exitcode,exitcode,... ] prog..." #define dieusage() strerr_dieusage(100, USAGE) static int isok (unsigned short *tab, unsigned int n, int code) { unsigned int i = 0 ; for (; i < n ; i++) if ((unsigned short)code == tab[i]) break ; return i < n ; } int main (int argc, char const *const *argv, char const *const *envp) { int wstat ; int not = 0, cont = 1, rev = 0 ; unsigned short okcodes[256] ; size_t nbc = 0 ; PROG = "loopwhilex" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "no:x:", &l) ; if (opt == -1) break ; switch (opt) { case 'n' : not = 1 ; break ; case 'o' : rev = 0 ; if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ; break ; case 'x' : rev = 1 ; if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (!argc) dieusage() ; if (!nbc) { okcodes[0] = 0 ; nbc = 1 ; } else if (rev) not = !not ; while (cont) { pid_t pid = el_spawn0(argv[0], argv, envp) ; if (!pid) { if (errno == ENOENT && argv[0][0] == ' ') strerr_diefu3x(111, "spawn ", argv[0], ": name begins with a space, are you trying to spawn a block as your loop body?") ; else strerr_diefu2sys(111, "spawn ", argv[0]) ; } if (wait_pid(pid, &wstat) < 0) strerr_diefu1sys(111, "wait_pid") ; cont = not != isok(okcodes, nbc, wait_estatus(wstat)) ; } return wait_estatus(wstat) ; } execline-2.8.2.0/src/execline/multidefine.c000066400000000000000000000005101416030414000204760ustar00rootroot00000000000000/* ISC license. */ #include #include "exlsn.h" #define USAGE "multidefine [ -0 ] [ -r ] [ -N | -n ] [ -C | -c ] [ -d delim ] value { vars... } prog..." int main (int argc, char const **argv, char const *const *envp) { PROG = "multidefine" ; exlsn_main(argc, argv, envp, &exlsn_multidefine, USAGE) ; } execline-2.8.2.0/src/execline/multisubstitute.c000066400000000000000000000030101416030414000214550ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include "exlsn.h" #define USAGE "see http://skarnet.org/software/execline/multisubstitute.html" static char const *const commands[] = { "define", "importas", "elglob", "elgetpositionals", "multidefine", 0 } ; static exls_func_ref const functions[] = { &exlsn_define, &exlsn_importas, &exlsn_elglob, &exlsn_exlp, &exlsn_multidefine, 0 } ; int main (int argc, char const **argv, char const *const *envp) { exlsn_t info = EXLSN_ZERO ; int argc1 ; PROG = "multisubstitute" ; if (!--argc) strerr_dieusage(100, USAGE) ; argc1 = el_semicolon(++argv) ; if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ; if (argc1 + 1 == argc) strerr_dieusage(100, USAGE) ; while (argc1) { int n ; unsigned int i = 0 ; for (; commands[i] ; i++) if (!strcmp(*argv, commands[i])) break ; if (!commands[i]) strerr_dief3x(100, "syntax error: unrecognized", " directive ", *argv) ; n = (*(functions[i]))(argc1, argv, envp, &info) ; if (n < 0) switch (n) { case -3 : strerr_dief3x(100, "syntax error at", " directive ", commands[i]) ; case -2 : strerr_dief3x(100, "wrong key for", " directive ", commands[i]) ; case -1 : strerr_diefu3sys(111, "run", " directive ", commands[i]) ; default : strerr_dief3x(111, "unknown error with", " directive ", commands[i]) ; } argv += n ; argc1 -= n ; argc -= n ; } el_substandrun(argc-1, argv+1, envp, &info) ; } execline-2.8.2.0/src/execline/pipeline.c000066400000000000000000000035551416030414000200120ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include #define USAGE "pipeline [ -d ] [ -r | -w ] { command... } command..." #define dieusage() strerr_dieusage(100, USAGE) int main (int argc, char const **argv, char const *const *envp) { int df = 0, w = 0 ; PROG = "pipeline" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "drw", &l) ; if (opt == -1) break ; switch (opt) { case 'd' : df = 1 ; break ; case 'r' : w = 0 ; break ; case 'w' : w = 1 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } { pid_t pid ; int fd ; int argc1 = el_semicolon(argv) ; if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ; if (argc1 + 1 == argc) strerr_dief1x(100, "empty remainder") ; argv[argc1] = 0 ; if (df) { int p[2] ; if (pipe(p) < 0) strerr_diefu1sys(111, "create pipe") ; pid = doublefork() ; switch (pid) { case -1: strerr_diefu1sys(111, "doublefork") ; case 0: PROG = "pipeline (grandchild)" ; fd_close(p[w]) ; if (fd_move(!w, p[!w]) < 0) strerr_diefu1sys(111, "fd_move") ; xexec0_e(argv, envp) ; } fd_close(p[!w]) ; fd = p[w] ; } else { pid = el_spawn1(argv[0], argv, envp, &fd, !w) ; if (!pid) strerr_diefu2sys(111, "spawn ", argv[0]) ; } if (fd_move(w, fd) < 0) strerr_diefu1sys(111, "fd_move") ; if (w == fd) uncoe(fd) ; { char fmt[PID_FMT + 2] = "!=" ; size_t i = 2 ; i += pid_fmt(fmt+i, pid) ; fmt[i++] = 0 ; xmexec_en(argv + argc1 + 1, envp, fmt, i, 1) ; } } } execline-2.8.2.0/src/execline/piperw.c000066400000000000000000000013031416030414000175000ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #define USAGE "piperw fdr fdw prog..." int main (int argc, char const *const *argv) { int fdr, fdw ; int p[2] ; PROG = "piperw" ; if ((argc < 4) || !uint0_scan(argv[1], (unsigned int *)&fdr) || !uint0_scan(argv[2], (unsigned int *)&fdw) || (fdr == fdw)) strerr_dieusage(100, USAGE) ; if (pipe(p) == -1) strerr_diefu1sys(111, "create pipe") ; if (p[1] == fdr) p[1] = dup(p[1]) ; if ((p[1] == -1) || (fd_move(fdr, p[0]) == -1) || (fd_move(fdw, p[1]) == -1)) strerr_diefu1sys(111, "move fds") ; xexec(argv+3) ; } execline-2.8.2.0/src/execline/redirfd.c000066400000000000000000000040611416030414000176150ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #define USAGE "redirfd -[ r | w | u | a | x ] [ -n ] [ -b ] fd file prog..." #define dieusage() strerr_dieusage(100, USAGE) int main (int argc, char const *const *argv) { int fd, fd2 ; unsigned int flags = 0 ; int what = -1 ; int changemode = 0 ; PROG = "redirfd" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "rwuaxnb", &l) ; if (opt == -1) break ; switch (opt) { case 'r' : what = O_RDONLY ; flags &= ~(O_APPEND|O_CREAT|O_TRUNC|O_EXCL) ; break ; case 'w' : what = O_WRONLY ; flags |= O_CREAT|O_TRUNC ; flags &= ~(O_APPEND|O_EXCL) ; break ; case 'u' : what = O_RDWR ; flags &= ~(O_APPEND|O_CREAT|O_TRUNC|O_EXCL) ; break ; case 'a' : what = O_WRONLY ; flags |= O_CREAT|O_APPEND ; flags &= ~(O_TRUNC|O_EXCL) ; break ; case 'x' : what = O_WRONLY ; flags |= O_CREAT|O_EXCL ; flags &= ~(O_APPEND|O_TRUNC) ; break ; case 'n' : flags |= O_NONBLOCK ; break ; case 'b' : changemode = 1 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if ((argc < 3) || (what == -1)) dieusage() ; if (!uint0_scan(argv[0], (unsigned int *)&fd)) dieusage() ; flags |= what ; fd2 = open3(argv[1], flags, 0666) ; if ((fd2 == -1) && (what == O_WRONLY) && (errno == ENXIO)) { int fdr = open_read(argv[1]) ; if (fdr == -1) strerr_diefu2sys(111, "open_read ", argv[1]) ; fd2 = open3(argv[1], flags, 0666) ; fd_close(fdr) ; } if (fd2 == -1) strerr_diefu2sys(111, "open ", argv[1]) ; if (fd_move(fd, fd2) == -1) { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, fd2)] = 0 ; strerr_diefu4sys(111, "move fd ", fmt, " to fd ", argv[0]) ; } if (changemode) { if (((flags & O_NONBLOCK) ? ndelay_off(fd) : ndelay_on(fd)) < 0) strerr_diefu1sys(111, "change blocking mode") ; } xexec(argv+2) ; } execline-2.8.2.0/src/execline/runblock.c000066400000000000000000000112031416030414000200110ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include #include #include #define USAGE "runblock [ -P ] [ -n argshift ] [ -r ] n cmd..." #define dieusage() strerr_dieusage(100, USAGE) int main (int argc, char const *const *argv, char const *const *envp) { genalloc v = GENALLOC_ZERO ; /* array of char const * */ unsigned int n, sharp ; unsigned int m = 0 ; unsigned int strict = el_getstrict() ; int flagnopop = 0, flagr = 0 ; PROG = "runblock" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "Prn:", &l) ; if (opt == -1) break ; switch (opt) { case 'P' : flagnopop = 1 ; break ; case 'r' : flagr = 1 ; break ; case 'n' : if (!uint0_scan(l.arg, &m)) dieusage() ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (!argc--) dieusage() ; if (!uint0_scan(*argv++, &n) || (!n && !flagr)) dieusage() ; { char const *x = getenv("#") ; if (!x) strerr_dienotset(100, "#") ; if (!uint0_scan(x, &sharp)) strerr_dieinvalid(100, "#") ; } /* Skip n-1 blocks (n if flagr) */ { unsigned int i = 1 ; for (; i < n + flagr ; i++) { unsigned int base = m ; for (;;) { char const *x ; char fmt[UINT_FMT] ; if (++m > sharp) strerr_dief1x(100, "too few arguments") ; fmt[uint_fmt(fmt, m)] = 0 ; x = getenv(fmt) ; if (!x) strerr_dienotset(100, fmt) ; if ((x[0] == EXECLINE_BLOCK_END_CHAR) && (!EXECLINE_BLOCK_END_CHAR || !x[1])) break ; if ((x[0] != EXECLINE_BLOCK_QUOTE_CHAR) && strict) { char fmtb[UINT_FMT] ; char fmti[UINT_FMT] ; fmti[uint_fmt(fmti, i)] = 0 ; fmtb[uint_fmt(fmtb, m - base)] = 0 ; if (strict == 1) strerr_warnw6x("unquoted positional ", x, " at block ", fmti, " position ", fmtb) ; else strerr_dief6x(100, "unquoted positional ", x, " at block ", fmti, " position ", fmtb) ; } } } } /* First put args, if any, into v */ if (!genalloc_ready(char const *, &v, argc)) strerr_diefu1sys(111, "genalloc_ready") ; for (unsigned int i = 0 ; i < (unsigned int)argc ; i++) genalloc_append(char const *, &v, argv + i) ; if (flagr) /* put remainder envvars into v */ { if (++m > sharp) return 0 ; if (!genalloc_readyplus(char const *, &v, sharp - m + 2)) strerr_diefu1sys(111, "genalloc_readyplus") ; for (; m <= sharp ; m++) { char const *x ; char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, m)] = 0 ; x = getenv(fmt) ; if (!x) strerr_dienotset(100, fmt) ; genalloc_append(char const *, &v, &x) ; } } else /* put envvars from nth block into v */ { unsigned int base = m ; for (;;) { char const *x ; char fmt[UINT_FMT] ; if (++m > sharp) strerr_dief1x(100, "too few arguments") ; fmt[uint_fmt(fmt, m)] = 0 ; x = getenv(fmt) ; if (!x) strerr_dienotset(100, fmt) ; if ((x[0] == EXECLINE_BLOCK_END_CHAR) && (!EXECLINE_BLOCK_END_CHAR || !x[1])) break ; if (x[0] != EXECLINE_BLOCK_QUOTE_CHAR) { if (strict) { char fmtb[UINT_FMT] ; char fmtn[UINT_FMT] ; fmtn[uint_fmt(fmtn, n)] = 0 ; fmtb[uint_fmt(fmtb, m - base)] = 0 ; if (strict == 1) strerr_warnw6x("unquoted positional ", x, " at block ", fmtn, " position ", fmtb) ; else strerr_dief6x(100, "unquoted positional ", x, " at block ", fmtn, " position ", fmtb) ; } } else x++ ; if (!genalloc_append(char const *, &v, &x)) strerr_diefu1sys(111, "envalloc_catb") ; } } { char const *z = 0 ; if (!genalloc_append(char const *, &v, &z)) strerr_diefu1sys(111, "genalloc_append") ; } if (flagnopop) /* exec now */ xexec_e(genalloc_s(char const *, &v), envp) ; else /* popenv, then exec */ { char const *list[11] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "#" } ; size_t envlen = env_len(envp) ; int popped = el_popenv(&satmp, envp, envlen, list, 11) ; if (popped < 0) strerr_diefu1sys(111, "pop environment") ; else { char const *w[envlen - popped + 1] ; if (!env_make(w, envlen - popped, satmp.s, satmp.len)) strerr_diefu1sys(111, "env_make") ; w[envlen - popped] = 0 ; xexec_e(genalloc_s(char const *, &v), w) ; } } } execline-2.8.2.0/src/execline/shift.c000066400000000000000000000057621416030414000173240ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #define USAGE "shift [ -n arg# ] [ -b block# ] prog..." #define dieusage() strerr_dieusage(100, USAGE) int main (int argc, char const *const *argv) { unsigned int strict = el_getstrict() ; unsigned int b = 0 ; unsigned int n = 0 ; unsigned int sharp ; unsigned int i = 0 ; PROG = "shift" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "n:b:", &l) ; if (opt == -1) break ; switch (opt) { case 'n' : if (!uint0_scan(l.arg, &n)) dieusage() ; i = 1 ; break ; case 'b' : if (!uint0_scan(l.arg, &b)) dieusage() ; i = 1 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (!argc) dieusage() ; if (i) i = 0 ; else n = 1 ; { char const *x = getenv("#") ; if (!x) strerr_dienotset(100, "#") ; if (!uint0_scan(x, &sharp)) strerr_dieinvalid(100, "#") ; } /* Shift n args */ if (n > sharp) { if (strict) { char fmtn[UINT_FMT] ; char fmtsharp[UINT_FMT] ; fmtn[uint_fmt(fmtn, n)] = 0 ; fmtsharp[uint_fmt(fmtsharp, sharp)] = 0 ; if (strict == 1) strerr_warnwu5x("shift", " ", fmtn, " arguments: got ", fmtsharp) ; else strerr_diefu5x(100, "shift", " ", fmtn, " arguments: got ", fmtsharp) ; } n = sharp ; } /* Shift b blocks */ for (; i < b ; i++) { for (;;) { char const *x ; unsigned int base = n ; char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, ++n)] = 0 ; if (n > sharp) { char fmti[UINT_FMT] ; fmti[uint_fmt(fmt, i)] = 0 ; strerr_diefu6x(100, "shift", " block ", fmti, ": too few arguments (", fmt, ")") ; } x = getenv(fmt) ; if (!x) strerr_dienotset(100, fmt) ; if ((x[0] == EXECLINE_BLOCK_END_CHAR) && (!EXECLINE_BLOCK_END_CHAR || !x[1])) break ; if ((x[0] != EXECLINE_BLOCK_QUOTE_CHAR) && strict) { char fmti[UINT_FMT] ; char fmtp[UINT_FMT] ; fmti[uint_fmt(fmti, i)] = 0 ; fmtp[uint_fmt(fmtp, n - base)] = 0 ; if (strict == 1) strerr_warnw6x("unquoted positional ", x, " at block ", fmti, " position ", fmtp) ; else strerr_dief6x(100, "unquoted positional ", x, " at block ", fmti, " position ", fmtp) ; } } } /* n = shift value; modify the env */ { unsigned int i = 1 ; char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, sharp - n)] = 0 ; if (!env_mexec("#", fmt)) strerr_diefu1sys(111, "env_mexec") ; for (; i <= sharp ; i++) { char fmu[UINT_FMT] ; fmt[uint_fmt(fmt, i)] = 0 ; fmu[uint_fmt(fmu, i + n)] = 0 ; if (!env_mexec(fmt, i <= (sharp - n) ? getenv(fmu) : 0)) strerr_diefu1sys(111, "modify environment") ; } } xmexec(argv) ; } execline-2.8.2.0/src/execline/trap.c000066400000000000000000000103501416030414000171420ustar00rootroot00000000000000/* ISC license. */ #include /* for SKALIBS_NSIG to work */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define USAGE "trap [ -x ] { signal { cmdline } ... } prog..." #define dieusage() strerr_dieusage(100, USAGE) ; static pid_t pids[SKALIBS_NSIG + 1] ; static char const *const *argvs[SKALIBS_NSIG] ; /* initted with 0s */ static inline void action (unsigned int i, char const *const *envp, size_t envlen) { if (argvs[i]) { if (!pids[i]) { char const *newenvp[envlen + 3] ; char modif[9 + PID_FMT + UINT_FMT] = "!=" ; size_t m = 2 ; m += pid_fmt(modif + m, pids[SKALIBS_NSIG]) ; modif[m++] = 0 ; memcpy(modif + m, "SIGNAL=", 7) ; m += 7 ; m += uint_fmt(modif + m, i) ; modif[m++] = 0 ; if (!env_mergen(newenvp, envlen + 3, envp, envlen, modif, m, 2)) strerr_diefu1sys(111, "adjust environment for child") ; pids[i] = child_spawn0(argvs[i][0], argvs[i], newenvp) ; if (!pids[i]) strerr_diefu2sys(111, "spawn ", argvs[i][0]) ; } } else kill(pids[SKALIBS_NSIG], i) ; } int main (int argc, char const **argv, char const *const *envp) { size_t envlen = env_len(envp) ; iopause_fd x = { .events = IOPAUSE_READ } ; sigset_t full, set ; int xfersigs = 0 ; unsigned int argc1 ; unsigned int i = 0 ; PROG = "trap" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "xt:", &l) ; if (opt == -1) break ; switch (opt) { case 'x' : xfersigs = 1 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (!argc) dieusage() ; argc1 = el_semicolon(argv) ; if (!argc1) strerr_dief1x(100, "empty block") ; if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ; if (argc1 + 1 == argc) dieusage() ; argv[argc1] = 0 ; sigfillset(&full) ; sigdelset(&full, SIGKILL) ; sigdelset(&full, SIGSTOP) ; while (i < argc1) { unsigned int argc2 ; int sig = 0 ; if (!sig0_scan(argv[i], &sig) && strcasecmp(argv[i], "default")) strerr_dief3x(100, "unrecognized", " directive: ", argv[i]) ; argc2 = el_semicolon(argv + ++i) ; if (i + argc2 >= argc1) strerr_dief3x(100, "unterminated", " internal block for directive ", argv[i-1]) ; if (argvs[sig]) strerr_dief3x(100, "duplicate", " directive: ", argv[i-1]) ; if (!sig || (sig != SIGCHLD && sigismember(&full, sig) > 0)) argvs[sig] = argv + i ; else { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, (unsigned int)sig)] = 0 ; strerr_dief5x(100, "SIG", sig_name(sig), " (", fmt, ") cannot be trapped") ; } argv[i + argc2] = 0 ; i += argc2 + 1 ; } if (argvs[0]) for (i = 1 ; i < SKALIBS_NSIG ; i++) if (!argvs[i] && sigismember(&full, i) > 0) argvs[i] = argvs[0] ; if (xfersigs) set = full ; else { sigemptyset(&set) ; sigaddset(&set, SIGCHLD) ; for (i = 1 ; i < SKALIBS_NSIG ; i++) if (argvs[i]) sigaddset(&set, i) ; } x.fd = selfpipe_init() ; if (x.fd < 0) strerr_diefu1sys(111, "selfpipe_init") ; if (!selfpipe_trapset(&set)) strerr_diefu1sys(111, "trap signals") ; pids[SKALIBS_NSIG] = child_spawn0(argv[argc1 + 1], argv + argc1 + 1, envp) ; if (!pids[SKALIBS_NSIG]) strerr_diefu2sys(111, "spawn ", argv[argc1 + 1]) ; loop: if (iopause_g(&x, 1, 0) < 0) strerr_diefu1sys(111, "iopause") ; for (;;) { int r = selfpipe_read() ; switch (r) { case -1 : strerr_diefu1sys(111, "selfpipe_read") ; case 0 : goto loop ; case SIGCHLD : for (;;) { int wstat ; ssize_t id = wait_pids_nohang(pids, SKALIBS_NSIG + 1, &wstat) ; if (id < 0 && errno != ECHILD) strerr_diefu1sys(111, "wait") ; if (id <= 0) break ; pids[id - 1] = 0 ; if (id == SKALIBS_NSIG + 1) return wait_estatus(wstat) ; } break ; default : action(r, envp, envlen) ; } } } execline-2.8.2.0/src/execline/tryexec.c000066400000000000000000000031731416030414000176640ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #define USAGE "tryexec [ -n ] [ -c ] [ -l ] [ -a argv0 ] { command... } remainder..." int main (int argc, char const **argv, char const *const *envp) { char const *env_zero[1] = { 0 } ; char const *executable = 0 ; char const *argv0 = 0 ; char const **dom = 0 ; char const **sub = 0 ; char const *const *dom_envp = envp ; int not = 0, dash = 0 ; PROG = "tryexec" ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "ncla:", &l) ; if (opt == -1) break ; switch (opt) { case 'n' : not = 1 ; break ; case 'c' : dom_envp = env_zero ; break ; case 'l' : dash = 1 ; break ; case 'a' : argv0 = l.arg ; break ; default : strerr_dieusage(100, USAGE) ; } } argc -= l.ind ; argv += l.ind ; } { int argc1 = el_semicolon(argv) ; if (!argc1) strerr_dief1x(100, "empty block") ; if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ; if (not && argc1 == argc - 1) strerr_dief1x(100, "empty remainder not allowed with -n") ; argv[argc1] = 0 ; dom = argv + not * (argc1 + 1) ; sub = argv + !not * (argc1 + 1) ; } executable = dom[0] ; if (argv0) dom[0] = argv0 ; if (dash) { size_t n = strlen(dom[0]) ; char dashed[n+2] ; dashed[0] = '-' ; memcpy(dashed+1, dom[0], n+1) ; dom[0] = dashed ; exec_ae(executable, dom, dom_envp) ; } else exec_ae(executable, dom, dom_envp) ; xexec0_e(sub, envp) ; } execline-2.8.2.0/src/execline/unexport.c000066400000000000000000000007111416030414000200600ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #define USAGE "unexport variable prog..." int main (int argc, char const *const *argv) { size_t len ; PROG = "unexport" ; if (argc < 3) strerr_dieusage(100, USAGE) ; len = strlen(argv[1]) ; if (memchr(argv[1], '=', len)) strerr_dief2x(100, "invalid variable name: ", argv[1]) ; xmexec_n(argv+2, argv[1], len+1, 1) ; } execline-2.8.2.0/src/execline/wait.c000066400000000000000000000075771416030414000171610ustar00rootroot00000000000000/* ISC license. */ #include #include #include #ifdef EXECLINE_PEDANTIC_POSIX #include #endif #include #include #include #include #include #include #include #include #include #define USAGE "wait [ -I | -i ] [ -r | -t timeout ] { pids... }" #define dieusage() strerr_dieusage(100, USAGE) typedef int ac_func (pid_t *, unsigned int *, int *) ; typedef ac_func *ac_func_ref ; static inline int waitall (void) { int wstat = 0 ; pid_t r = 1 ; while (r > 0) r = wait(&wstat) ; if (r < 0) { if (errno != ECHILD) strerr_diefu1sys(111, "wait") ; else return 127 ; } return wait_estatus(wstat) ; } static int waitany (pid_t *dummytab, unsigned int *dummyn, int *res) { int wstat ; pid_t r = 1 ; while (r > 0) r = wait_nohang(&wstat) ; if (!r) return (*res = wait_estatus(wstat), 1) ; if (errno != ECHILD) strerr_diefu1sys(111, "wait") ; *res = 127 ; (void)dummytab ; (void)dummyn ; return 0 ; } static int waitintab (pid_t *tab, unsigned int *n, int *res) { unsigned int i = 0 ; for (; i < *n ; i++) { int wstat ; pid_t r = waitpid(tab[i], &wstat, WNOHANG) ; if (r) { if (r < 0) { if (errno == ECHILD) *res = 127 ; else strerr_diefu1sys(111, "waitpid") ; } else *res = wait_estatus(wstat) ; tab[i--] = tab[--(*n)] ; } } return !!*n ; } static inline void handle_signals (void) { for (;;) switch (selfpipe_read()) { case -1 : strerr_diefu1sys(111, "read selfpipe") ; case 0 : return ; case SIGCHLD : break ; default: strerr_dief1x(101, "internal inconsistency. Please submit a bug-report.") ; } } static inline int mainloop (tain *deadline, int insist, ac_func_ref f, pid_t *tab, unsigned int *n) { iopause_fd x = { .events = IOPAUSE_READ } ; int res = 0 ; x.fd = selfpipe_init() ; if (x.fd < 0) strerr_diefu1sys(111, "create selfpipe") ; if (!selfpipe_trap(SIGCHLD)) strerr_diefu1sys(111, "trap SIGCHLD") ; tain_now_set_stopwatch_g() ; tain_add_g(deadline, deadline) ; while ((*f)(tab, n, &res)) { int r = iopause_g(&x, 1, deadline) ; if (r < 0) strerr_diefu1sys(111, "iopause") ; else if (!r) { if (!insist) break ; errno = ETIMEDOUT ; strerr_diefu1sys(1, "wait") ; } else handle_signals() ; } selfpipe_finish() ; return res ; } int main (int argc, char const **argv) { tain tto ; int argc1 ; int hastimeout = 0 ; int insist = 0 ; int r ; int hasblock ; PROG = "wait" ; #ifdef EXECLINE_PEDANTIC_POSIX setlocale(LC_ALL, "") ; /* but of course, dear POSIX */ #endif { subgetopt l = SUBGETOPT_ZERO ; unsigned int t = 0 ; for (;;) { int opt = subgetopt_r(argc, argv, "iIrt:", &l) ; if (opt == -1) break ; switch (opt) { case 'i' : insist = 1 ; break ; case 'I' : insist = 0 ; break ; case 'r' : t = 0 ; hastimeout = 1 ; break ; case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; hastimeout = 1 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; if (hastimeout) tain_from_millisecs(&tto, t) ; else tto = tain_infinite_relative ; } argc1 = el_semicolon(argv) ; if (argc1 >= argc) { hasblock = 0 ; argc1 = argc ; } else hasblock = 1 ; if (!argc1 && !hastimeout) r = waitall() ; else { ac_func_ref f = argc1 ? &waitintab : &waitany ; unsigned int n = argc1 ? (unsigned int)argc1 : 1 ; pid_t tab[n] ; if (argc1) { unsigned int i = 0 ; for (; i < n ; i++) if (!pid0_scan(argv[i], tab+i)) strerr_dieusage(100, USAGE) ; } r = mainloop(&tto, insist, f, tab, &n) ; } if (!hasblock) return r ; xexec0(argv + argc1 + 1) ; } execline-2.8.2.0/src/execline/withstdinas.c000066400000000000000000000032621416030414000205410ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #define USAGE "withstdinas [ -i | -I | -D default ] [ -N | -n ] [ -E | -e ] var remainder..." #define dieusage() strerr_dieusage(100, USAGE) int main (int argc, char const *const *argv) { subgetopt localopt = SUBGETOPT_ZERO ; stralloc value = STRALLOC_ZERO ; int insist = 0, chomp = 1, doimport = 0 ; char const *def = 0 ; char const *val ; PROG = "withstdinas" ; for (;;) { int opt = subgetopt_r(argc, argv, "iINnD:Ee", &localopt) ; if (opt < 0) break ; switch (opt) { case 'i' : insist = 2 ; break ; case 'I' : insist = 1 ; break ; case 'N' : chomp = 0 ; break ; case 'n' : chomp = 1 ; break ; case 'D' : def = localopt.arg ; break ; case 'E' : doimport = 1 ; break ; case 'e' : doimport = 0 ; break ; default : dieusage() ; } } argc -= localopt.ind ; argv += localopt.ind ; if (!argc) dieusage() ; if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ; if (!slurp(&value, 0) || !stralloc_0(&value)) strerr_diefu1sys(111, "slurp") ; val = value.s ; if (strlen(value.s) < value.len - 1) { if (insist >= 2) strerr_dief1x(1, "stdin contained a null character") ; else if (insist) val = 0 ; else if (def) { val = def ; strerr_warnw2x("stdin contained a null character", " - using default instead") ; } } else if (chomp && (value.s[value.len - 2] == '\n')) value.s[--value.len - 1] = 0 ; el_modif_and_exec(argv + 1, argv[0], val, doimport) ; } execline-2.8.2.0/src/include-local/000077500000000000000000000000001416030414000167505ustar00rootroot00000000000000execline-2.8.2.0/src/include-local/exlsn.h000066400000000000000000000022061416030414000202520ustar00rootroot00000000000000/* ISC license. */ #ifndef EXLSN_H #define EXLSN_H #include #include #include typedef struct exlsn_s exlsn_t, *exlsn_t_ref ; struct exlsn_s { stralloc vars ; stralloc values ; genalloc data ; /* array of elsubst */ stralloc modifs ; } ; #define EXLSN_ZERO { .vars = STRALLOC_ZERO, .values = STRALLOC_ZERO, .data = GENALLOC_ZERO, .modifs = STRALLOC_ZERO } extern void exlsn_free (exlsn_t *) ; typedef int exls_func (int, char const **, char const *const *, exlsn_t *) ; typedef exls_func *exls_func_ref ; extern exls_func exlsn_define ; extern exls_func exlsn_importas ; extern exls_func exlsn_elglob ; extern exls_func exlsn_exlp ; extern exls_func exlsn_multidefine ; extern int exlp (unsigned int, char const *const *, exlsn_t *) ; extern void el_substandrun (int, char const *const *, char const *const *, exlsn_t const *) gccattr_noreturn ; extern void el_substandrun_str (stralloc *, size_t, char const *const *, exlsn_t const *) gccattr_noreturn ; extern void exlsn_main (int, char const **, char const *const *, exls_func *, char const *) gccattr_noreturn ; #endif execline-2.8.2.0/src/include/000077500000000000000000000000001416030414000156605ustar00rootroot00000000000000execline-2.8.2.0/src/include/execline/000077500000000000000000000000001416030414000174545ustar00rootroot00000000000000execline-2.8.2.0/src/include/execline/execline.h000066400000000000000000000043731416030414000214300ustar00rootroot00000000000000/* ISC license. */ #ifndef EXECLINE_H #define EXECLINE_H #include #include #include #include #define EXECLINE_BLOCK_QUOTE_STRING " " #define EXECLINE_BLOCK_QUOTE_CHAR ' ' #define EXECLINE_BLOCK_END_STRING "" #define EXECLINE_BLOCK_END_CHAR '\0' /* Parsing */ typedef int el_chargen_func (unsigned char *, void *) ; typedef el_chargen_func *el_chargen_func_ref ; extern int el_parse (stralloc *, el_chargen_func_ref, void *) ; extern int el_parse_from_string (stralloc *, char const *) ; extern int el_parse_from_buffer (stralloc *, buffer *) ; /* Basics */ extern int el_vardupl (char const *, char const *, size_t) gccattr_pure ; extern unsigned int el_getstrict (void) gccattr_const ; /* Environment shifting */ extern int el_pushenv (stralloc *, char const *const *, size_t, char const *const *, size_t) ; extern int el_popenv (stralloc *, char const *const *, size_t, char const *const *, size_t) ; /* Sequence */ extern pid_t el_spawn0 (char const *, char const *const *, char const *const *) ; extern pid_t el_spawn1 (char const *, char const *const *, char const *const *, int *, int) ; extern void el_execsequence (char const *const *, char const *const *, char const *const *) gccattr_noreturn ; /* Block unquoting */ extern int el_semicolon (char const **) ; /* Value transformation */ typedef struct eltransforminfo_s eltransforminfo_t, *eltransforminfo_t_ref ; struct eltransforminfo_s { char const *delim ; unsigned int crunch : 1 ; unsigned int chomp : 1 ; unsigned int split : 1 ; } ; #define ELTRANSFORMINFO_ZERO { .delim = " \n\r\t", .crunch = 0, .chomp = 0, .split = 0 } extern int el_transform (stralloc *, size_t, eltransforminfo_t const *) ; /* Substitution */ typedef struct elsubst_s elsubst_t, *elsubst_t_ref ; struct elsubst_s { size_t var ; size_t value ; unsigned int n ; } ; extern int el_substitute (stralloc *, char const *, size_t, char const *, char const *, elsubst_t const *, unsigned int) ; /* Execution with or without substitution */ extern void el_modif_and_exec (char const *const *, char const *, char const *, int) gccattr_noreturn ; extern pid_t el_modif_and_spawn (char const *const *, char const *, char const *, int) ; #endif execline-2.8.2.0/src/libexecline/000077500000000000000000000000001416030414000165205ustar00rootroot00000000000000execline-2.8.2.0/src/libexecline/deps-lib/000077500000000000000000000000001416030414000202175ustar00rootroot00000000000000execline-2.8.2.0/src/libexecline/deps-lib/execline000066400000000000000000000006201416030414000217340ustar00rootroot00000000000000el_execsequence.o el_getstrict.o el_modif_and_exec.o el_modif_and_spawn.o el_parse.o el_parse_from_buffer.o el_parse_from_string.o el_popenv.o el_pushenv.o el_semicolon.o el_spawn0.o el_spawn1.o el_substandrun.o el_substandrun_str.o el_substitute.o el_transform.o el_vardupl.o exlsn_define.o exlsn_elglob.o exlsn_importas.o exlsn_multidefine.o exlsn_exlp.o exlsn_main.o exlsn_free.o exlp.o -lskarnet execline-2.8.2.0/src/libexecline/el_execsequence.c000066400000000000000000000013431416030414000220220ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include void el_execsequence (char const *const *argv1, char const *const *argv2, char const *const *envp) { size_t j = 2 ; char fmt[UINT_FMT + 1] = "?=" ; pid_t pid = el_spawn0(argv1[0], argv1, envp) ; if (!pid) { strerr_warnwu2sys("spawn ", argv1[0]) ; memcpy(fmt+2, "127", 3) ; j += 3 ; } else { int wstat ; if (wait_pid(pid, &wstat) < 0) strerr_diefu2sys(111, "wait for ", argv1[0]) ; j += uint_fmt(fmt + j, wait_status(wstat)) ; } fmt[j++] = 0 ; xmexec0_en(argv2, envp, fmt, j, 1) ; } execline-2.8.2.0/src/libexecline/el_getstrict.c000066400000000000000000000005171416030414000213570ustar00rootroot00000000000000/* ISC license. */ #include #include #include unsigned int el_getstrict (void) { static unsigned int strict = 0 ; static int first = 1 ; if (first) { char const *x = getenv("EXECLINE_STRICT") ; first = 0 ; if (x) uint0_scan(x, &strict) ; } return strict ; } execline-2.8.2.0/src/libexecline/el_modif_and_exec.c000066400000000000000000000017401416030414000222720ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include void el_modif_and_exec (char const *const *argv, char const *var, char const *value, int doimport) { size_t varlen = strlen(var) ; size_t modiflen = value ? varlen + strlen(value) + 2 : 1 ; char modifs[modiflen] ; if (value) { memcpy(modifs, var, varlen) ; modifs[varlen] = '=' ; memcpy(modifs + varlen + 1, value, modiflen - varlen - 1) ; } if (doimport) { size_t m = 0 ; char const *newargv[env_len(argv) + 6] ; newargv[m++] = EXECLINE_BINPREFIX "importas" ; newargv[m++] = "-ui" ; newargv[m++] = "--" ; newargv[m++] = var ; newargv[m++] = var ; while (*argv) newargv[m++] = *argv++ ; newargv[m++] = 0 ; xmexec0_n(newargv, value ? modifs : var, value ? modiflen : varlen + 1, 1) ; } else xmexec0_n(argv, value ? modifs : var, value ? modiflen : varlen + 1, 1) ; } execline-2.8.2.0/src/libexecline/el_modif_and_spawn.c000066400000000000000000000022261416030414000224760ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include pid_t el_modif_and_spawn (char const *const *argv, char const *var, char const *value, int doimport) { size_t varlen = strlen(var) ; size_t modiflen = value ? varlen + strlen(value) + 2 : 1 ; size_t envlen = env_len((char const *const *)environ) ; char const *newenv[envlen + 2] ; char modifs[modiflen] ; if (value) { memcpy(modifs, var, varlen) ; modifs[varlen] = '=' ; memcpy(modifs + varlen + 1, value, modiflen - varlen - 1) ; } if (!env_mergen(newenv, envlen + 2, (char const *const *)environ, envlen, value ? modifs : var, value ? modiflen : varlen + 1, 1)) return 0 ; if (doimport) { size_t m = 0 ; char const *newargv[env_len(argv) + 6] ; newargv[m++] = EXECLINE_BINPREFIX "importas" ; newargv[m++] = "-ui" ; newargv[m++] = "--" ; newargv[m++] = var ; newargv[m++] = var ; while (*argv) newargv[m++] = *argv++ ; newargv[m++] = 0 ; return el_spawn0(newargv[0], newargv, newenv) ; } else return el_spawn0(argv[0], argv, newenv) ; } execline-2.8.2.0/src/libexecline/el_parse.c000066400000000000000000000102401416030414000204530ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include int el_parse (stralloc *sa, el_chargen_func_ref next, void *source) { static unsigned char const class[256] = "`aaaaaaaaadaaaaaaaaaaaaaaaaaaaaaafcbffffffffffffjhhhhhhhiifffffffmmmmmmfffffffffffffffffffffeffffggmmmgfffffffkfffkfkfkflffnfoffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ; static uint16_t const table[16][16] = { { 0x0011, 0x4011, 0x0010, 0x0010, 0x0010, 0x0011, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x4091 }, { 0x0000, 0x4000, 0x8001, 0x8003, 0x8003, 0x0005, 0x0010, 0x8403, 0x8403, 0x8403, 0x8403, 0x0010, 0x8403, 0x8403, 0x0100, 0x4080 }, { 0x0005, 0x8001, 0x8001, 0x8003, 0x8003, 0x0005, 0x0010, 0x8403, 0x8403, 0x8403, 0x8403, 0x0010, 0x8403, 0x8403, 0x8001, 0x8001 }, { 0x0203, 0x0003, 0x8001, 0x0001, 0x8003, 0x0005, 0x0010, 0x0401, 0x0401, 0x0401, 0x0401, 0x0010, 0x0401, 0x0401, 0x0003, 0x0003 }, { 0x0000, 0x4000, 0x8001, 0x8003, 0x0003, 0x0000, 0x0010, 0x8403, 0x8403, 0x8403, 0x8403, 0x0010, 0x8403, 0x8403, 0x0100, 0x4080 }, { 0x0202, 0x0002, 0x8001, 0x0004, 0x8003, 0x0005, 0x0010, 0x0404, 0x0404, 0x0404, 0x0404, 0x0010, 0x0404, 0x0404, 0x0002, 0x0002 }, { 0x8201, 0x8001, 0x8001, 0x8003, 0x8003, 0x0005, 0x0010, 0x8403, 0x8403, 0x8403, 0x8403, 0x0010, 0x8403, 0x8403, 0x8001, 0x8001 }, { 0x8201, 0x8001, 0x8001, 0x8003, 0x2003, 0x0005, 0x0010, 0x8403, 0x8403, 0x8403, 0x8403, 0x880c, 0x800d, 0x8403, 0x8001, 0x8001 }, { 0x8201, 0x8001, 0x8001, 0x8003, 0x9809, 0x0005, 0x8807, 0x8008, 0x800d, 0x800a, 0x800d, 0x880c, 0x800d, 0x8403, 0x8001, 0x8001 }, { 0x8201, 0x8001, 0x8001, 0x8003, 0x9809, 0x0005, 0x0010, 0x8403, 0x8403, 0x800a, 0x800d, 0x880c, 0x800d, 0x8403, 0x8001, 0x8001 }, { 0x8201, 0x8001, 0x8001, 0x8003, 0x1006, 0x0005, 0x8807, 0x8008, 0x800d, 0x800a, 0x800d, 0x880c, 0x800d, 0x8403, 0x8001, 0x8001 }, { 0x8201, 0x8001, 0x8001, 0x8003, 0x2003, 0x0005, 0x0010, 0x8403, 0x8403, 0x8403, 0x8403, 0x0010, 0x8403, 0x8403, 0x8001, 0x8001 }, { 0x8201, 0x8001, 0x8001, 0x8003, 0x8003, 0x0005, 0x100b, 0x8403, 0x8403, 0x8403, 0x8403, 0x0010, 0x8403, 0x8403, 0x8001, 0x8001 }, { 0x8201, 0x8001, 0x8001, 0x8003, 0x8003, 0x0005, 0x0010, 0x8403, 0x8403, 0x8403, 0x8403, 0x880c, 0x800d, 0x8403, 0x8001, 0x8001 }, { 0x820e, 0x8001, 0x8001, 0x8003, 0x8003, 0x0005, 0x0010, 0x8403, 0x8403, 0x8403, 0x8403, 0x0010, 0x8403, 0x8403, 0x8001, 0x8001 }, { 0x820f, 0x8001, 0x8001, 0x8003, 0x8003, 0x0005, 0x0010, 0x8403, 0x8403, 0x8403, 0x8403, 0x0010, 0x8403, 0x8403, 0x8001, 0x8001 } } ; size_t mark = 0 ; int n = 0 ; unsigned int blevel = 0 ; unsigned char state = 0, base = 10 ; while (state < 0x10) { uint16_t c ; unsigned char cur ; if (!(*next)(&cur, source)) return -1 ; c = table[class[cur]-'`'][state] ; state = c & 0x1F ; if (c & 0x0400) { unsigned int z ; if (!stralloc_0(sa)) return -1 ; sa->len = mark ; uint_scan_base(sa->s + sa->len, &z, base) ; sa->s[sa->len++] = (unsigned char)z ; } if (c & 0x0800) mark = sa->len ; if (c & 0x0200) { char tilde = EXECLINE_BLOCK_QUOTE_CHAR ; unsigned int i = blevel ; if (!stralloc_readyplus(sa, i<<1)) return -1 ; while (i--) stralloc_catb(sa, &tilde, 1) ; } if (c & 0x0100) sa->len -= ++blevel ; if (c & 0x0080) { if (!blevel--) return -4 ; sa->s[--sa->len-1] = EXECLINE_BLOCK_END_CHAR ; if (!EXECLINE_BLOCK_END_CHAR) sa->len-- ; } if (c & 0x8000) if (!stralloc_catb(sa, (char *)&cur, 1)) return -1 ; if (c & 0x2000) { char x = 7 + byte_chr("abtnvfr", 7, cur) ; if (!stralloc_catb(sa, &x, 1)) return -1 ; } if (c & 0x4000) if (n++, !stralloc_0(sa)) return -1 ; if (c & 0x1000) switch (cur) { case 'x' : base = 16 ; break ; case '0' : base = 8 ; break ; default : base = 10 ; } } if (state == 0x10) return -2 ; if (blevel) return -3 ; return n ; } execline-2.8.2.0/src/libexecline/el_parse_from_buffer.c000066400000000000000000000005371416030414000230370ustar00rootroot00000000000000/* ISC license. */ #include #include #include static int next (unsigned char *c, void *p) { ssize_t r = buffer_get((buffer *)p, (char *)c, 1) ; if (r < 0) return 0 ; if (!r) *c = 0 ; return 1 ; } int el_parse_from_buffer (stralloc *sa, buffer *b) { return el_parse(sa, &next, b) ; } execline-2.8.2.0/src/libexecline/el_parse_from_string.c000066400000000000000000000004161416030414000230700ustar00rootroot00000000000000/* ISC license. */ #include #include static int next (unsigned char *c, void *p) { *c = *(*(char const **)p)++ ; return 1 ; } int el_parse_from_string (stralloc *sa, char const *s) { return el_parse(sa, &next, &s) ; } execline-2.8.2.0/src/libexecline/el_popenv.c000066400000000000000000000024371416030414000206610ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include int el_popenv (stralloc *sa, char const *const *envp, size_t envlen, char const *const *list, size_t listlen) { size_t i = 0, salen = sa->len ; int count = 0 ; for (; i < envlen ; i++) { size_t equal, colon, j = 0 ; unsigned int n ; for (; j < listlen ; j++) if (str_start(envp[i], list[j])) break ; if (j == listlen) goto copyit ; j = strlen(list[j]) ; colon = j + str_chr(envp[i] + j, ':') ; equal = j + str_chr(envp[i] + j, '=') ; if (!envp[i][equal]) goto badenv ; if (colon >= equal) { count++ ; continue ; } if (colon + 1 + uint_scan(envp[i] + colon + 1, &n) != equal) goto copyit ; if (!n) goto copyit ; if (!stralloc_catb(sa, envp[i], colon)) goto err ; if (n > 1) { char fmt[UINT_FMT+1] = ":" ; j = 1 + uint_fmt(fmt+1, n-1) ; if (!stralloc_catb(sa, fmt, j)) goto err ; } if (!stralloc_catb(sa, envp[i] + equal, strlen(envp[i] + equal) + 1)) goto err ; continue ; copyit: if (!stralloc_catb(sa, envp[i], strlen(envp[i]) + 1)) goto err ; } return count ; badenv : errno = EINVAL ; err: sa->len = salen ; return -1 ; } execline-2.8.2.0/src/libexecline/el_pushenv.c000066400000000000000000000025461416030414000210430ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include int el_pushenv (stralloc *sa, char const *const *envp, size_t envlen, char const *const *list, size_t listlen) { size_t i = 0, salen = sa->len ; int count = 0 ; for (; i < envlen ; i++) { size_t equal, colon, j = 0 ; for (; j < listlen ; j++) if (str_start(envp[i], list[j])) break ; if (j == listlen) goto copyit ; count++ ; j = strlen(list[j]) ; colon = j + str_chr(envp[i] + j, ':') ; equal = j + str_chr(envp[i] + j, '=') ; if (!envp[i][equal]) goto badenv ; if (colon >= equal) { if (!stralloc_catb(sa, envp[i], equal) || !stralloc_catb(sa, ":1", 2)) goto err ; } else { unsigned int n ; char fmt[UINT_FMT+1] = ":" ; if (colon + 1 + uint_scan(envp[i] + colon + 1, &n) != equal) goto copyit ; j = 1 + uint_fmt(fmt+1, n+1) ; if (!stralloc_catb(sa, envp[i], colon)) goto err ; if (!stralloc_catb(sa, fmt, j)) goto err ; } if (!stralloc_catb(sa, envp[i] + equal, strlen(envp[i] + equal) + 1)) goto err ; continue ; copyit: if (!stralloc_catb(sa, envp[i], strlen(envp[i]) + 1)) goto err ; } return count ; badenv : errno = EINVAL ; err: sa->len = salen ; return -1 ; } execline-2.8.2.0/src/libexecline/el_semicolon.c000066400000000000000000000017341416030414000213410ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include int el_semicolon (char const **argv) { static unsigned int nblock = 0 ; int argc1 = 0 ; nblock++ ; for (;; argc1++, argv++) { char const *arg = *argv ; if (!arg) return argc1 + 1 ; if ((arg[0] == EXECLINE_BLOCK_END_CHAR) && (!EXECLINE_BLOCK_END_CHAR || !arg[1])) return argc1 ; else if (arg[0] == EXECLINE_BLOCK_QUOTE_CHAR) ++*argv ; else { unsigned int strict = el_getstrict() ; if (strict) { char fmt1[UINT_FMT] ; char fmt2[UINT_FMT] ; fmt1[uint_fmt(fmt1, nblock)] = 0 ; fmt2[uint_fmt(fmt2, (unsigned int)argc1)] = 0 ; if (strict >= 2) strerr_dief6x(100, "unquoted argument ", arg, " at block ", fmt1, " position ", fmt2) ; else strerr_warnw6x("unquoted argument ", arg, " at block ", fmt1, " position ", fmt2) ; } } } } execline-2.8.2.0/src/libexecline/el_spawn0.c000066400000000000000000000006231416030414000205550ustar00rootroot00000000000000/* ISC license. */ #include #include #include pid_t el_spawn0 (char const *prog, char const *const *argv, char const *const *envp) { if (!argv[0]) { static char const *const newargv[3] = { EXECLINE_BINPREFIX "exit", "0", 0 } ; return child_spawn0(newargv[0], newargv, 0) ; } else return child_spawn0(prog, argv, envp) ; } execline-2.8.2.0/src/libexecline/el_spawn1.c000066400000000000000000000006721416030414000205620ustar00rootroot00000000000000/* ISC license. */ #include #include #include pid_t el_spawn1 (char const *prog, char const *const *argv, char const *const *envp, int *fd, int w) { if (!argv[0]) { static char const *const newargv[3] = { EXECLINE_BINPREFIX "exit", "0", 0 } ; return child_spawn1_pipe(newargv[0], newargv, 0, fd, w) ; } else return child_spawn1_pipe(prog, argv, envp, fd, w) ; } execline-2.8.2.0/src/libexecline/el_substandrun.c000066400000000000000000000006001416030414000217100ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include "exlsn.h" void el_substandrun (int argc, char const *const *argv, char const *const *envp, exlsn_t const *info) { satmp.len = 0 ; if (!env_string(&satmp, argv, (unsigned int)argc)) strerr_diefu1sys(111, "env_string") ; el_substandrun_str(&satmp, 0, envp, info) ; } execline-2.8.2.0/src/libexecline/el_substandrun_str.c000066400000000000000000000015001416030414000226000ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include "exlsn.h" void el_substandrun_str (stralloc *src, size_t srcbase, char const *const *envp, exlsn_t const *info) { stralloc dst = STRALLOC_ZERO ; int r = el_substitute(&dst, src->s + srcbase, src->len, info->vars.s, info->values.s, genalloc_s(elsubst_t const, &info->data), genalloc_len(elsubst_t const, &info->data)) ; if (r < 0) strerr_diefu1sys(111, "el_substitute") ; if (!r) _exit(0) ; stralloc_free(src) ; { char const *v[r + 1] ; if (!env_make(v, r, dst.s, dst.len)) strerr_diefu1sys(111, "env_make") ; v[r] = 0 ; xmexec_em(v, envp, info->modifs.s, info->modifs.len) ; } } execline-2.8.2.0/src/libexecline/el_substitute.c000066400000000000000000000120601416030414000215560ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include typedef struct elsubsu_s elsubsu_t, *elsubsu_t_ref ; struct elsubsu_s { elsubst_t const *subst ; size_t pos ; } ; typedef struct subsuinfo_s subsuinfo_t, *subsuinfo_t_ref ; struct subsuinfo_s { stralloc dst ; stralloc sa ; genalloc list ; /* array of elsubsu_t */ char const *values ; } ; #define SUBSUINFO_ZERO { .dst = STRALLOC_ZERO, .sa = STRALLOC_ZERO, .list = GENALLOC_ZERO, .values = 0 } #define TEST 0x80 #define MARK 0x40 #define KEEPESC 0x20 #define INCRESC 0x10 #define STATE 0x07 #define INWORD 0x00 #define INDOLL 0x01 #define INDBR 0x02 #define INVAR 0x03 #define INVARBR 0x04 #define ACCEPT 0x05 static ssize_t parseword (stralloc *sa, genalloc *list, char const *s, char const *vars, elsubst_t const *substs, unsigned int nsubst) { static char const class[5] = "\0\\${}" ; static unsigned char const table[6][5] = { { ACCEPT, ACCEPT, ACCEPT, ACCEPT | TEST, ACCEPT }, { INWORD | KEEPESC | INCRESC, INWORD | INCRESC, INWORD | INCRESC, INWORD | TEST | INCRESC, INWORD | INCRESC }, { INDOLL | KEEPESC, INDOLL, INDOLL, INDOLL | TEST, INDOLL }, { INWORD, INDBR | KEEPESC, INWORD, INWORD | TEST, INWORD }, { INWORD, INWORD, INWORD, INWORD | TEST, INWORD | TEST }, { INWORD, INVAR | MARK | KEEPESC, INVARBR | MARK | KEEPESC, INVAR | KEEPESC, INVARBR | KEEPESC } } ; size_t mark = 0, offset = 0, esc = 0, salen = sa->len, listlen = genalloc_len(elsubsu_t, list) ; ssize_t pos = 0 ; unsigned char state = INWORD ; while (state != ACCEPT) { int nopush = 0 ; unsigned char c = table[byte_chr(class, 5, s[pos])][state] ; if (c & TEST) { unsigned int supp = (state == INVARBR) ; unsigned int i = 0 ; for (; i < nsubst ; i++) { if (!strncmp(vars + substs[i].var, s + mark, pos - mark) && !vars[substs[i].var + pos - mark]) { sa->len -= esc >> 1 ; offset += esc >> 1 ; if (esc & 1) { memmove(sa->s + mark - offset - 2 - supp, sa->s + mark - offset + (esc>>1) - 1 - supp, pos - mark + 1 + supp) ; sa->len-- ; offset++ ; } else { elsubsu_t cur ; cur.subst = substs + i ; cur.pos = mark - offset - 1 - supp ; if (!genalloc_append(elsubsu_t, list, &cur)) goto err ; offset += sa->len - cur.pos ; sa->len = cur.pos ; if (supp) nopush = 1 ; } break ; } } } if (nopush) offset++ ; else if (!stralloc_catb(sa, s+pos, 1)) goto err ; if (c & MARK) mark = pos ; if (!(c & KEEPESC)) esc = 0 ; if (c & INCRESC) esc++ ; state = c & STATE ; pos++ ; } sa->len-- ; return pos ; err: sa->len = salen ; list->len = listlen ; return -1 ; } static int substword (subsuinfo_t *info, size_t wordstart, size_t wordlen, unsigned int n, size_t offset) { if (n < genalloc_len(elsubsu_t, &info->list)) { elsubsu_t *list = genalloc_s(elsubsu_t, &info->list) ; char const *p = info->values + list[n].subst->value ; size_t l = list[n].pos + offset ; size_t dstbase = info->dst.len ; size_t sabase = info->sa.len ; unsigned int i = 0 ; int nc = 0 ; if (!stralloc_readyplus(&info->sa, l)) return -1 ; stralloc_catb(&info->sa, info->sa.s + wordstart, l) ; for (; i < list[n].subst->n ; i++) { size_t plen = strlen(p) ; int r ; info->sa.len = sabase + l ; if (!stralloc_readyplus(&info->sa, plen + wordlen - l)) goto err ; stralloc_catb(&info->sa, p, plen) ; stralloc_catb(&info->sa, info->sa.s + wordstart + l, wordlen - l) ; r = substword(info, sabase, info->sa.len - sabase, n+1, offset + plen) ; if (r < 0) goto err ; nc += r ; p += plen+1 ; } return nc ; err: info->sa.len = sabase ; info->dst.len = dstbase ; return -1 ; } else { if (!stralloc_readyplus(&info->dst, wordlen+1)) return -1 ; stralloc_catb(&info->dst, info->sa.s + wordstart, wordlen) ; stralloc_0(&info->dst) ; return 1 ; } } int el_substitute (stralloc *dst, char const *src, size_t len, char const *vars, char const *values, elsubst_t const *substs, unsigned int nsubst) { subsuinfo_t info = SUBSUINFO_ZERO ; size_t i = 0 ; int nc = 0 ; int wasnull = !dst->s ; if (!stralloc_copy(&info.dst, dst)) return -1 ; info.values = values ; while (i < len) { genalloc_setlen(elsubsu_t, &info.list, 0) ; info.sa.len = 0 ; { ssize_t r = parseword(&info.sa, &info.list, src + i, vars, substs, nsubst) ; if (r < 0) goto err ; i += r ; } { int r = substword(&info, 0, info.sa.len, 0, 0) ; if (r < 0) goto err ; nc += r ; } } genalloc_free(elsubsu_t, &info.list) ; stralloc_free(&info.sa) ; if (!wasnull) stralloc_free(dst) ; *dst = info.dst ; return nc ; err : genalloc_free(elsubsu_t, &info.list) ; stralloc_free(&info.sa) ; stralloc_free(&info.dst) ; return -1 ; } execline-2.8.2.0/src/libexecline/el_transform.c000066400000000000000000000034651416030414000213670ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include static void el_crunch (stralloc *sa, size_t base, char const *delim) { size_t i = base, j = base ; int crunching = 0 ; for (; i < sa->len ; i++) { if (!crunching) sa->s[j++] = sa->s[i] ; if (strchr(delim, sa->s[i])) crunching = 1 ; else if (crunching) { i-- ; crunching = 0 ; } } sa->len = j ; } static int el_split (stralloc *sa, size_t base, eltransforminfo_t const *si, int chomped) { int n = 0 ; size_t i = base ; for (; i < sa->len ; i++) if (strchr(si->delim, sa->s[i])) { sa->s[i] = 0 ; n++ ; base = i+1 ; } if (sa->len && sa->s[sa->len - 1]) { if (si->chomp && !chomped) sa->len = base ; else if (!stralloc_0(sa)) return -1 ; else n++ ; } return n ; } static int el_splitnetstring (stralloc *sa, size_t base) { size_t tmpbase = satmp.len, i = base ; int n = 0 ; while (i < sa->len) { ssize_t r = netstring_decode(&satmp, sa->s + i, sa->len - i) ; if (r < 0) goto err ; if (!stralloc_0(&satmp)) goto err ; i += r ; n++ ; } sa->len = base ; if (!stralloc_catb(sa, satmp.s + tmpbase, satmp.len - tmpbase)) { sa->len = i ; goto err ; } satmp.len = tmpbase ; return n ; err: satmp.len = tmpbase ; return -1 ; } int el_transform (stralloc *sa, size_t i, eltransforminfo_t const *si) { int chomped = 0 ; if (si->crunch && *si->delim) el_crunch(sa, i, si->delim) ; if (si->chomp && (sa->len > i) && strchr(si->delim, sa->s[sa->len-1])) { sa->len-- ; chomped = 1 ; } return si->split ? *si->delim ? el_split(sa, i, si, chomped) : el_splitnetstring(sa, i) : stralloc_0(sa) ? 1 : -1 ; } execline-2.8.2.0/src/libexecline/el_vardupl.c000066400000000000000000000003711416030414000210220ustar00rootroot00000000000000/* ISC license. */ #include #include int el_vardupl (char const *key, char const *s, size_t len) { size_t i = 0 ; for (; i < len ; i += strlen(s + i) + 1) if (!strcmp(key, s + i)) return 1 ; return 0 ; } execline-2.8.2.0/src/libexecline/exlp.c000066400000000000000000000046041416030414000176400ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include "exlsn.h" int exlp (unsigned int nmin, char const *const *envp, exlsn_t *info) { size_t varbase = info->vars.len ; size_t valbase = info->values.len ; size_t datbase = genalloc_len(elsubst_t, &info->data) ; size_t poszero ; elsubst_t blah ; char const *x = env_get2(envp, "#") ; unsigned int n, ntot, i = 0 ; if (!x) return -2 ; if (!uint0_scan(x, &n)) return -2 ; if (el_vardupl("#", info->vars.s, info->vars.len)) return -2 ; if (el_vardupl("@", info->vars.s, info->vars.len)) return -2 ; { unsigned int strict = el_getstrict() ; if (strict && (n < nmin)) { char fmta[UINT_FMT] ; char fmtn[UINT_FMT] ; fmta[uint_fmt(fmta, n)] = 0 ; fmtn[uint_fmt(fmtn, nmin)] = 0 ; if (strict > 1) strerr_dief4x(100, "too few arguments: expected at least ", fmtn, " but got ", fmta) ; else strerr_warnw4x("too few arguments: expected at least ", fmtn, " but got ", fmta) ; } } blah.var = varbase ; blah.value = info->values.len ; blah.n = 1 ; if (!stralloc_catb(&info->vars, "#\0@", 4) || !stralloc_catb(&info->values, x, strlen(x) + 1) || !genalloc_append(elsubst_t, &info->data, &blah)) goto err ; ntot = n > nmin ? n : nmin ; poszero = info->values.len ; for (; i <= ntot ; i++) { char fmt[UINT_FMT] ; size_t l = uint_fmt(fmt, i) ; fmt[l] = 0 ; if (el_vardupl(fmt, info->vars.s, info->vars.len)) goto err2 ; x = (i <= n) ? env_get2(envp, fmt) : "" ; if (!x) goto err2 ; blah.var = info->vars.len ; blah.value = info->values.len ; blah.n = 1 ; if (!stralloc_catb(&info->vars, fmt, l+1) || !stralloc_catb(&info->values, x, strlen(x) + 1) || !genalloc_append(elsubst_t, &info->data, &blah)) goto err ; } blah.var = varbase + 2 ; blah.value = poszero + strlen(info->values.s + poszero) + 1 ; blah.n = n ; if (!genalloc_append(elsubst_t, &info->data, &blah)) goto err ; return n ; err: info->vars.len = varbase ; info->values.len = valbase ; genalloc_setlen(elsubst_t, &info->data, datbase) ; return -1 ; err2: info->vars.len = varbase ; info->values.len = valbase ; genalloc_setlen(elsubst_t, &info->data, datbase) ; return -2 ; } execline-2.8.2.0/src/libexecline/exlsn_define.c000066400000000000000000000026601416030414000213330ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include "exlsn.h" int exlsn_define (int argc, char const **argv, char const *const *envp, exlsn_t *info) { eltransforminfo_t si = ELTRANSFORMINFO_ZERO ; subgetopt localopt = SUBGETOPT_ZERO ; elsubst_t blah ; blah.var = info->vars.len ; blah.value = info->values.len ; for (;;) { int opt = subgetopt_r(argc, argv, "NnsCcd:", &localopt) ; if (opt < 0) break ; switch (opt) { case 'N' : si.chomp = 0 ; break ; case 'n' : si.chomp = 1 ; break ; case 's' : si.split = 1 ; break ; case 'C' : si.crunch = 1 ; break ; case 'c' : si.crunch = 0 ; break ; case 'd' : si.delim = localopt.arg ; break ; default : return -3 ; } } argc -= localopt.ind ; argv += localopt.ind ; if (argc < 2) return -3 ; if (!*argv[0] || el_vardupl(argv[0], info->vars.s, info->vars.len)) return -2 ; if (!stralloc_catb(&info->vars, argv[0], strlen(argv[0]) + 1)) return -1 ; if (!stralloc_cats(&info->values, argv[1])) goto err ; { int r = el_transform(&info->values, blah.value, &si) ; if (r < 0) goto err ; blah.n = r ; } if (!genalloc_append(elsubst_t, &info->data, &blah)) goto err ; (void)envp ; return localopt.ind + 2 ; err: info->vars.len = blah.var ; info->values.len = blah.value ; return -1 ; } execline-2.8.2.0/src/libexecline/exlsn_elglob.c000066400000000000000000000040151416030414000213410ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include #include "exlsn.h" static int elgloberrfunc (char const *s, int e) { errno = e ; strerr_warnw2sys("while globbing, error reading ", s) ; return 0 ; } int exlsn_elglob (int argc, char const **argv, char const *const *envp, exlsn_t *info) { glob_t pglob ; subgetopt localopt = SUBGETOPT_ZERO ; elsubst_t blah ; int flags = GLOB_NOSORT | GLOB_NOCHECK ; unsigned int i = 0 ; int verbose = 0 ; blah.var = info->vars.len ; blah.value = info->values.len ; for (;;) { int opt = subgetopt_r(argc, argv, "vwsme0", &localopt) ; if (opt < 0) break ; switch (opt) { case 'v' : verbose = 1 ; break ; case 'w' : flags |= GLOB_ERR ; break ; case 's' : flags &= ~GLOB_NOSORT ; break ; case 'm' : flags |= GLOB_MARK ; break ; case 'e' : flags |= GLOB_NOESCAPE ; break ; case '0' : flags &= ~GLOB_NOCHECK ; break ; default : return -3 ; } } argc -= localopt.ind ; argv += localopt.ind ; if (argc < 2) return -3 ; if (!*argv[0] || el_vardupl(argv[0], info->vars.s, info->vars.len)) return -2 ; if (!stralloc_catb(&info->vars, argv[0], strlen(argv[0]) + 1)) return -1 ; pglob.gl_offs = 0 ; switch (glob(argv[1], flags, verbose ? &elgloberrfunc : 0, &pglob)) { case 0 : break ; case GLOB_NOMATCH: { pglob.gl_pathc = 0 ; pglob.gl_pathv = 0 ; break ; } default: goto err ; } for ( ; i < (unsigned int)pglob.gl_pathc ; i++) if (!stralloc_catb(&info->values, pglob.gl_pathv[i], strlen(pglob.gl_pathv[i]) + 1)) goto globerr ; blah.n = pglob.gl_pathc ; globfree(&pglob) ; if (!genalloc_append(elsubst_t, &info->data, &blah)) goto err ; (void)envp ; return localopt.ind + 2 ; globerr: globfree(&pglob) ; err: info->vars.len = blah.var ; info->values.len = blah.value ; return -1 ; } execline-2.8.2.0/src/libexecline/exlsn_exlp.c000066400000000000000000000011401416030414000210410ustar00rootroot00000000000000/* ISC license. */ #include #include #include "exlsn.h" int exlsn_exlp (int argc, char const **argv, char const *const *envp, exlsn_t *info) { subgetopt localopt = SUBGETOPT_ZERO ; unsigned int nmin = 0 ; int n ; for (;;) { int opt = subgetopt_r(argc, argv, "P:", &localopt) ; if (opt < 0) break ; switch (opt) { case 'P' : if (uint0_scan(localopt.arg, &nmin)) break ; default : return -3 ; } } argc -= localopt.ind ; argv += localopt.ind ; n = exlp(nmin, envp, info) ; if (n < 0) return n ; return localopt.ind ; } execline-2.8.2.0/src/libexecline/exlsn_free.c000066400000000000000000000003531416030414000210170ustar00rootroot00000000000000/* ISC license. */ #include #include "exlsn.h" void exlsn_free (exlsn_t *info) { stralloc_free(&info->vars) ; stralloc_free(&info->values) ; stralloc_free(&info->data) ; stralloc_free(&info->modifs) ; } execline-2.8.2.0/src/libexecline/exlsn_importas.c000066400000000000000000000037161416030414000217420ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include "exlsn.h" int exlsn_importas (int argc, char const **argv, char const *const *envp, exlsn_t *info) { eltransforminfo_t si = ELTRANSFORMINFO_ZERO ; subgetopt localopt = SUBGETOPT_ZERO ; elsubst_t blah ; char const *defaultval = 0 ; char const *x ; int insist = 0 ; int unexport = 0 ; blah.var = info->vars.len ; blah.value = info->values.len ; for (;;) { int opt = subgetopt_r(argc, argv, "iuD:NnsCcd:", &localopt) ; if (opt < 0) break ; switch (opt) { case 'i' : insist = 1 ; break ; case 'u' : unexport = 1 ; break ; case 'D' : defaultval = localopt.arg ; break ; case 'N' : si.chomp = 0 ; break ; case 'n' : si.chomp = 1 ; break ; case 's' : si.split = 1 ; break ; case 'C' : si.crunch = 1 ; break ; case 'c' : si.crunch = 0 ; break ; case 'd' : si.delim = localopt.arg ; break ; default : return -3 ; } } argc -= localopt.ind ; argv += localopt.ind ; if ((unsigned int)argc < 2) return -3 ; if (!*argv[0] || el_vardupl(argv[0], info->vars.s, info->vars.len)) return -2 ; if (!stralloc_catb(&info->vars, argv[0], strlen(argv[0]) + 1)) return -1 ; x = env_get2(envp, argv[1]) ; if (!x) { if (insist) strerr_dienotset(100, argv[1]) ; x = defaultval ; } else if (unexport) { if (!stralloc_catb(&info->modifs, argv[1], strlen(argv[1]) + 1)) goto err ; } if (!x) blah.n = 0 ; else { int r ; if (!stralloc_cats(&info->values, x)) goto err ; r = el_transform(&info->values, blah.value, &si) ; if (r < 0) goto err ; blah.n = r ; } if (!genalloc_append(elsubst_t, &info->data, &blah)) goto err ; return localopt.ind + 2 ; err: info->vars.len = blah.var ; info->values.len = blah.value ; return -1 ; } execline-2.8.2.0/src/libexecline/exlsn_main.c000066400000000000000000000013251416030414000210220ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include "exlsn.h" void exlsn_main (int argc, char const **argv, char const *const *envp, exls_func *func, char const *usage) { exlsn_t info = EXLSN_ZERO ; int r = (*func)(argc, argv, envp, &info) ; if (r < 0) switch (r) { case -4 : strerr_dief1x(100, "empty block") ; case -3 : strerr_dieusage(100, usage) ; case -2 : strerr_dief1x(111, "bad substitution key") ; case -1 : strerr_diefu1sys(111, "complete exlsn function") ; default : strerr_diefu2x(111, "complete exlsn function", ": unknown error") ; } el_substandrun(argc-r, argv+r, envp, &info) ; } execline-2.8.2.0/src/libexecline/exlsn_multidefine.c000066400000000000000000000044011416030414000224010ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include "exlsn.h" int exlsn_multidefine (int argc, char const **argv, char const *const *envp, exlsn_t *info) { eltransforminfo_t si = ELTRANSFORMINFO_ZERO ; subgetopt localopt = SUBGETOPT_ZERO ; size_t varbase = info->vars.len ; size_t valbase = info->values.len ; size_t pos = valbase ; unsigned int i = 0 ; unsigned int max ; char const *x ; int argc1 ; int zeroword = 0, likeread = 0 ; si.split = 1 ; for (;;) { int opt = subgetopt_r(argc, argv, "0rNnCcd:", &localopt) ; if (opt < 0) break ; switch (opt) { case '0' : zeroword = 1 ; break ; case 'r' : likeread = 1 ; break ; case 'N' : si.chomp = 0 ; break ; case 'n' : si.chomp = 1 ; break ; case 'C' : si.crunch = 1 ; break ; case 'c' : si.crunch = 0 ; break ; case 'd' : si.delim = localopt.arg ; break ; default : return -3 ; } } argc -= localopt.ind ; argv += localopt.ind ; if (argc < 2) return -3 ; x = argv[0] ; argv++ ; argc-- ; argc1 = el_semicolon(argv) ; if (!argc1) return -4 ; if (argc1 >= argc) return -3 ; if (!stralloc_cats(&info->values, x)) return -1 ; { int r = el_transform(&info->values, valbase, &si) ; if (r < 0) goto err ; max = r ; } if (!stralloc_0(&info->values)) goto err ; for (; i < (unsigned int)argc1 ; i++) { if (*argv[i]) { elsubst_t blah ; blah.var = info->vars.len ; if (el_vardupl(argv[i], info->vars.s, info->vars.len)) goto err2 ; if (!stralloc_catb(&info->vars, argv[i], strlen(argv[i]) + 1)) goto err ; blah.value = i < max ? pos : info->values.len - 1 ; blah.n = (i < max) || !zeroword ; if (!genalloc_append(elsubst_t, &info->data, &blah)) goto err ; } if (i < max) pos += strlen(info->values.s + pos) + 1 ; } if ((i < max) && likeread) genalloc_s(elsubst_t, &info->data)[genalloc_len(elsubst_t, &info->data) - 1].n = max - i + 1 ; (void)envp ; return localopt.ind + argc1 + 2 ; err: info->vars.len = varbase ; info->values.len = valbase ; return -1 ; err2: info->vars.len = varbase ; info->values.len = valbase ; return -2 ; } execline-2.8.2.0/src/posix/000077500000000000000000000000001416030414000153775ustar00rootroot00000000000000execline-2.8.2.0/src/posix/deps-exe/000077500000000000000000000000001416030414000171115ustar00rootroot00000000000000execline-2.8.2.0/src/posix/deps-exe/posix-cd000066400000000000000000000000121416030414000205530ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/posix/deps-exe/posix-umask000066400000000000000000000000121416030414000213050ustar00rootroot00000000000000-lskarnet execline-2.8.2.0/src/posix/posix-cd.c000066400000000000000000000076511416030414000173020ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define USAGE "posix-cd [ -L | -P ] [ - | path ] [ prog... ]" #define dieusage() strerr_dieusage(100, USAGE) #define dienomem() strerr_diefu1sys(111, "stralloc_catb") int main (int argc, char const **argv) { int phy = 0 ; int dopwd = 0 ; char const *where ; int got = 0 ; stralloc sa = STRALLOC_ZERO ; PROG = "posix-cd" ; setlocale(LC_ALL, "") ; /* yeah, as if */ { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "LP", &l) ; if (opt == -1) break ; switch (opt) { case 'L' : phy = 0 ; break ; case 'P' : phy = 1 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (!argc) where = getenv("HOME") ; else { where = *argv++ ; if (!strcmp(where, "-")) { where = getenv("OLDPWD") ; dopwd = 1 ; } } if (!where || !where[0]) dieusage() ; if (!(where[0] == '/' || (where[0] == '.' && (!where[1] || where[1] == '/' || (where[1] == '.' && (!where[2] || where[2] == '/')))))) { char const *cdpath = getenv("CDPATH") ; if (cdpath) { size_t pos = 0 ; size_t len = strlen(cdpath) ; while (pos < len) { struct stat st ; size_t m = byte_chr(cdpath + pos, len - pos, ':') ; sa.len = 0 ; if (m) { if (!stralloc_catb(&sa, cdpath + pos, m)) dienomem() ; if (cdpath[pos + m - 1] != '/' && !stralloc_catb(&sa, "/", 1)) dienomem() ; } else if (!stralloc_catb(&sa, "./", 2)) dienomem() ; if (!stralloc_cats(&sa, where) || !stralloc_0(&sa)) dienomem() ; if (!stat(sa.s, &st) && S_ISDIR(st.st_mode)) { got = 1 ; dopwd = 1 ; break ; } pos += m+1 ; } } } if (!got && (!stralloc_cats(&sa, where) || !stralloc_0(&sa))) dienomem() ; { size_t sabase = sa.len ; if (sagetcwd(&sa) < 0) strerr_diefu1sys(111, "getcwd") ; if (!stralloc_0(&sa)) dienomem() ; if (!env_mexec("OLDPWD", sa.s + sabase)) dienomem() ; sa.len = sabase ; } if (!phy) { char const *x = getenv("PWD") ; if (x && sa.s[0] != '/') { size_t len = strlen(x) ; int doslash = len && x[len-1] != '/' ; if (!stralloc_insertb(&sa, 0, x, len + doslash)) dienomem() ; if (doslash) sa.s[len] = '/' ; } { stralloc tmp = STRALLOC_ZERO ; if (!stralloc_ready(&tmp, sa.len + 2)) dienomem() ; tmp.len = path_canonicalize(tmp.s, sa.s, 1) ; if (!tmp.len++) strerr_diefu4sys(111, "canonicalize ", sa.s, ": problem with ", tmp.s) ; stralloc_free(&sa) ; sa = tmp ; } if (!env_mexec("PWD", sa.s)) dienomem() ; #ifdef PATH_MAX if (sa.len > PATH_MAX && strlen(where) < PATH_MAX && x && *x) { size_t len = strlen(x) ; int hasslash = x[len-1] == '/' ; if (!strncmp(sa.s, x, len)) { if (hasslash || (sa.len > len && sa.s[len] == '/')) { sa.len -= len + !hasslash ; memmove(sa.s, sa.s + len + !hasslash, sa.len) ; } } } #endif } /* fking finally */ if (chdir(sa.s) < 0) strerr_diefu2sys(111, "chdir to ", where) ; /* and there's still more nonsense to do afterwards! */ if (phy) { sa.len = 0 ; if (sagetcwd(&sa) < 0) strerr_diefu1sys(111, "getcwd") ; if (!stralloc_0(&sa)) dienomem() ; if (!env_mexec("PWD", sa.s)) dienomem() ; } if (dopwd) { sa.s[sa.len - 1] = '\n' ; if (allwrite(1, sa.s, sa.len) < sa.len) strerr_diefu1sys(111, "write to stdout") ; } xmexec0(argv) ; } execline-2.8.2.0/src/posix/posix-umask.c000066400000000000000000000101721416030414000200240ustar00rootroot00000000000000/* ISC license. */ #include #include #include #include #include #include #include #include #include #include #define USAGE "posix-umask [ -S ] [ mask ] [ prog... ]" #define dieusage() strerr_dieusage(100, USAGE) #define dieout() strerr_diefu1sys(111, "write to stdout") /* well, unlike posix-cd, at least this one was fun to write */ static inline int output (int sym) { mode_t mode = umask(0) ; size_t m = 0 ; char fmt[18] ; if (sym) { unsigned int i = 3 ; while (i--) { unsigned int mask = ~(mode >> (3*i)) ; fmt[m++] = "ogu"[i] ; fmt[m++] = '=' ; if (mask & 4) fmt[m++] = 'r' ; if (mask & 2) fmt[m++] = 'w' ; if (mask & 1) fmt[m++] = 'x' ; if (i) fmt[m++] = ',' ; } } else m += uint0_ofmt(fmt, mode, 4) ; fmt[m++] = '\n' ; if (buffer_putflush(buffer_1, fmt, m) < 0) dieout() ; return 0 ; } static void diesyntax (char const *) gccattr_noreturn ; static void diesyntax (char const *s) { strerr_dief3x(101, "internal parsing error: bad ", s, ". Please submit a bug-report.") ; } static inline uint8_t cclass (char c) { /* char tables may be more efficient, but this is way more readable */ switch (c) { case 0 : return 0 ; case ',' : return 1 ; case '+' : case '-' : case '=' : return 2 ; case 'u' : case 'g' : case 'o' : return 3 ; case 'a' : return 4 ; case 'r' : case 'w' : case 'x' : case 'X' : case 's' : case 't' : return 5 ; default : return 6 ; } } static inline uint8_t who_value (char c) { switch (c) { case 'u' : return 4 ; case 'g' : return 2 ; case 'o' : return 1 ; case 'a' : case '+' : /* shortcut for when who is empty */ case '-' : case '=' : return 7 ; default : diesyntax("who") ; } } static inline uint8_t perm_value (char c) { switch (c) { case 'r' : return 4 ; case 'w' : return 2 ; case 'x' : case 'X' : return 1 ; case 's' : case 't' : return 0 ; default : diesyntax("perm") ; } } static inline unsigned int parsemode (char const *s) { static uint16_t const table[5][7] = { { 0x005, 0x000, 0x064, 0x021, 0x021, 0x006, 0x006 }, { 0x005, 0x006, 0x042, 0x021, 0x021, 0x006, 0x006 }, { 0x005, 0x200, 0x042, 0x083, 0x006, 0x104, 0x006 }, { 0x805, 0xe00, 0xc42, 0x006, 0x006, 0x006, 0x006 }, { 0x805, 0xe00, 0xc42, 0x006, 0x006, 0x104, 0x006 } } ; unsigned int oldmode = ~umask(0) ; uint8_t modes[3] = { oldmode & 7, (oldmode >> 3) & 7, (oldmode >> 6) & 7 } ; uint8_t who = 0 ; uint8_t perm = 0 ; uint8_t state = 0 ; char op = 0 ; while (state < 5) { char c = *s++ ; uint16_t what = table[state][cclass(c)] ; state = what & 7 ; if (what & 0x020) who |= who_value(c) ; if (what & 0x080) perm = modes[byte_chr("ogu", 3, c)] ; if (what & 0x100) perm |= perm_value(c) ; if (what & 0x800) { unsigned int i = 3 ; while (i--) if (who & (1 << i)) switch (op) { case '-' : modes[i] &= ~perm ; break ; case '+' : modes[i] |= perm ; break ; case '=' : modes[i] = perm ; break ; default : diesyntax("op") ; } } if (what & 0x040) op = c ; if (what & 0x200) who = 0 ; if (what & 0x400) perm = 0 ; } if (state > 5) strerr_dief1x(1, "invalid mode string") ; return ((unsigned int)modes[2] << 6) | ((unsigned int)modes[1] << 3) | modes[0] ; } int main (int argc, char const **argv) { int sym = 0 ; unsigned int mode ; PROG = "posix-umask" ; setlocale(LC_ALL, "") ; /* totally supported, I swear */ { subgetopt l = SUBGETOPT_ZERO ; for (;;) { int opt = subgetopt_r(argc, argv, "S", &l) ; if (opt == -1) break ; switch (opt) { case 'S' : sym = 1 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (!argc) return output(sym) ; if (!uint0_oscan(argv[0], &mode)) mode = ~parsemode(argv[0]) ; umask(mode & 00777) ; xexec0(argv+1) ; } execline-2.8.2.0/src/posix/posix-umask.txt000066400000000000000000000016141416030414000204220ustar00rootroot00000000000000 parsemode() function for posix-umask goal: parse the "u+r,g-wx,o=u" symbolic mode string and convert it to a numeric value suitable for umask(). In the purest skarnet.org tradition, we implement the parser via a DFA. class | 0 1 2 3 4 5 6 st\ev | \0 , +-= ugo a rwxXst other ------------------------------------------------------------------------ START | wo w w 0 | END START OP WHO WHO X X WHO | o w w 1 | END X OP WHO WHO X X OP | r o c p 2 | END START OP PERMCPY X PERM X PERMCPY | ! !rR !Ro 3 | END START OP X X X X PERM | ! !rR !Ro p 4 | END START OP X X PERM X ------------------------------------------------------------------------ END=5, X=6. -> states: 3 bits 7 actions -> 10 bits total, need uint16_t w: 0x020: who |= c o: 0x040: store op c: 0x080: copy perm from c p: 0x100: perm |= c r: 0x200: reset who R: 0x400: reset perm !: 0x800: apply (who, op, perm) change execline-2.8.2.0/tools/000077500000000000000000000000001416030414000146065ustar00rootroot00000000000000execline-2.8.2.0/tools/gen-deps.sh000077500000000000000000000047431416030414000166570ustar00rootroot00000000000000#!/bin/sh -e . package/info echo '#' echo '# This file has been generated by tools/gen-deps.sh' echo '#' echo for dir in src/include/${package} src/* ; do for file in $(ls -1 $dir | grep -- \\.h$) ; do { grep -F -- "#include <${package}/" < ${dir}/$file | cut -d'<' -f2 | cut -d'>' -f1 ; grep -- '#include ".*\.h"' < ${dir}/$file | cut -d'"' -f2 } | sort -u | { deps= while read dep ; do if echo $dep | grep -q "^${package}/" ; then deps="$deps src/include/$dep" elif test -f "${dir}/$dep" ; then deps="$deps ${dir}/$dep" else deps="$deps src/include-local/$dep" fi done if test -n "$deps" ; then echo "${dir}/${file}:${deps}" fi } done done for dir in src/* ; do for file in $(ls -1 $dir | grep -- \\.c$) ; do { grep -F -- "#include <${package}/" < ${dir}/$file | cut -d'<' -f2 | cut -d'>' -f1 ; grep -- '#include ".*\.h"' < ${dir}/$file | cut -d'"' -f2 } | sort -u | { deps=" ${dir}/$file" while read dep ; do if echo $dep | grep -q "^${package}/" ; then deps="$deps src/include/$dep" elif test -f "${dir}/$dep" ; then deps="$deps ${dir}/$dep" else deps="$deps src/include-local/$dep" fi done o=$(echo $file | sed s/\\.c$/.o/) lo=$(echo $file | sed s/\\.c$/.lo/) echo "${dir}/${o} ${dir}/${lo}:${deps}" } done done echo for dir in $(ls -1 src | grep -v ^include) ; do for file in $(ls -1 src/$dir/deps-lib) ; do deps= libs= while read dep ; do if echo $dep | grep -q -e ^-l -e '^\${.*_LIB}' ; then libs="$libs $dep" else deps="$deps src/$dir/$dep" fi done < src/$dir/deps-lib/$file echo 'ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)' echo "lib${file}.a.xyzzy:$deps" echo else echo "lib${file}.a.xyzzy:$(echo "$deps" | sed 's/\.o/.lo/g')" echo endif echo "lib${file}.so.xyzzy: EXTRA_LIBS :=$libs" echo "lib${file}.so.xyzzy:$(echo "$deps" | sed 's/\.o/.lo/g')" done for file in $(ls -1 src/$dir/deps-exe) ; do deps= libs= while read dep ; do if echo $dep | grep -q -- \\.o$ ; then dep="src/$dir/$dep" fi if echo $dep | grep -q -e ^-l -e '^\${.*_LIB}' ; then libs="$libs $dep" else deps="$deps $dep" fi done < src/$dir/deps-exe/$file echo "$file: EXTRA_LIBS :=$libs" echo "$file: src/$dir/$file.o$deps" done done execline-2.8.2.0/tools/install.sh000077500000000000000000000016751416030414000166240ustar00rootroot00000000000000#!/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