From f316a2ed52195135a35e32d7096e876357c48c69 Mon Sep 17 00:00:00 2001
From: Laurent Bercot
Date: Thu, 18 Sep 2014 20:03:23 +0000
Subject: initial commit: rc for execline-2.0.0.0
---
doc/background.html | 57 +++++++++
doc/backtick.html | 66 ++++++++++
doc/cd.html | 45 +++++++
doc/componentsb.txt | 41 ++++++
doc/define.html | 42 +++++++
doc/dieshdiedie.html | 278 +++++++++++++++++++++++++++++++++++++++++
doc/dollarat.html | 86 +++++++++++++
doc/el_pushenv.html | 173 ++++++++++++++++++++++++++
doc/el_semicolon.html | 124 +++++++++++++++++++
doc/el_substitute.html | 309 ++++++++++++++++++++++++++++++++++++++++++++++
doc/el_transform.html | 204 ++++++++++++++++++++++++++++++
doc/elgetopt.html | 60 +++++++++
doc/elgetpositionals.html | 94 ++++++++++++++
doc/elglob.html | 68 ++++++++++
doc/emptyenv.html | 57 +++++++++
doc/exec.html | 50 ++++++++
doc/execline-shell.html | 53 ++++++++
doc/execline-startup.html | 59 +++++++++
doc/execlineb.html | 246 ++++++++++++++++++++++++++++++++++++
doc/exit.html | 44 +++++++
doc/export.html | 43 +++++++
doc/fdblock.html | 55 +++++++++
doc/fdclose.html | 44 +++++++
doc/fdmove.html | 55 +++++++++
doc/fdreserve.html | 92 ++++++++++++++
doc/forbacktickx.html | 77 ++++++++++++
doc/foreground.html | 57 +++++++++
doc/forx.html | 66 ++++++++++
doc/getpid.html | 44 +++++++
doc/grammar.html | 160 ++++++++++++++++++++++++
doc/heredoc.html | 56 +++++++++
doc/homeof.html | 37 ++++++
doc/if.html | 68 ++++++++++
doc/ifelse.html | 59 +++++++++
doc/ifte.html | 67 ++++++++++
doc/ifthenelse.html | 59 +++++++++
doc/import.html | 37 ++++++
doc/importas.html | 57 +++++++++
doc/index.html | 213 ++++++++++++++++++++++++++++++++
doc/loopwhilex.html | 60 +++++++++
doc/multidefine.html | 69 +++++++++++
doc/multisubstitute.html | 121 ++++++++++++++++++
doc/pipeline.html | 67 ++++++++++
doc/piperw.html | 38 ++++++
doc/quine-dam.txt | 110 +++++++++++++++++
doc/quine-jriou.txt | 28 +++++
doc/quine-prj-2.txt | 15 +++
doc/quine-prj-3.txt | 13 ++
doc/quine-prj.txt | 13 ++
doc/redirfd.html | 100 +++++++++++++++
doc/runblock.html | 75 +++++++++++
doc/shift.html | 68 ++++++++++
doc/tryexec.html | 67 ++++++++++
doc/umask.html | 44 +++++++
doc/unexport.html | 46 +++++++
doc/upgrade.html | 35 ++++++
doc/wait.html | 53 ++++++++
57 files changed, 4524 insertions(+)
create mode 100644 doc/background.html
create mode 100644 doc/backtick.html
create mode 100644 doc/cd.html
create mode 100644 doc/componentsb.txt
create mode 100644 doc/define.html
create mode 100644 doc/dieshdiedie.html
create mode 100644 doc/dollarat.html
create mode 100644 doc/el_pushenv.html
create mode 100644 doc/el_semicolon.html
create mode 100644 doc/el_substitute.html
create mode 100644 doc/el_transform.html
create mode 100644 doc/elgetopt.html
create mode 100644 doc/elgetpositionals.html
create mode 100644 doc/elglob.html
create mode 100644 doc/emptyenv.html
create mode 100644 doc/exec.html
create mode 100644 doc/execline-shell.html
create mode 100644 doc/execline-startup.html
create mode 100644 doc/execlineb.html
create mode 100644 doc/exit.html
create mode 100644 doc/export.html
create mode 100644 doc/fdblock.html
create mode 100644 doc/fdclose.html
create mode 100644 doc/fdmove.html
create mode 100644 doc/fdreserve.html
create mode 100644 doc/forbacktickx.html
create mode 100644 doc/foreground.html
create mode 100644 doc/forx.html
create mode 100644 doc/getpid.html
create mode 100644 doc/grammar.html
create mode 100644 doc/heredoc.html
create mode 100644 doc/homeof.html
create mode 100644 doc/if.html
create mode 100644 doc/ifelse.html
create mode 100644 doc/ifte.html
create mode 100644 doc/ifthenelse.html
create mode 100644 doc/import.html
create mode 100644 doc/importas.html
create mode 100644 doc/index.html
create mode 100644 doc/loopwhilex.html
create mode 100644 doc/multidefine.html
create mode 100644 doc/multisubstitute.html
create mode 100644 doc/pipeline.html
create mode 100644 doc/piperw.html
create mode 100644 doc/quine-dam.txt
create mode 100644 doc/quine-jriou.txt
create mode 100644 doc/quine-prj-2.txt
create mode 100644 doc/quine-prj-3.txt
create mode 100644 doc/quine-prj.txt
create mode 100644 doc/redirfd.html
create mode 100644 doc/runblock.html
create mode 100644 doc/shift.html
create mode 100644 doc/tryexec.html
create mode 100644 doc/umask.html
create mode 100644 doc/unexport.html
create mode 100644 doc/upgrade.html
create mode 100644 doc/wait.html
(limited to 'doc')
diff --git a/doc/background.html b/doc/background.html
new file mode 100644
index 0000000..85d2589
--- /dev/null
+++ b/doc/background.html
@@ -0,0 +1,57 @@
+
+
+
+
+ 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...'.
+
+
+
+
diff --git a/doc/backtick.html b/doc/backtick.html
new file mode 100644
index 0000000..7bdc037
--- /dev/null
+++ b/doc/backtick.html
@@ -0,0 +1,66 @@
+
+
+
+
+ execline: the backtick command
+
+
+
+
+
+
+
+execline
+Software
+skarnet.org
+
+
+ The backtick program
+
+
+backtick runs a program and uses its output as the argument of
+another program.
+
+
+ Interface
+
+
+ In an execlineb script:
+
+
+
+ backtick [ -i ] [ -n ] 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 the modified prog2..., with
+variable added to the environment with prog1...'s
+output as a value.
+
+
+ Options
+
+
+ - -i : insist. If prog1 exits non-zero,
+backtick exits with the same exit code (or 111 if prog1
+crashed for some reason). Without this option, backtick execs into
+prog2... no matter what prog1 does, with the null word as
+variable's value if prog1 didn't write anything before
+dying.
+ - -n : chomp an ending newline off prog1...'s
+output.
+
+
+ Notes
+
+
+ - You can start prog2... with "import variable unexport variable"
+to perform variable substitution.
+
+
+
+
diff --git a/doc/cd.html b/doc/cd.html
new file mode 100644
index 0000000..416dc42
--- /dev/null
+++ b/doc/cd.html
@@ -0,0 +1,45 @@
+
+
+
+
+ execline: the cd command
+
+
+
+
+
+
+
+execline
+Software
+skarnet.org
+
+
+ The cd program
+
+
+cd changes the current working directory to a
+given directory, then executes a program.
+
+
+ Interface
+
+
+ cd dir prog...
+
+
+
+cd performs a
+chdir()
+system call on dir, then execs into prog....
+
+
+ Notes
+
+
+cd is a standard shell builtin. Be careful if you want to
+use the cd command outside of an execline script.
+
+
+
+
diff --git a/doc/componentsb.txt b/doc/componentsb.txt
new file mode 100644
index 0000000..a191f04
--- /dev/null
+++ b/doc/componentsb.txt
@@ -0,0 +1,41 @@
+#!/command/execlineb
+
+# 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 import 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.
diff --git a/doc/define.html b/doc/define.html
new file mode 100644
index 0000000..4d5e0f2
--- /dev/null
+++ b/doc/define.html
@@ -0,0 +1,42 @@
+
+
+
+
+ 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 ] [ -d delim ] variable value prog...
+
+
+
+
+
+
diff --git a/doc/dieshdiedie.html b/doc/dieshdiedie.html
new file mode 100644
index 0000000..dc3c661
--- /dev/null
+++ b/doc/dieshdiedie.html
@@ -0,0 +1,278 @@
+
+
+
+
+ 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.
+Even worse, the
+shell sometimes has to perform double parsing, for instance
+after parameter expansion. This can lead to atrocities like
+
+zork="foo ; echo bar"
+touch $zork
+
not doing what you would like them to do, even in that simple
+case. (zsh has a sane behaviour by
+default, at the expense of explicitly breaking the spec.)
+
+
+
+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 than 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 inside an execline script. If you want to trap
+signals, write a specific C program, or use a shell.
+ - 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.
+
+
+
+
diff --git a/doc/dollarat.html b/doc/dollarat.html
new file mode 100644
index 0000000..2c09592
--- /dev/null
+++ b/doc/dollarat.html
@@ -0,0 +1,86 @@
+
+
+
+
+ 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. Any -d
+argument will be ignored. Warning: this option should only be used to feed
+data to programs that know how to handle null-separated lists.
+
+
+ Notes
+
+
+
+
+
diff --git a/doc/el_pushenv.html b/doc/el_pushenv.html
new file mode 100644
index 0000000..2ae16dd
--- /dev/null
+++ b/doc/el_pushenv.html
@@ -0,0 +1,173 @@
+
+
+
+
+ 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 import 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.
+
+
+
+
diff --git a/doc/el_semicolon.html b/doc/el_semicolon.html
new file mode 100644
index 0000000..615b411
--- /dev/null
+++ b/doc/el_semicolon.html
@@ -0,0 +1,124 @@
+
+
+
+
+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 everytime
+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.
+
+
+
+
diff --git a/doc/el_substitute.html b/doc/el_substitute.html
new file mode 100644
index 0000000..4da03f5
--- /dev/null
+++ b/doc/el_substitute.html
@@ -0,0 +1,309 @@
+
+
+
+
+ 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:
+
+
+
+
+
+
diff --git a/doc/el_transform.html b/doc/el_transform.html
new file mode 100644
index 0000000..094533a
--- /dev/null
+++ b/doc/el_transform.html
@@ -0,0 +1,204 @@
+
+
+
+
+ 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.
+
+
+
+
+ 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.
+
+
+
+ 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 can be requested by giving the -n switch to the
+substitution command. 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:
+
+
+
+
+ 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.
+
+
+
+
diff --git a/doc/elgetopt.html b/doc/elgetopt.html
new file mode 100644
index 0000000..a5650f2
--- /dev/null
+++ b/doc/elgetopt.html
@@ -0,0 +1,60 @@
+
+
+
+
+ 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.
+
+
+
+
diff --git a/doc/elgetpositionals.html b/doc/elgetpositionals.html
new file mode 100644
index 0000000..d193413
--- /dev/null
+++ b/doc/elgetpositionals.html
@@ -0,0 +1,94 @@
+
+
+
+
+ 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
+
+
+
+
+
diff --git a/doc/elglob.html b/doc/elglob.html
new file mode 100644
index 0000000..5b5d6aa
--- /dev/null
+++ b/doc/elglob.html
@@ -0,0 +1,68 @@
+
+
+
+
+ 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.
+
+
+
+
diff --git a/doc/emptyenv.html b/doc/emptyenv.html
new file mode 100644
index 0000000..81cf45a
--- /dev/null
+++ b/doc/emptyenv.html
@@ -0,0 +1,57 @@
+
+
+
+
+ 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
+elgetpositionals.
+ - -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.
+
+
+
+
diff --git a/doc/exec.html b/doc/exec.html
new file mode 100644
index 0000000..8655541
--- /dev/null
+++ b/doc/exec.html
@@ -0,0 +1,50 @@
+
+
+
+
+ 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.
+
+
+
+
diff --git a/doc/execline-shell.html b/doc/execline-shell.html
new file mode 100644
index 0000000..b3526f0
--- /dev/null
+++ b/doc/execline-shell.html
@@ -0,0 +1,53 @@
+
+
+
+
+ execline: the execline-shell script
+
+
+
+
+
+
+
+execline
+Software
+skarnet.org
+
+
+ The execline-shell script
+
+
+execline-shell executes $HOME/.execline-shell
+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 his 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
+provided in execline's etc/ subdirectory, and should be copied by
+the administrator to /etc.
+
+
+
+
diff --git a/doc/execline-startup.html b/doc/execline-startup.html
new file mode 100644
index 0000000..5df401d
--- /dev/null
+++ b/doc/execline-startup.html
@@ -0,0 +1,59 @@
+
+
+
+
+ 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 $@.
+ - ${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
+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.
+
+
+
+
diff --git a/doc/execlineb.html b/doc/execlineb.html
new file mode 100644
index 0000000..64f29bd
--- /dev/null
+++ b/doc/execlineb.html
@@ -0,0 +1,246 @@
+
+
+
+
+ execline: the execlineb command
+
+
+
+
+
+
+
+execline
+Software
+skarnet.org
+
+
+ The execlineb program
+
+
+execlineb reads and executes a script.
+
+
+ Interface
+
+
+ execlineb [ -q | -w | -W ] [ -p | -P | -S nmin ] -c script [ args... ]
+
+
+
+or
+
+
+
+ execlineb [ -q | -w | -W ] [ -p | -P | -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 neither the
+-p nor the -P nor the -S option is 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 neither the -P
+nor the -S option is 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 everytime 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.
+
+
+ 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.
+
+
+ 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 option, each execlineb
+invocation uses up some space in the environment.
+
+
+
+
diff --git a/doc/exit.html b/doc/exit.html
new file mode 100644
index 0000000..1e94ebd
--- /dev/null
+++ b/doc/exit.html
@@ -0,0 +1,44 @@
+
+
+
+
+ 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.
+
+
+
+
diff --git a/doc/export.html b/doc/export.html
new file mode 100644
index 0000000..35a7f68
--- /dev/null
+++ b/doc/export.html
@@ -0,0 +1,43 @@
+
+
+
+
+ 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 = .
+
+
+
+
diff --git a/doc/fdblock.html b/doc/fdblock.html
new file mode 100644
index 0000000..5b2bfa8
--- /dev/null
+++ b/doc/fdblock.html
@@ -0,0 +1,55 @@
+
+
+
+
+ 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.
+
+
+
+
diff --git a/doc/fdclose.html b/doc/fdclose.html
new file mode 100644
index 0000000..15265ac
--- /dev/null
+++ b/doc/fdclose.html
@@ -0,0 +1,44 @@
+
+
+
+
+ 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<&-'
+
+
+
+
diff --git a/doc/fdmove.html b/doc/fdmove.html
new file mode 100644
index 0000000..8498408
--- /dev/null
+++ b/doc/fdmove.html
@@ -0,0 +1,55 @@
+
+
+
+
+ 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 -c a b prog... is roughly equivalent to
+sh -c 'exec prog... a>&b'
+ - fdmove a b prog... is roughly equivalent to
+sh -c 'exec prog... a>&b b<&-'
+
+
+
+
diff --git a/doc/fdreserve.html b/doc/fdreserve.html
new file mode 100644
index 0000000..ef047dc
--- /dev/null
+++ b/doc/fdreserve.html
@@ -0,0 +1,92 @@
+
+
+
+
+ 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.)
+
+
+
+
diff --git a/doc/forbacktickx.html b/doc/forbacktickx.html
new file mode 100644
index 0000000..9e09c81
--- /dev/null
+++ b/doc/forbacktickx.html
@@ -0,0 +1,77 @@
+
+
+
+
+ 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 [ -p | -x breakcode ] [ -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.
+ - -0 : accept null characters from gen's output,
+using them as delimiters. If this option and a -d option are
+used simultaneously, the rightmost one wins.
+ - -x breakcodes : breakcodes must
+be a comma-separated list of exit codes. If at some point loop...
+exits with a code listed in breakcodes, forbacktickx will not keep
+looping, but will exit immediately with the same exit code. This doesn't apply
+if the -p option has been given.
+ - Other options are used to control
+the substitution mechanism for every x. Of course, you can't
+split x.
+
+
+ Notes
+
+
+ - You can start loop... with "import variable unexport variable"
+to perform variable substitution.
+
+
+
+
diff --git a/doc/foreground.html b/doc/foreground.html
new file mode 100644
index 0000000..a2a465f
--- /dev/null
+++ b/doc/foreground.html
@@ -0,0 +1,57 @@
+
+
+
+
+ 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...
+did not exit normally, the ? value is 111.
+ - 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...'.
+
+
+
+
+
diff --git a/doc/forx.html b/doc/forx.html
new file mode 100644
index 0000000..86729b8
--- /dev/null
+++ b/doc/forx.html
@@ -0,0 +1,66 @@
+
+
+
+
+ execline: the forx command
+
+
+
+
+
+
+
+execline
+Software
+skarnet.org
+
+
+ The forx program
+
+
+forx runs a loop.
+
+
+ Interface
+
+
+ In an execlineb script:
+
+
+
+ forx [ -p | -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
+
+
+ - -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, though.
+ - -x breakcodes : breakcodes 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 breakcodes,
+forx will not run the following instances of the loop, but exit immediately with the
+same exit code.
+
+
+ Notes
+
+
+ - You can start loop with "import variable unexport variable"
+if you want variable substitution.
+
+
+
+
diff --git a/doc/getpid.html b/doc/getpid.html
new file mode 100644
index 0000000..fb60c7c
--- /dev/null
+++ b/doc/getpid.html
@@ -0,0 +1,44 @@
+
+
+
+
+ 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 var prog...
+
+
+
+getpid stores its PID in the var variable, then
+execs into prog with its arguments.
+
+
+ Notes
+
+
+ - var must be given without a dollar !
+ - var must not contain =.
+
+
+
+
diff --git a/doc/grammar.html b/doc/grammar.html
new file mode 100644
index 0000000..6c26dbd
--- /dev/null
+++ b/doc/grammar.html
@@ -0,0 +1,160 @@
+
+
+
+
+ execline: language design and grammar
+
+
+
+
+
+
+
+execline
+Software
+skarnet.org
+
+
+ The execline language design and grammar
+
+
+ execline principles
+
+
+ Here are some basic Unix facts:
+
+
+
+ - Unix programs are started with the execve()
+system call, which takes 3 arguments: the command name (which
+we won't discuss here because it's redundant in most cases),
+the command line argv, which specifies the program name and its
+arguments, and the environment envp.
+ - The argv structure makes it easy to read some
+arguments at the beginning of argv, perform some action,
+then execve() into the rest of argv. For
+instance, the nice command works that way:
+
nice -10 echo blah
will read nice and -10
+from the argv, change the process' nice value, then exec into
+the command echo blah. This is called
+chain loading
+by some people, and
+Bernstein chaining by others.
+ - The purpose of the environment is to preserve some state across
+execve() calls. This state is usually small: most programs
+keep their information in the filesystem.
+ - A script is basically a text file whose meaning is a
+sequence of actions, i.e. calls to Unix programs, with some control
+over the execution flow. You need a program to interpret your script.
+Traditionally, this program is /bin/sh: scripts are written
+in the shell language.
+ - The shell reads and interprets the script command after command.
+That means it must preserve a state, and stay in memory while the
+script is running.
+ - Standard shells have lots of built-in features and commands, so
+they are big. Spawning (i.e. fork()ing then exec()ing)
+a shell script takes time, because the shell program itself must be
+initialized. For simple programs like nice -10 echo blah,
+a shell is overpowered - we only need a way to make an argv
+from the "nice -10 echo blah" string, and execve()
+into that argv.
+ - Unix systems have a size limit for argv+envp,
+but it is high. POSIX states that this limit must not be inferior to
+4 KB - and most simple scripts are smaller than that. Modern systems
+have a much higher limit: for instance, it is 64 KB on FreeBSD-4.6,
+and 128 KB on Linux.
+
+
+
+ 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.
+
+
+
+
+ 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:
+
+
+
+
+
+
diff --git a/doc/heredoc.html b/doc/heredoc.html
new file mode 100644
index 0000000..f49f880
--- /dev/null
+++ b/doc/heredoc.html
@@ -0,0 +1,56 @@
+
+
+
+
+ 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.
+
+
+
+
diff --git a/doc/homeof.html b/doc/homeof.html
new file mode 100644
index 0000000..31f2a40
--- /dev/null
+++ b/doc/homeof.html
@@ -0,0 +1,37 @@
+
+
+
+
+ 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.
+
+
+
+
diff --git a/doc/if.html b/doc/if.html
new file mode 100644
index 0000000..2157a07
--- /dev/null
+++ b/doc/if.html
@@ -0,0 +1,68 @@
+
+
+
+
+ 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 exits 1 with a special
+error message.
+ - If prog1 exits a non-zero status,
+if exits 1.
+ - Else if execs into prog2.
+
+
+ Options
+
+
+ - -X : treat a crash of prog1 as a non-zero ("false") exit.
+
- -n : negate the test (exit on true, exec into prog2 on false)
+ - -x exitcode : exit exitcode instead of 1 if the test fails.
+ - -t : exit 0 instead of 1 if the test fails.
+This is equivalent to -x 0.
+
+
+ Notes
+
+
+
+
+
diff --git a/doc/ifelse.html b/doc/ifelse.html
new file mode 100644
index 0000000..2298cf8
--- /dev/null
+++ b/doc/ifelse.html
@@ -0,0 +1,59 @@
+
+
+
+
+ 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 exits 1 with an error message.
+ - 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...'.
+
+
+
+
diff --git a/doc/ifte.html b/doc/ifte.html
new file mode 100644
index 0000000..40b0ec9
--- /dev/null
+++ b/doc/ifte.html
@@ -0,0 +1,67 @@
+
+
+
+
+ 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
+exits 1 with an error message.
+ - 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".
+
+
+
+
diff --git a/doc/ifthenelse.html b/doc/ifthenelse.html
new file mode 100644
index 0000000..3180412
--- /dev/null
+++ b/doc/ifthenelse.html
@@ -0,0 +1,59 @@
+
+
+
+
+ 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
+exits 1 with an error message.
+ - 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.
+
+
+
+
diff --git a/doc/import.html b/doc/import.html
new file mode 100644
index 0000000..1c6896c
--- /dev/null
+++ b/doc/import.html
@@ -0,0 +1,37 @@
+
+
+
+
+ execline: the import program
+
+
+
+
+
+
+
+execline
+Software
+skarnet.org
+
+
+ The import program
+
+
+import replaces an environment variable name with its value,
+then executes another program.
+
+
+ Interface
+
+
+ import [ -i | -D default ] [ -s ] [ -C | -c ] [ -n ] [ -d delim ] envvar prog...
+
+
+
+ - import behaves exactly as
+importas envvar envvar.
+
+
+
+
diff --git a/doc/importas.html b/doc/importas.html
new file mode 100644
index 0000000..a9c6f15
--- /dev/null
+++ b/doc/importas.html
@@ -0,0 +1,57 @@
+
+
+
+
+ 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 ] [ -s ] [ -C | -c ] [ -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, the null word is returned.
+ - 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 envvar is
+undefined, and this option is not given, substitute zero word for
+variable instead of the empty word; and if it is given,
+substitute default instead. 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.
+ - Other options are used to control
+the substitution mechanism.
+
+
+
+
diff --git a/doc/index.html b/doc/index.html
new file mode 100644
index 0000000..682e935
--- /dev/null
+++ b/doc/index.html
@@ -0,0 +1,213 @@
+
+
+
+
+ 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.0.0.0 or later
+
+
+ Licensing
+
+
+ execline is free software. It is available under the
+ISC license.
+
+
+ Download
+
+
+ - The current execline version is 2.0.0.0.
+
+
+ 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.
+
+
+ (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 is discussed on the
+skaware mailing-list.
+
+
+
+
diff --git a/doc/loopwhilex.html b/doc/loopwhilex.html
new file mode 100644
index 0000000..9def60f
--- /dev/null
+++ b/doc/loopwhilex.html
@@ -0,0 +1,60 @@
+
+
+
+
+ execline: the loopwhilex command
+
+
+
+
+
+
+
+execline
+Software
+skarnet.org
+
+
+ The loopwhilex program
+
+
+loopwhilex performs a conditional loop.
+
+
+ Interface
+
+
+ loopwhilex [ -n ] [ -x exitcodes ] 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 0. If prog was killed by a signal,
+loopwhilex exits that signal's number instead.
+
+
+ Options
+
+
+ - -x exitcodes : exitcodes must be a comma-separated
+list of valid exit codes. If this option is given, loopwhilex will exit if prog...'s
+exit code is listed in breakcodes.
+ - -n : negate the test: run prog... as long as it exits non-zero
+(or exits a code that is not listed in breakcodes).
+
+
+ Notes
+
+
+ - loopwhilex prog... is equivalent to loopwhilex -n -x 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.
+
+
+
+
diff --git a/doc/multidefine.html b/doc/multidefine.html
new file mode 100644
index 0000000..03f6b22
--- /dev/null
+++ b/doc/multidefine.html
@@ -0,0 +1,69 @@
+
+
+
+
+ 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 ] [ -d delim ] value { variables... } prog...
+
+
+
+ - multidefine reads a block
+containing a list of variables.
+ - 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.
+
+
+
+
diff --git a/doc/multisubstitute.html b/doc/multisubstitute.html
new file mode 100644
index 0000000..6400187
--- /dev/null
+++ b/doc/multisubstitute.html
@@ -0,0 +1,121 @@
+
+
+
+
+ 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 ] [ -s ] [ -C | -c ] [ -d delim ] variable value ]
+ [ importas [ -i | -D default ] [ -n ] [ -s ] [ -C | -c ] [ -d delim ] variable envvar ]
+ [ import [ -i | -D default ] [ -n ] [ -s ] [ -C | -c ] [ -d delim ] 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 a backtick directive was given with the -i option,
+and command crashes or exits nonzero, multisubstitute will
+also exit with the same exit code.
+ - If an import or 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}
+ import 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}
+ import 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.
+
+
+
+
diff --git a/doc/pipeline.html b/doc/pipeline.html
new file mode 100644
index 0000000..4f6677f
--- /dev/null
+++ b/doc/pipeline.html
@@ -0,0 +1,67 @@
+
+
+
+
+ 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: 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.
+
+
+
+
diff --git a/doc/piperw.html b/doc/piperw.html
new file mode 100644
index 0000000..64b9477
--- /dev/null
+++ b/doc/piperw.html
@@ -0,0 +1,38 @@
+
+
+
+
+ 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.
+
+
+
+
diff --git a/doc/quine-dam.txt b/doc/quine-dam.txt
new file mode 100644
index 0000000..c69a52c
--- /dev/null
+++ b/doc/quine-dam.txt
@@ -0,0 +1,110 @@
+#! /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.)
diff --git a/doc/quine-jriou.txt b/doc/quine-jriou.txt
new file mode 100644
index 0000000..f8e5455
--- /dev/null
+++ b/doc/quine-jriou.txt
@@ -0,0 +1,28 @@
+#!/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}
diff --git a/doc/quine-prj-2.txt b/doc/quine-prj-2.txt
new file mode 100644
index 0000000..9c60b92
--- /dev/null
+++ b/doc/quine-prj-2.txt
@@ -0,0 +1,15 @@
+#!/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
diff --git a/doc/quine-prj-3.txt b/doc/quine-prj-3.txt
new file mode 100644
index 0000000..e5b5708
--- /dev/null
+++ b/doc/quine-prj-3.txt
@@ -0,0 +1,13 @@
+#!/command/execlineb -P
+define e "#!/command/execlineb -P
+define e ${q}${E}${q}
+export E $e
+define q ${b}${q}
+define b ${b}${b}
+import E
+echo $e"
+export E $e
+define q \"
+define b \\
+import E
+echo $e
diff --git a/doc/quine-prj.txt b/doc/quine-prj.txt
new file mode 100644
index 0000000..8d2643f
--- /dev/null
+++ b/doc/quine-prj.txt
@@ -0,0 +1,13 @@
+#!/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
diff --git a/doc/redirfd.html b/doc/redirfd.html
new file mode 100644
index 0000000..fd29ef4
--- /dev/null
+++ b/doc/redirfd.html
@@ -0,0 +1,100 @@
+
+
+
+
+ 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 | -c | -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, -c, 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.
+ - -c : open file for appending. Do not create 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 -c n file prog... has no portable
+shell equivalent. Some shells provide the noclobber option for
+a similar feature.
+ - 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.
+
+
+
+
diff --git a/doc/runblock.html b/doc/runblock.html
new file mode 100644
index 0000000..6f5386e
--- /dev/null
+++ b/doc/runblock.html
@@ -0,0 +1,75 @@
+
+
+
+
+ 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.
+
+
+ Interface
+
+
+ runblock [ -P ] [ -n argshift ] [ -r ] n
+
+
+
+ - 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.
+ - 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.
+
+
+
+
diff --git a/doc/shift.html b/doc/shift.html
new file mode 100644
index 0000000..775e472
--- /dev/null
+++ b/doc/shift.html
@@ -0,0 +1,68 @@
+
+
+
+
+ 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.
+
+
+
+
diff --git a/doc/tryexec.html b/doc/tryexec.html
new file mode 100644
index 0000000..2fcc7b6
--- /dev/null
+++ b/doc/tryexec.html
@@ -0,0 +1,67 @@
+
+
+
+
+ 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.
+
+
+
+
diff --git a/doc/umask.html b/doc/umask.html
new file mode 100644
index 0000000..5edf511
--- /dev/null
+++ b/doc/umask.html
@@ -0,0 +1,44 @@
+
+
+
+
+ execline: the umask command
+
+
+
+
+
+
+
+execline
+Software
+skarnet.org
+
+
+ The umask program
+
+
+umask sets the umask (file creation mask),
+then executes a program.
+
+
+ Interface
+
+
+ umask mask prog...
+
+
+
+umask sets the current umask to mask,
+then execs into prog....
+
+
+ Notes
+
+
+umask is a standard shell builtin. Be careful if you want to
+use the umask command outside of an execline script.
+
+
+
+
diff --git a/doc/unexport.html b/doc/unexport.html
new file mode 100644
index 0000000..331189c
--- /dev/null
+++ b/doc/unexport.html
@@ -0,0 +1,46 @@
+
+
+
+
+ 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.
+
+
+
+
diff --git a/doc/upgrade.html b/doc/upgrade.html
new file mode 100644
index 0000000..9cd795b
--- /dev/null
+++ b/doc/upgrade.html
@@ -0,0 +1,35 @@
+
+
+
+
+ execline: how to upgrade
+
+
+
+
+
+
+
+execline
+Software
+skarnet.org
+
+
+
+ to 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.
+
+
+
+
diff --git a/doc/wait.html b/doc/wait.html
new file mode 100644
index 0000000..680cd78
--- /dev/null
+++ b/doc/wait.html
@@ -0,0 +1,53 @@
+
+
+
+
+ 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 [ -r ] { [ 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 : reap mode. Do not pause until a child has
+exited; only reap all pending zombies. The read block must be empty
+for that option to be effective.
+
+
+
+
--
cgit v1.2.3