diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2014-09-18 20:03:23 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2014-09-18 20:03:23 +0000 |
commit | f316a2ed52195135a35e32d7096e876357c48c69 (patch) | |
tree | 5f4486b9a5a213a69e66ef574d6bc643a207981c /doc | |
download | execline-f316a2ed52195135a35e32d7096e876357c48c69.tar.xz |
initial commit: rc for execline-2.0.0.0
Diffstat (limited to 'doc')
57 files changed, 4524 insertions, 0 deletions
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 @@ +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the background command</title> + <meta name="Description" content="execline: the background command" /> + <meta name="Keywords" content="execline command background" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> +</head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>background</tt> program </h1> + +<tt>background</tt> launches a command in the background, then goes on +with the execution flow. + +<h2> Interface </h2> + +<p> + In an <a href="execlineb.html">execlineb</a> script: +</p> + +<pre> + background [ -d ] { <em>prog1...</em> } <em>prog2...</em> +</pre> + +<ul> + <li> <tt>background</tt> reads a <em>prog1...</em> command in a +<a href="el_semicolon.html">block</a> and unquotes it. </li> + <li> It spawns a child executing <em>prog1...</em>. </li> + <li> It sets the <tt>!</tt> environment +variable to the pid of the <em>prog1...</em> process. </li> + <li> It then execs into <em>prog2...</em>. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-d</tt> : doublefork. If the <tt>-d</tt> option is set, +<em>prog1...</em> will run as a grandchild of <tt>background</tt>. </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> <tt>background <em>prog1...</em> "" <em>prog2...</em></tt> is +equivalent to <tt>sh -c '<em>prog1...</em> & ; exec <em>prog2...</em>'</tt>. </li> +</ul> + +</body> +</html> 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 @@ +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the backtick command</title> + <meta name="Description" content="execline: the backtick command" /> + <meta name="Keywords" content="execline command backtick" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> +</head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>backtick</tt> program </h1> + +<p> +<tt>backtick</tt> runs a program and uses its output as the argument of +another program. +</p> + +<h2> Interface </h2> + +<p> + In an <a href="execlineb.html">execlineb</a> script: +</p> + +<pre> + backtick [ -i ] [ -n ] <em>variable</em> { <em>prog1...</em> } <em>prog2...</em> +</pre> + +<ul> + <li> <tt>backtick</tt> reads <em>prog1...</em> in a +<a href="el_semicolon.html">block</a> and unquotes it. </li> + <li> It runs <em>prog1...</em> as a child process and saves its +output in memory. This output must not contain a null character. </li> + <li><tt>backtick</tt> execs into the modified <em>prog2...</em>, with +<em>variable</em> added to the environment with <em>prog1...</em>'s +output as a value. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-i</tt> : insist. If <em>prog1</em> exits non-zero, +<tt>backtick</tt> exits with the same exit code (or 111 if <em>prog1</em> +crashed for some reason). Without this option, <tt>backtick</tt> execs into +<em>prog2...</em> no matter what <em>prog1</em> does, with the null word as +<em>variable</em>'s value if <em>prog1</em> didn't write anything before +dying. </li> + <li> <tt>-n</tt> : chomp an ending newline off <em>prog1...</em>'s +output. </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> You can start <em>prog2...</em> with "import <em>variable</em> unexport <em>variable</em>" +to perform variable substitution. </li> +</ul> + +</body> +</html> 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 @@ +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the cd command</title> + <meta name="Description" content="execline: the cd command" /> + <meta name="Keywords" content="execline command cd chdir" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> +</head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>cd</tt> program </h1> + +<p> +<tt>cd</tt> changes the current working directory to a +given directory, then executes a program. +</p> + +<h2> Interface </h2> + +<pre> + cd <em>dir</em> <em>prog...</em> +</pre> + +<p> +<tt>cd</tt> performs a +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html">chdir()</a> +system call on <em>dir</em>, then execs into <em>prog...</em>. +</p> + +<h2> Notes </h2> + +<p> +<tt>cd</tt> is a standard shell builtin. Be careful if you want to +use the <tt>cd</tt> command outside of an <tt>execline</tt> script. +</p> + +</body> +</html> 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 @@ +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the define command</title> + <meta name="Description" content="execline: the define command" /> + <meta name="Keywords" content="execline command define" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> +</head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>define</tt> program </h1> + +<p> +<tt>define</tt> replaces a literal with a value, then executes +another program. +</p> + +<h2> Interface </h2> + +<pre> + define [ -s ] [ -C | -c ] [ -n ] [ -d <em>delim</em> ] <em>variable</em> <em>value</em> <em>prog...</em> +</pre> + +<ul> + <li> <tt>define</tt> performs +<a href="el_substitute.html">variable substitution</a> on +<em>prog...</em>, using <em>variable</em> as key and +<em>value</em> as value. +<tt>define</tt>'s options are used to <a href="el_transform.html">control +the substitution mechanism</a>. </li> + <li> <tt>define</tt> then execs into the modified <em>prog...</em>. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: why execline and not sh</title> + <meta name="Description" content="execline: why execline and not sh" /> + <meta name="Keywords" content="execline sh shell script language" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a><p /> + +<h1> Why not just use <tt>/bin/sh</tt> ? </h1> + + +<a name="security"> +<h2> Security </h2></a> + +<p> + One of the most frequent sources of security problems in programs +is <em>parsing</em>. Parsing is a complex operation, and it is easy to +make mistakes while designing and implementing a parser. (See +<a href="http://cr.yp.to/qmail/guarantee.html">what Dan Bernstein says +on the subject</a>, section 5.) +</p> + +<p> + But shells parse all the time. Worse, the <em>essence</em> +of the shell is parsing: the parser and the runner are intimately +interleaved and cannot be clearly separated, thanks to the +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html">specification</a>. +Even worse, the +shell sometimes has to perform <em>double parsing</em>, for instance +after parameter expansion. This can lead to atrocities like +<pre> +zork="foo ; echo bar" +touch $zork +</pre> not doing what you would like them to do, even in that simple +case. (<a href="http://www.zsh.org/">zsh</a> has a sane behaviour by +default, at the expense of explicitly breaking the spec.) +</p> + +<p> +<tt>execlineb</tt> 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 <tt>execlineb</tt> 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. +</p> + +<a name="portability"> +<h2> Portability </h2></a> + +<p> + 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 +<tt>sh</tt> flavours, not even counting the openly incompatible +<tt>csh</tt> approach and its various <tt>tcsh</tt>-like followers. +The <tt>ash</tt>, <tt>bash</tt>, <tt>ksh</tt> and <tt>zsh</tt> shells +all exhibit a different behaviour, <em>even when they are +run with the so-called compatibility mode</em>. From what I have +seen on various experiments, only <tt>zsh</tt> 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 <em>should</em> be able to assume that a script will run everywhere, +but <em>cannot</em> in practice. Even a simple utility like <tt>test</tt> +cannot be used safely with the normalized options, because most shells +come with a builtin <tt>test</tt> that does <em>not</em> respect the +specification to the letter. And let's not get started about <tt>echo</tt>, +which has its own set of problems. Rich Felker has +<a href="http://www.etalabs.net/sh_tricks.html">a page</a> listing tricks +to use to write portable shell scripts. Writing a portable script should +not be that hard. +</p> + +<p> +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. +</p> + +<p> + 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 <tt>/bin/sh</tt>, it is <em>almost</em> the case (Solaris +manages to get it wrong by having a non-POSIX shell as <tt>/bin/sh</tt> +and requiring something like <tt>#!/usr/xpg4/bin/sh</tt> to get a POSIX +shell to interpret your script). Other scripting languages are not so +lucky: perl can be <tt>/bin/perl</tt>, <tt>/usr/bin/perl</tt>, +<tt>/usr/local/bin/perl</tt> or something else entirely. For those cases, +some people advocate the use of <tt>env</tt>: <tt>#!/usr/bin/env perl</tt>. +But first, <tt>env</tt> 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 <tt>env</tt> utility does not +have a guaranteed absolute path. <tt>/usr/bin/env</tt> is the usual +convention, but not a strong guarantee: it is valid for systems to have +<tt>/bin/env</tt> instead, for instance. +</p> + +<p> +<tt>execline</tt> suffers from the same issues. <tt>#!/bin/execlineb</tt> ? +<tt>#!/usr/bin/execlineb</tt> ? This is the only portability problem that +you will find with execline, and it is common to every script language. +</p> + +<p> + The real solution to this portability problem is a convention that +guarantees fixed absolute paths for executables, which the FHS does not do. +The <a href="http://cr.yp.to/slashpackage.html">slashpackage</a> 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. +</p> + +<a name="simplicity"> +<h2> Simplicity </h2></a> + +<p> + I originally wanted a shell that could be used on an embedded system. +Even the <tt>ash</tt> shell seemed big, so I thought of writing my +own. Hence I had a look at the +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html">sh +specification</a>... and ran away screaming. +This specification +is <em>insane</em>. It goes against every good programming +practice; it seems to have been designed only to give headaches +to wannabe <tt>sh</tt> implementors. +</p> + +<p> + 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 +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/gets.html">gets</a> +function, but this is the way it is. +</p> + +<p> + 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 <tt>/bin/sh</tt>: +"It works, but it's far from not being a nightmare". +</p> + +<p> + 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 +<tt>sh</tt>, a seemingly simple and basic Unix program, is hard to +understand when you lift the cover. +</p> + +<p> + So I decided to forego sh entirely and take a new approach. So far it +has been working. + The <a href="grammar.html">execline specification</a> is simple, and, +as I hope to have shown, easy to implement without too many bugs or +glitches. +</p> + +<a name="performance"> +<h2> Performance </h2></a> + +<p> + Since it was made to run on an embedded system, <tt>execline</tt> was +designed to be light in memory usage. And it is. +</p> + +<ul> + <li> No overhead due to interactive support. </li> + <li> 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. </li> + <li> Very limited use of the C library. Only the C interface to the +kernel's system calls, and some very basic functions like <tt>malloc()</tt>, +are used in the C library. In addition to avoiding the horrible interfaces +like <tt>stdio</tt> 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. </li> +</ul> + +<p> + You can have hundreds of execline scripts running simultaneously on an +embedded box. Not exactly possible with a shell. +</p> + +<p> + For scripts than do not require many computations that a shell can do +without calling external programs, + <tt>execline</tt> is <em>faster</em> than the shell. +Unlike <tt>sh</tt>'s +one, the <tt>execline</tt> 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. +</p> + +<a name="comparison" /> +<ul> + <li> + 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. </li> + <li> 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. </li> + <li> 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 <em>scripting</em> language, not as a <em>programming</em> +language: it is efficient at being the glue that ties together programs +doing a job, not at implementing a program's logic. </li> +</ul> + +<a name="limitations"> +<h2> execline limitations </h2></a> + +<ul> + <li> <tt>execline</tt> can only handle scripts that fit in one <em>argv</em>. +Unix systems have a limit on the <em>argv</em>+<em>envp</em> size; +<tt>execline</tt> cannot execute scripts that are bigger than this limit.</li> + <li> <tt>execline</tt> 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. </li> + <li> Due to the <tt>execline</tt> design, maintaining a state is +difficult. Information has to transit via environment variables or +temporary files, which makes commands like +<a href="loopwhilex.html">loopwhilex</a> a bit painful to handle. </li> + <li> Despite all its problems, the main shell advantage (apart from +being available on every Unix platform, that is) is that it +is often <em>convenient</em>. Shell constructs can be terse and short, +where <tt>execline</tt> constructs will be verbose and lengthy. </li> + <li> An execline script is generally heavier on <tt>execve()</tt> 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 <em>statically compile</em> the +execline package, to eliminate the dynamic resolution costs. Unless +you're heavily looping around <tt>execve()</tt>, +the remaining costs will be negligible. </li> +</ul> + +</body> +</html> 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 @@ +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the dollarat command</title> + <meta name="Description" content="execline: the dollarat command" /> + <meta name="Keywords" content="execline command dollarat" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> +</head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>dollarat</tt> program </h1> + +<p> +<tt>dollarat</tt> prints the positional parameters of an execline script. +</p> + +<h2> Interface </h2> + +<pre> + dollarat [ -n ] [ -0 | -d <em>delimchar</em> ] +</pre> + +<ul> + <li> <tt>dollarat</tt> reads the number <em>n</em> of "positional +parameters" in the <tt>#</tt> environment variable. If that variable +is not set or does not contain a valid <em>n</em>, <tt>dollarat</tt> +exits 100. </li> + <li> <tt>dollarat</tt> prints the value of the <tt>1</tt> environment +variable, then <em>delimchar</em>, then the value of the <tt>2</tt> +environment variable... and so on until <tt><em>n</em></tt>. If one of +these variables is not set, <tt>dollarat</tt> exits 100. </li> + <li> If everything runs OK, <tt>dollarat</tt> exits 0. This makes it +one of the rare "exiting" execline commands. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-n</tt> : <em>chomp</em>. Do not print the last +<em>delimchar</em>. </li> + <li> <tt>-d</tt> <em>delimchar</em> : use the character +<em>delimchar</em> as separator between the arguments. Default: <tt>\n</tt>. +If <em>delimchar</em> has more than one character, only the first one is +used. If <em>delimchar</em> is the empty string, then <tt>dollarat</tt> +will output the positional parameters as a +<a href="el_transform.html#netstrings">sequence of netstrings</a> (and the +<tt>-n</tt> option will be ignored). </li> + <li> <tt>-0</tt> : use the null character as separator. Any <tt>-d</tt> +argument will be ignored. Warning: this option should only be used to feed +data to programs that know how to handle null-separated lists. </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> You can use <tt>dollarat -d ""</tt> along with the +<a href="forbacktickx.html">forbacktickx</a> command to reliably loop +over the positional parameters: +<pre> + #!/command/execlineb + forbacktickx -d "" ARG { dollarat -d "" } + dosomething $ARG +</pre> + + will call <tt>dosomething</tt> in turn on each argument to the script. +That will work even if those arguments contain spaces, newlines, +or other fancy characters. </li> + + <li> Alternatively, instead of encoding data into a netstring, you can +use a null-separated list, which will work the same way: +<pre> + #!/command/execlineb + forbacktickx -0 ARG { dollarat -0 } + dosomething $ARG +</pre> </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: pushing and popping the environment</title> + <meta name="Description" content="execline: pushing and popping the environment" /> + <meta name="Keywords" content="execline environment push pop el_pushenv el_popenv" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> Pushing and popping the environment </h1> + +<p> + The <a href="execlineb.html">execlineb</a> launcher +can store <em>positional +parameters</em>, i.e. arguments given to your script, into the +environment. The <tt>#</tt> variable contains the number of arguments; +the <tt>0</tt> variable contains the name of your execline script; +the <tt>1</tt> variable contains the first argument; and so on. +</p> + +<p> + 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 +<a href="runblock.html">runblock</a> command was impossible. +</p> + +<a name="push" /> + +<p> + To solve that issue, execline now implements a kind of <em>environment +stack</em>. When execlineb reads the arguments, it does +not overwrite the positional parameters, but <em>pushes</em> them on a +stack: +</p> + +<ul> + <li> <tt>#</tt> will be set to the current number of arguments </li> + <li> but if a variable named <tt>#</tt> existed before, it is renamed <tt>#:1</tt> </li> + <li> and if a variable named <tt>#:1</tt> also existed, it is renamed <tt>#:2</tt> </li> + <li> ... and so on until <tt>#:<em>n+1</em></tt> doesn't exist. </li> +</ul> + +<p> + Same goes for the other <em>positional parameters</em>. +</p> + +<p> + The script then runs; and commands such as +<a href="elgetpositionals.html">elgetpositionals</a> use the current +frame of positional parameters, without paying attention to the deeper +levels. +</p> + +<a name="pop" /> + +<p> + When you are done with the arguments, it is advisable to <em>drop</em> +the current frame, and <em>pop</em> the environment stack to get it back +to its previous state: +</p> + +<ul> + <li> <tt>#</tt> will be unset </li> + <li> but if <tt>#:1</tt> exists, it will be renamed <tt>#</tt> </li> + <li> and if <tt>#:2</tt> exists, it will be renamed <tt>#:1</tt> </li> + <li> ... and so on until <tt>#:<em>n+1</em></tt> doesn't exist. </li> +</ul> + +<p> + Again, same goes for the other <em>positional parameters</em>. <br /> +The <a href="runblock.html">runblock</a> command will perform that +<em>pop</em> operation automatically; the standard "manual" way to +perform it is to use the <a href="emptyenv.html">emptyenv -P</a> command. +</p> + +<h2> A pop example </h2> + +<p> + Suppose you want to run the long-lived program <em>prog</em> after +printing the list of its arguments. +</p> + +<pre> + #!/command/execlineb + elgetpositionals + foreground { echo $0 $@ } + prog $@ +</pre> + +<p> +will work, but will pollute <em>prog</em>'s environment with a set of +positional parameters that have no meaning to it. A better script is: +</p> + +<pre> + #!/command/execlineb + elgetpositionals + foreground { echo $0 $@ } + emptyenv -P + prog $@ +</pre> + +<p> +which will run <em>prog</em> with the same environment as the script's +caller. +</p> + +<a name="integrated" /> + +<h2> Substituting positional parameters without touching the environment </h2> + +<p> + 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 +<a href="elgetpositionals.html">elgetpositionals</a> and +<a href="emptyenv.html">emptyenv</a> chain. execline comes with an +integrated substitution mechanism, that does not touch the environment +at all: the <tt>-S <em>n</em></tt> option. +</p> + +<p> + Scripts beginning with: +</p> + +<pre> +#!/command/execlineb -S<em>n</em> +<em>foobar...</em> +</pre> + +<p> + are equivalent to: +</p> + +<pre> +#!/command/execlineb +elgetpositionals -P<em>n</em> +emptyenv -P +<em>foobar...</em> +</pre> + +<p> + So, to summarize, from most efficient (but less flexible) to least efficient +(but more flexible): +</p> + +<ul> + <li> Use <tt>execlineb -P</tt> if you don't need positional parameters +at all; for instance, in +<a href="http://skarnet.org/software/s6/">s6</a> or +<a href="http://smarden.org/runit/">runit</a> <em>run scripts</em>. </li> + <li> Use <tt>execlineb -S<em>n</em></tt> if you need only simple +positional parameter substitution in your script - no +<a href="shift.html">shift</a> or <a href="elgetopt.html">elgetopt</a>, +no <tt>import 1</tt>. </li> + <li> Use <tt>execlineb -p</tt>, then <tt>elgetpositionals</tt> if +you don't mind overwriting the current stack of positional parameters. </li> + <li> Use <tt>execlineb</tt>, then <tt>elgetpositionals</tt>, then +<tt>emptyenv -P</tt> if you need the full power of positional parameter +handling. </li> +</ul> + +</body> +</html> 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 @@ +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<meta http-equiv="Content-Language" content="en" /> +<title>execline: block management</title> +<meta name="Description" content="execline: block management" /> +<meta name="Keywords" content="execline block blocks null argument tilda semicolon el_semicolon" /> +<!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> +</head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> Blocks </h1> + +<p> +A command line (and thus an execline script) is one-dimensional. But a +Unix execution flow can be <em>two</em>-dimensional: when two +instructions are sequenced, for instance. In that case, we need a +way to extract <em>two</em> command lines from <em>one</em> argv. +That is precisely what <em>blocks</em> are made for. +</p> + +<p> + execline commands that need more than one linear set of arguments +use blocks. For instance, the +<a href="foreground.html">foreground</a> 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: +</p> +<pre> + #!/command/execlineb + foreground { echo 1 } echo 2 +</pre> +<p> + <tt>echo 1</tt> is read from a block and spawned; then +<tt>echo 2</tt> is executed. +</p> + +<h2> execlineb syntax </h2> + +<p> + In <a href="execlineb.html">execlineb</a> scripts, blocks are +delimited by braces. They can be nested. +</p> + +<h2> argv syntax </h2> + +<p> + execlineb reads and parses the script, and converts it into an <em>argv</em> +(a simple Unix command line) with a different syntax for blocks. +In an argv, blocks are not delimited by braces; +they are made of <em>quoted arguments</em> 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. +</p> + +<p> + Actually, the block-reading commands know nothing about braces; +they only understand the "quoted arguments + empty word" syntax. +So if you want to use <a href="foreground.html">foreground</a> +from your shell to sequence <tt>echo 1</tt> and +<tt>echo 2</tt>, you will have to write +</p> + +<pre> + $ foreground ' echo' ' 1' '' echo 2 +</pre> + +<p> + You do not really need to quote every argument inside a block in +that simple case. The following command works as well: +</p> + +<pre> + $ foreground echo 1 '' echo 2 +</pre> + +<p> + However, this is bad practice, because it leads to a security hole: +commands that perform +<a href="el_substitute.html">substitution</a> inside a block may +produce empty words, which may modify your script's execution flow. +</p> + +<pre> + $ define FOO '' foreground ' echo' ' ${FOO}' ' rm' ' -rf' ' /' '' echo blah +</pre> + +<p> + is safe, whereas +</p> + +<pre> + $ define FOO '' foreground echo '${FOO}' rm -rf / '' echo blah +</pre> + +<p> + has very much unwanted results. (Don't try this at home.) +</p> + +<p> + You can use the <tt>EXECLINE_STRICT</tt> environment variable to +check proper block quoting. If that variable contains <tt>1</tt>, +commands that read blocks will print a warning message everytime +they find an unquoted argument inside a block. If that variable +contains <tt>2</tt> or a bigger integer, commands will print an +error message and die on unquoted arguments. +<br /> You can use <a href="execlineb.html">execlineb</a>'s +<tt>-w</tt> or <tt>-W</tt> +switch to set <tt>EXECLINE_STRICT</tt> to <tt>1</tt> or <tt>2</tt>. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: variable substitution</title> + <meta name="Description" content="execline: variable substitution" /> + <meta name="Keywords" content="execline variable substitution el_substitute" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> Variable substitution </h1> + +<p> + In a shell, when you write +</p> +<pre> + $ A='foobar' ; echo $A +</pre> +<p> + the <tt>echo</tt> command is given the argument <tt>foobar</tt>. +The <tt>foobar</tt> <em>value</em> has been substituted for the +<tt>A</tt> <em>variable</em>. +</p> +<p> + Although <tt>execline</tt> maintains no state, and thus has no +real variables, it provides such a <em>substitution</em> facility +via <em>substitution commands</em>, namely: +</p> +<ul> + <li> <a href="define.html">define</a> </li> + <li> <a href="import.html">import</a> </li> + <li> <a href="importas.html">importas</a> </li> + <li> <a href="elglob.html">elglob</a> </li> + <li> <a href="elgetpositionals.html">elgetpositionals</a> </li> + <li> <a href="multidefine.html">multidefine</a> </li> + <li> <a href="multisubstitute.html">multisubstitute</a> </li> +</ul> + +<p> + A substitution command takes a <em>key</em>, i.e. a string +(which can contain any character but <tt>$</tt>, <tt>{</tt> and +<tt>}</tt>, although it is recommended to use only alphanumerical +characters), and a way to compute a <em>value</em>. +</p> + +<h2> Basics </h2> + +<ul> + <li> If the substitution key is <em>foo</em>, then the substitution +command will look for every occurrence of <tt>${<em>foo</em>}</tt> or +<tt>$<em>foo</em></tt> in the rest of its argv. Note that +<tt>${<em>foo</em>}bar</tt> matches, but <tt>$<em>foo</em>bar</tt> +<strong>does not</strong>. To be safe, always use the syntax with +braces, unless <tt>$<em>foo</em></tt> is a word on its own. </li> + <li> Every match is then replaced with the <em>value</em>. </li> +</ul> + +<p> +The simplest example is the following: +</p> + +<pre> +#!/command/execlineb +define FOO blah +echo $FOO +</pre> + +<p> + which will replace the <tt>FOO</tt> key with the <tt>blah</tt> value, +then execute the <tt>echo</tt> command. So that script will print +<tt>blah</tt> on stdout. +</p> + +<a name="quoting" /> +<h2> Quoting </h2> + +<p> + execline allows you to write literal <tt>${<em>foo</em>}</tt> constructs +even when the <em>foo</em> variable is being substituted, thanks to a +quoting mechanism. + Brace (pun intended) yourself: the following is the most complex part +of the whole language. +</p> + +<h3> Rationale </h3> + +<p> + If we want to be able to have a literal <tt>${<em>foo</em>}</tt>, then: +</p> +<ul> + <li> The <tt>${<em>foo</em>}</tt> sequence will mean one of two things: +be substituted, or <em>don't</em> be substituted. </li> + <li> The default (unquoted) action should be: substitute. </li> + <li> 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 ?) </li> + <li> There should be as few quote characters as possible, to avoid +shell-like quoting nightmares. </li> +</ul> + +<h3> Syntax </h3> + +<p> + Rule: +</p> + +<ul> + <li> The backslash (<tt>\</tt>) is a quote character for substitution commands. </li> + <li> The following rule applies only if the <em>foo</em> key is +explicitly used in a substitution command. If no command tries to +substitute anything for <em>foo</em>, sequences like +<tt>${<em>foo</em>}</tt> and preceding backslashes are left untouched. </li> + <li> (Substitute.) If <tt>${<em>foo</em>}</tt> is preceded by <tt>2*n</tt> backslashes +(an <strong>even</strong> number), the whole sequence will be +replaced with <tt>n</tt> backslashes, followed by the substituted value. </li> + <li> (Do not substitute.) If <tt>${<em>foo</em>}</tt> is preceded by <tt>2*n+1</tt> backslashes +(an <strong>odd</strong> number), the whole sequence will be replaced +with <tt>n</tt> backslashes, followed by the literal <tt>${<em>foo</em>}</tt>. </li> +</ul> + +<p> + And now, the catch: the <a href="execlineb.html">execlineb</a> launcher, +as well as the shell, +interprets backslashes as escape characters. To make a word that contains +a backlash, you need to write <em>two</em> backslashes in your execline +script or shell command line. That means that the whole number of backslashes +you must write before your <tt>${<em>foo</em>}</tt> sequence must be doubled +for the substitution command to read the proper number of backslashes and +perform its work correctly. <br /> + Once you keep that in mind, the quoting rule is logical. +</p> + +<h3> Example </h3> + +<p> + The quoting rule is best illustrated with the following example, where +the <tt>A</tt> key is substituted, and the <tt>$B</tt> sequences mean +nothing special. +</p> + +<pre> +#!/command/execlineb +define A val +foreground { echo $A \\$A \\\\$A \\\\\\$A \\\\\\\\$A \\\\\\\\\\$A } + echo $B \\$B \\\\$B \\\\\\$B \\\\\\\\$B \\\\\\\\\\$B +</pre> +<p> + prints +</p> +<pre> +val $A \val \$A \\val \\$A +$B \$B \\$B \\\$B \\\\$B \\\\\$B +</pre> + +<p> + Phew. +</p> + +<a name="el_transform"> +<h2> Value transformations </h2> +</a> + +<p> + A value can go through +<a href="el_transform.html">several transformations</a> before it is +substituted. It can be <a href="el_transform.html#crunch">crunched</a>, +<a href="el_transform.html#chomp">chomped</a>, and/or +<a href="el_transform.html#split">split</a>. +</p> + +<a name="split"> +<h2> Substitution of split values </h2> +</a> + +<p> + A <a href="el_transform.html">split</a> value for <tt>FOO</tt> means that +a word containing <tt>${FOO}</tt> will be replaced by zero, one, or +(usually) more than one word. The value actually means a +<em>list</em> of values. +</p> + +<p> + The rule is: substituting a list of values +(<em>v1</em>, <em>v2</em>, <em>...</em>) for a key <em>A</em> is the +same as listing the substitutions of every value <em>v<tt>i</tt></em> +for <em>A</em>. <br /> + For instance, +</p> + +<pre> +#!/command/execlineb +define -s FOO "v1 v2 v3" echo prefix-${FOO}-postfix +</pre> + +<p> + will substitute three values for <tt>$FOO</tt>: <tt>v1</tt>, <tt>v2</tt> +and <tt>v3</tt>. So the <tt>echo</tt> command will be called with three +arguments: <tt>prefix-v1-postfix</tt>, <tt>prefix-v2-postfix</tt>, and +<tt>prefix-v3-postfix</tt>. +</p> + +<p> +(Implementation note: the fact that word prefixes are kept is +what makes execline's subtitutions secure. +<a href="el_semicolon.html">Blocks</a> 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.) +</p> + +<a name="recursive" /> +<h3> Recursive substitutions </h3> + +<p> + 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 +</p> + +<pre> +#!/command/execlineb +define -s B "1 2 3" echo ${B}x${B} +</pre> +<p> + the <tt>${B}x${B}</tt> word will be replaced with <em>nine</em> words: +<tt>1x1</tt>, <tt>1x2</tt>, <tt>1x3</tt>, <tt>2x1</tt>, <tt>2x2</tt>, +<tt>2x3</tt>, <tt>3x1</tt>, <tt>3x2</tt>, and <tt>3x3</tt>, in that order. +<br /> Here is an example with two distinct substitutions in parallel: +</p> + +<pre> +#!/command/execlineb +multisubstitute +{ + define -s A "a b c d" + define -s B "1 2 3" +} +echo ${A}x${B} +</pre> + +<p> + The <tt>${A}x${B}</tt> word will be replaced with <em>twelve</em> words: +<tt>ax1</tt>, <tt>ax2</tt>, <tt>ax3</tt>, <tt>bx1</tt>, <tt>bx2</tt>, +<tt>bx3</tt>, <tt>cx1</tt>, <tt>cx2</tt>, <tt>cx3</tt>, <tt>dx1</tt>, +<tt>dx2</tt>, and <tt>dx3</tt>, in that order. You can check that the +order of the <tt>define</tt> directives in +<a href="multisubstitute.html">multisubstitute</a> does not matter. +</p> + +<p> +If the left-to-right order does not suit you, then you should perform +<em>serial</em> substitutions. For instance, the previous script can +be replaced with +</p> + +<pre> +#!/command/execlineb +define -s B "1 2 3" +define -s A "a b c d" +echo ${A}x${B} +</pre> +<p> + and will substitute <tt>${B}</tt> first, then <tt>${A}</tt>. So it +will print +</p> + +<pre> +ax1 bx1 cx1 dx1 ax2 bx2 cx2 dx2 ax3 bx3 cx3 dx3 +</pre> + +<p> + in that order. +</p> + +<a name="brainfsck"></a> +<h2> Not for the faint of heart </h2> + +<p> + If you think you have mastered the art of execline substitution, then +you can try to do better than these people: +</p> + +<ul> + <li><a href="http://jriou.org/">Joël Riou</a> +wrote the <a href="quine-jriou.txt">first execlineb quine</a>, using +only <tt>echo</tt> as non-execline external command. </li> + <li> Shortly after, <a href="http://code.dogmap.org/">Paul Jarc</a> +wrote a <a href="quine-prj.txt">much shorter quine</a>, using +<tt>echo</tt> and <tt>env</tt> as non-execline external commands. He +also wrote a <a href="quine-prj-2.txt">revised version</a>, using only +<tt>echo</tt>, and a shorter <a href="quine-prj-3.txt">definitive +version</a>. The last one is probably very close to the shortest +possible execline quine. </li> + <li> <a href="http://www.madore.org/~david/">David Madore</a> +wrote <a href="quine-dam.txt">another quine</a>, using <tt>printf</tt>. +His quine is longer than the other ones, but is well-commented and can +be used as a tutorial on how to write quines. :) </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: value transformation</title> + <meta name="Description" content="execline: value transformation" /> + <meta name="Keywords" content="execline value transformation el_transform crunch chomp split" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> Value transformation </h1> + +<p> + You can apply 3 kinds of transformations to a value which is to be +<a href="el_substitute.html">substituted</a> for a variable: +crunching, chomping and splitting. They +always occur in that order. +</p> + + +<a name="delim"> +<h2> Delimiters </h2> +</a> + +<p> + The transformations work around <em>delimiters</em>. 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 <tt>-d</tt> option +used by substitution commands. By default, the string "<tt> \n\r\t</tt>" +is used, which means that the default delimiters are spaces, newlines, +carriage returns and tabs. +</p> + + +<a name="crunch"> +<h2> Crunching </h2> +</a> + +<p> + 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 <em>crunching</em>, and it is done +by giving the <tt>-C</tt> switch to the substitution command. The +remaining delimiter will always be the first in the sequence. +</p> + +<p> + Crunching is mainly useful when also <a href="#split">splitting</a>. +</p> + +<a name="chomp"> +<h2> Chomping </h2> +</a> + +<p> + Sometimes you don't want the last delimiter in a value. + <em>Chomping</em> deletes the last character of a value if it is a +delimiter. It can be requested by giving the <tt>-n</tt> switch to the +substitution command. Note that chomping always happens <em>after</em> +crunching, which means you can use crunching+chomping to ignore, for +instance, a set of trailing spaces. +</p> + + +<a name="split"> +<h2> Splitting </h2> +</a> + +<p> + In a shell, when you write +</p> + +<pre> + $ A='foo bar' ; echo $A +</pre> + +<p> + the <tt>echo</tt> command is given two arguments, <tt>foo</tt> +and <tt>bar</tt>. The <tt>$A</tt> value has been <em>split</em>, +and the space between <tt>foo</tt> and <tt>bar</tt> acted as a +<em>delimiter</em>. +</p> + +<p> +If you want to avoid splitting, you must write something like +</p> + +<pre> + $ A='foo bar' ; echo "$A" +</pre> + +<p> + 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. +</p> + +<p> + <tt>execline</tt> provides a <em>splitting</em> facility, with +several advantages over the shell's: +</p> + +<ul> + <li> Splitting has to be explicitly requested, by specifying the +<tt>-s</tt> option to commands that perform +<a href="el_substitute.html">substitution</a>. By default, +substitutions are performed as is, without interpreting the +characters in the value. </li> + <li> Positional parameters are never split, so that execline +scripts can handle arguments the way the user intended to. To +split <tt>$1</tt>, for instance, you have to ask for it +specifically: +<pre> +#!/command/<a href="execlineb.html">execlineb</a> -S1 +<a href="define.html">define</a> -sd" " ARG1S $1 +blah $ARG1S +</pre> + and $ARG1S will be split using the space character as only delimiter. + </li> + <li> Any character can be a delimiter. </li> +</ul> + +<h3> How it works </h3> + +<ul> + <li> A substitution command can request that the substitution value +be split, via the <tt>-s</tt> switch. </li> + <li> The splitting function parses the value, looking for delimiters. +It fills up a structure, marking the split points, and the number +<em>n</em> of words the value is to be split into. + <ul> + <li> A word is a sequence of characters in the value <em>terminated +by a delimiter</em>. The delimiter is not included in the word. </li> + <li> If the value begins with <em>x</em> delimiters, the word list +will begin with <em>x</em> empty words. </li> + <li> 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 <a href="#chomp">chomping</a> and there was no delimiter at +the end of the value <em>before</em> the chomp operation - in which case +that last sequence will not appear at all. </li> + </ul> </li> + <li> 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 <em>n</em> separate words. </li> + <li> Substitution of split values is +<a href="el_substitute.html#recursive">performed recursively</a>. </li> +</ul> + + +<a name="netstrings"> +<h3> Decoding netstrings </h3> +</a> + +<p> + <a href="http://cr.yp.to/proto/netstrings.txt">Netstrings</a> are +a way to reliably encode strings containing arbitrary characters. +<tt>execline</tt> 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 <tt>-d ""</tt> 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: +</p> + +<pre> + $ define -s -d "" A '1:a,2:bb,0:,7:xyz 123,1: ,' echo '$A' +</pre> + +<p> + the <tt>echo</tt> command will be given five arguments: +</p> + +<ul> + <li> the "<tt>a</tt>" string </li> + <li> the "<tt>bb</tt>" string </li> + <li> the empty string </li> + <li> the "<tt>xyz 123</tt>" string </li> + <li> the "<tt> </tt>" string (a single space) </li> +</ul> + +<p> + However, if the value is not a valid sequence of netstrings, the +substitution command will die with an error message. +</p> + +<p> + The <a href="dollarat.html">dollarat</a> 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 <tt>-d ""</tt> option. +</p> + +</body> +</html> 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 @@ +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the elgetopt command</title> + <meta name="Description" content="execline: the elgetopt command" /> + <meta name="Keywords" content="execline command elgetopt options arguments" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> +</head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +<p /> + +<h1> The <tt>elgetopt</tt> program </h1> + +<p> +<tt>elgetopt</tt> performs <tt>getopt</tt>-style parsing on the +arguments to an execline script. +</p> + +<h2> Interface </h2> + +<pre> + elgetopt <em>optstring</em> <em>prog...</em> +</pre> + +<ul> + <li> <tt>elgetopt</tt> expects to find a valid number <em>n</em> of +arguments in the <tt>#</tt> environment variable, and <em>n</em>+1 +environment variables <tt>0</tt>, <tt>1</tt>, ..., <tt><em>n</em></tt>. +It exits 100 if it is not the case. </li> + <li> <tt>elgetopt</tt> <a href="el_pushenv.html">pushes</a> +environment variables starting with <tt>ELGETOPT_</tt>. To get the +previous values back, use +<a href="emptyenv.html"><tt>emptyenv -o</tt></a>. </li> + <li> <tt>elgetopt</tt> looks into <tt>1</tt>, <tt>2</tt>... for options, +as specified by <em>optstring</em>, which is a standard <tt>getopt</tt> +string. </li> + <li> If the <tt>-<em>c</em></tt> switch is recognized, <tt>elgetopt</tt> +sets the <tt>ELGETOPT_<em>c</em></tt> environment variable. The value +of that variable is the argument to the <tt>-<em>c</em></tt> switch if +it has one, and 1 otherwise. </li> + <li> After setting all recognized options, <tt>elgetopt</tt> makes +new <tt>#</tt>, <tt>1</tt>, <tt>2</tt>... "positional parameters" with +what remains. </li> + <li> <tt>elgetopt</tt> then execs into <em>prog...</em>. </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> GNU-style options are not supported. </li> +</ul> + +</body> +</html> 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 @@ +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the elgetpositionals command</title> + <meta name="Description" content="execline: the elgetpositionals command" /> + <meta name="Keywords" content="execline command elgetpositionals arguments positional parameters" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> +</head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +<p /> + +<h1> The <tt>elgetpositionals</tt> program </h1> + +<p> +<tt>elgetpositionals</tt> substitutes the positional parameters of an execline script. +</p> + +<h2> Interface </h2> + +<pre> + elgetpositionals [ -P <em>sharp</em> ] <em>prog...</em> +</pre> + +<ul> + <li> <tt>elgetpositionals</tt> reads the number <em>n</em> of "positional +parameters" in the <tt>#</tt> environment variable. If that variable +is not set or does not contain a valid <em>n</em>, <tt>elgetpositionals</tt> +exits 100. </li> + <li> <tt>elgetpositionals</tt> performs some +<a href="el_substitute.html">substitutions</a> in parallel on +<em>prog...</em>: +<ul> + <li> key: <tt>#</tt>, value: <em>n</em> </li> + <li> key: <tt>0</tt>, value: the value of the <tt>0</tt> environment +variable </li> + <li> key: <tt>1</tt>, value: the value of the <tt>1</tt> environment +variable </li> + <li> ... and so on until <em>n</em> (or <em>sharp</em> if it is +greater than <em>n</em>). Those values are never transformed. </li> + <li> key: <tt>@</tt>, value: all values of the variables from <tt>1</tt> to +<tt><em>n</em></tt>. This value is <a href="el_transform.html#split">split</a> +into <em>n</em> words. </li> +</ul> + If a variable between <tt>0</tt> and <tt><em>n</em></tt> does not +exist, <tt>elgetpositionals</tt> exits 100. + </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-P</tt> <em>sharp</em> : substitute at least +<em>sharp</em>+1 positional parameters, from 0 to +max(<em>n</em>, <em>sharp</em>). If <em>n</em><<em>sharp</em>, +positional parameters between <em>n</em>+1 and <em>sharp</em> are +replaced with the empty string. Not having the <tt>-P</tt> switch is +equivalent to having <tt>-P 0</tt>. </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> A typical argument-taking execline script will +often begin that way: +<pre> + #!/command/execlineb + elgetopt <em>optstring</em> + elgetpositionals + <em>prog...</em> +</pre> +</li> + <li> If you are performing other substitutions that do not depend +on the positional parameters, think about replacing the +<tt>elgetpositionals</tt> call with a +<a href="multisubstitute.html">multisubstitute</a> call containing +the <tt>elgetpositionals</tt> directive. </li> + <li> If you are going to use the <a href="shift.html">shift</a> +command, it is best to use <a href="importas.html">importas</a> to +substitute the first positional parameters, then use <tt>shift</tt>, +then <tt>elgetpositionals</tt>. That way, <tt>$@</tt> will correctly +be replaced by the remaining arguments. More generally, you should +try to use <tt>elgetpositionals</tt> as late as possible. </li> + <li> Use <tt>execlineb</tt>'s <tt>-S</tt> switch instead of +<tt>elgetpositionals</tt> whenever you can. It is more efficient. </li> +</ul> + +</body> +</html> 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 @@ +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the elglob command</title> + <meta name="Description" content="execline: the elglob command" /> + <meta name="Keywords" content="execline command elglob pattern shell globbing" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> +</head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +<p /> + +<h1> The <tt>elglob</tt> program </h1> + +<p> +<tt>elglob</tt> performs globbing on a pattern, then executes +another program. +</p> + +<h2> Interface </h2> + +<pre> + elglob [ -v ] [ -w ] [ -s ] [ -m ] [ -e ] [ -0 ] <em>variable</em> <em>pattern</em> <em>prog...</em> +</pre> + +<ul> + <li> <tt>elglob</tt> performs +<a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/glob.html">globbing</a> +on <em>pattern</em>. </li> + <li> It then performs +<a href="el_substitute.html">variable substitution</a> on +<em>prog...</em>, using <em>variable</em> 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. </li> + <li> <tt>elglob</tt> then execs into the modified <em>prog...</em>. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-v</tt> : verbose. If there is a problem while globbing, print +a warning message on stderr. </li> + <li> <tt>-w</tt> : strict. If there is a problem while globbing, die +immediately. This is harsh - you probably don't need that option. </li> + <li> <tt>-s</tt> : sort the matches. By default, the results are +left unsorted. </li> + <li> <tt>-m</tt> : mark. Append a slash to each word that corresponds +to a directory. </li> + <li> <tt>-e</tt> : no escape. Treat backslashes in <em>pattern</em> +literally; do not allow quoting of metacharacters in <em>pattern</em> via +backslashes. <strong>Warning</strong>: the +<a href="execlineb.html">execlineb</a> launcher +uses the backslash as their own escape character - if you want a +backslash to be passed to <tt>elglob</tt>, do not forget to <em>double</em> +it. </li> + <li> <tt>-0</tt> : null globbing. By default, if <em>pattern</em> +matches nothing, it will be substituted as is (verbatim in one word). With +this option, if <em>pattern</em> matches nothing, it will be properly +substituted as zero word. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the emptyenv program</title> + <meta name="Description" content="execline: the emptyenv program" /> + <meta name="Keywords" content="execline command emptyenv" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>emptyenv</tt> program </h1> + +<p> +<tt>emptyenv</tt> empties the current environment, or cleans it up; then +executes a program. +</p> + +<h2> Interface </h2> + +<pre> + emptyenv [ -p ] <em>prog...</em> + emptyenv -c <em>prog...</em> + emptyenv [ -o ] [ -P ] <em>prog...</em> +</pre> + +<p> +By default, <tt>emptyenv</tt> unsets all environment variables, then +execs into <em>prog</em> with its arguments. Options control which +environment variables are unset. +</p> + +<h2> Options </h2> + +<ul> + <li> <tt>-p</tt> : keep the <tt>PATH</tt> environment variable. </li> + <li> <tt>-c</tt> : 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. </li> + <li> <tt>-o</tt> : <a href="el_pushenv.html#pop">pop</a> environment +variables starting with <tt>ELGETOPT_</tt>. You might want to do this +before executing a final program from a script that uses +<a href="elgetpositionals.html">elgetpositionals</a>. </li> + <li> <tt>-P</tt> : <a href="el_pushenv.html#pop">pop</a> environment +variables starting with <tt>#</tt>, <tt>0</tt> to <tt>9</tt>, and +<tt>EXECLINE_</tt>. You might want to do this before executing a final program +from a script launched by <a href="execlineb.html">execlineb</a>. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the exec program</title> + <meta name="Description" content="execline: the exec program" /> + <meta name="Keywords" content="execline command exec" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>exec</tt> program </h1> + +<p> +<tt>exec</tt> executes the command line it is given. +</p> + +<h2> Interface </h2> + +<pre> + exec [ -c ] [ -l ] [ -a <em>argv0</em> ]<em>prog...</em> +</pre> + +<p> +<tt>exec</tt> execs into <em>prog...</em>. It does nothing else. +<br /> Without options, <tt>exec</tt> can be seen as the execline NOP. +</p> + +<h2> Options </h2> + +<ul> + <li> <tt>-c</tt> : empty the environment. <em>prog</em> is executed with no environment variables. <strong>Warning: </strong><em>prog</em> will run with an empty PATH, so make sure it does not rely on it. </li> + <li> <tt>-l</tt> : login. Prepends <em>prog</em>'s argv[0] with a dash. </li> + <li> <tt>-a <em>argv0</em></tt> : argv0. Replace <em>prog</em>'s argv[0] with <em>argv0</em>. This is done <em>before</em> adding a dash, if the <tt>-l</tt> option is also present. </li> +</ul> + +<p> +The <tt>exec</tt> command, along with its options, is designed to emulate +the standard <tt>exec</tt> shell builtin, which replaces the shell with the +command it is given. +</p> + +</body> +</html> 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 @@ +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the execline-shell script</title> + <meta name="Description" content="execline: the execline-shell script" /> + <meta name="Keywords" content="execline script execline-shell" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> +</head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>execline-shell</tt> script </h1> + +<p> +<tt>execline-shell</tt> executes <tt>$HOME/.execline-shell</tt> +with the arguments it is given. +</p> + +<h2> Interface </h2> + +<pre> + /etc/execline-shell +</pre> + +<ul> + <li> <tt>execline-shell</tt> transforms itself into +<tt>${HOME}/.execline-shell $@</tt>. </li> + <li><tt>${HOME}/.execline-shell</tt> must be readable and +executable by the user. It must exec into an interactive +shell with <tt>$@</tt> as its argument.</li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> <tt>execline-shell</tt> is meant to be used as the <tt>SHELL</tt> +environment variable value. It allows one to specify his favourite shell and +shell configuration in any language, since the <tt>${HOME}/.execline-shell</tt> +file can be any executable program. <tt>${HOME}/.execline-shell</tt> can be seen +as a portable <tt>.<em>whatever</em>rc</tt> file. </li> + <li> As an administrator-modifiable configuration file, <tt>execline-shell</tt> +provided in execline's <tt>etc/</tt> subdirectory, and should be copied by +the administrator to <tt>/etc</tt>. </li> +</ul> + +</body> +</html> 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 @@ +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the execline-startup script</title> + <meta name="Description" content="execline: the execline-startup script" /> + <meta name="Keywords" content="execline execline-startup startup login script .profile" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> +</head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>execline-startup</tt> script </h1> + +<p> +<tt>execline-startup</tt> performs some system-specific +login initialization, then executes <tt>${HOME}/.execline-loginshell</tt>. +</p> + +<h2> Interface </h2> + +<pre> + /etc/execline-startup +</pre> + +<ul> + <li> <tt>execline-startup</tt> sets the <tt>SHELL</tt> +environment variable to <tt>/etc/execline-shell</tt>. +It then performs some system-specific initialization, and +transforms itself into <tt>${HOME}/.execline-loginshell $@</tt>. </li> + <li><tt>${HOME}/.execline-loginshell</tt> must be readable and +executable by the user. It must exec into <tt>$SHELL $@</tt>. </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> <tt>execline-startup</tt> is an +<a href="execlineb.html">execlineb</a> script; hence, it is readable +and modifiable. It is meant to be modified by the system administrator +to perform system-specific login-time initialization. </li> + <li> As a modifiable configuration file, execline-startup is provided in execline's +<tt>etc/</tt> subdirectory, and should be copied by the administrator +to <tt>/etc</tt>. </li> + <li> <tt>execline-startup</tt> is meant to be used as a login shell. +System administrators should manually add <tt>/etc/execline-startup</tt> +to the <tt>/etc/shells</tt> file. The <tt>/etc/execline-startup</tt> +file itself plays the role of the <tt>/etc/profile</tt> file, and +<tt>${HOME}/.execline-loginshell</tt> plays the role of the +<tt>${HOME}/.profile</tt> file.</li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-6" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the execlineb command</title> + <meta name="Description" content="execline: the execlineb command" /> + <meta name="Keywords" content="execline command execlineb launcher" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>execlineb</tt> program </h1> + +<p> +<tt>execlineb</tt> reads and executes a script. +</p> + +<h2> Interface </h2> + +<pre> + execlineb [ -q | -w | -W ] [ -p | -P | -S <em>nmin</em> ] -c <em>script</em> [ <em>args...</em> ] +</pre> + +<p> +or +</p> + +<pre> + execlineb [ -q | -w | -W ] [ -p | -P | -S <em>nmin</em> ] <em>scriptfile</em> [ <em>args...</em> ] +</pre> + +<p> +or in an executable file: +</p> + +<pre> +#!/command/execlineb [ -qwWpPS<em>nmin</em> ] +<em>script</em> +</pre> + +<p> + <em>Parsing phase</em>. +</p> + +<ul> + <li> <tt>execlineb</tt> reads and parses the script it is given. +It exits 100 on a syntax error and 111 on a temporary error. +It makes an <em>argv</em>, i.e. a system command line, with the +parsed script. If the <em>argv</em> is empty, <tt>execlineb</tt> +exits 0. </li> +</ul> + +<p> + <em>Environment management phase</em>. +</p> + +<ul> + <li> <em>Pushing the current stack frame.</em> If neither the +<tt>-p</tt> nor the <tt>-P</tt> nor the <tt>-S</tt> option is set: +<tt>execlineb</tt> <a href="el_pushenv.html">pushes</a> +the current positional parameters, i.e. environment variables that +start with <tt>#</tt>, <tt>0</tt>, <tt>1</tt>, ..., <tt>9</tt>. +To get the previous values back, use +<a href="emptyenv.html"><tt>emptyenv -P</tt></a>. </li> + <li> <em>Setting the new stack frame.</em> If neither the <tt>-P</tt> +nor the <tt>-S</tt> option is set: + <ul> + <li> <tt>execlineb</tt> sets the <tt>#</tt> environment variable to +the number <em>n</em> of <em>args</em> it is given. </li> + <li> It sets the <tt>0</tt> environment variable to the name +of the script - or to the <tt>execlineb</tt> invocation name +if the <tt>-c</tt> option is used. </li> + <li> It sets the <tt>1</tt>, <tt>2</tt>, ... <tt><em>n</em></tt> +environment variables to the different <em>args</em>. </li> + </ul> </li> +</ul> + +<p> + <em>Execution phase</em>. +</p> + +<ul> + <li> <tt>execlineb</tt> executes into the <em>argv</em> it +has built from the script. +There is only one command line for the +whole script: the <tt>execlineb</tt> binary is a <em>launcher</em>, +whose sole purpose is to execute into that command line. It does +not stay in memory like a traditional <em>interpreter</em> would. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-c <em>script</em></tt> : execute <em>script</em>, do not +look for a file. </li> +</ul> + +<p> + See below for the other options. +</p> + +<h2> Syntax of scripts </h2> + +<p> + An execlineb script is a string that must not contain the null character. +<tt>execlineb</tt> parses it and divides it into <em>words</em>. + + The parser recognizes the following components: +</p> + +<ul> + <li> <em>whitespace</em> is defined as spaces, tabs, newlines and +carriage returns. Words are always separated by whitespace.</li> + <li> A <em>quoted string</em> begins with a doublequote (<tt>"</tt>) +and ends with another doublequote. Quoted doublequotes must be prefixed +by a backslash (<tt>\</tt>). Quoted strings always evaluate to exactly +one word. For instance, <tt>""</tt> evaluates to the empty word. </li> + <li> The <tt>\a</tt>, <tt>\b</tt>, <tt>\t</tt>, <tt>\n</tt>, <tt>\v</tt>, +<tt>\f</tt>, and <tt>\r</tt> sequences are recognized in quoted +strings, and are converted to the ASCII numbers 7, 8, 9, 10, 11, 12 and +13 respectively. </li> + <li> Inside a quoted string, backslashed +newlines disappear completely. </li> + <li> <tt>\0x<em>ab</em></tt> sequences are recognized in quoted strings +and evaluate to ASCII hexadecimal number <em>ab</em>. </li> + <li> <tt>\0<em>abc</em></tt> sequences are recognized in quoted strings +and evaluate to ASCII octal number <em>abc</em>. </li> + <li> <tt>\<em>abc</em></tt> sequences are recognized in quoted strings +and evaluate to ASCII decimal number <em>abc</em>. <em>a</em> must not +be zero. </li> + <li> A comment starts with a <tt>#</tt> and ends with the line. Comments +are not recognized inside quoted strings. </li> + <li> Anything else is an unquoted string, that can evaluate to +zero or more words. </li> + <li> 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. </li> +</ul> + +<p> + You can see an example of distinct <tt>execlineb</tt> components +<a href="componentsb.txt">here</a>. +</p> + +<p> + In addition to that simple lexing, +<tt>execlineb</tt> performs the following higher-level parsing: +</p> + +<ul> + <li> A word consisting of a single <em>opening brace</em> (<tt>{</tt>) +increments an internal level counter, <em>blevel</em>, and disappears from the +<em>argv</em>. Quoted open braces do not have that behaviour. </li> + <li> A word consisting of a single <em>closing brace</em> (<tt>}</tt>) +decrements <em>blevel</em>, and is replaced with the empty word. +Quoted closing braces do not have that behaviour. </li> + <li> If <tt>execlineb</tt> finds that braces are unmatched (i.e. +<em>blevel</em> goes below 0 during the parsing, or is not 0 at the end +of the script), it exits 100 with an error message. </li> + <li> <tt>execlineb</tt> automatically quotes +<a href="el_semicolon.html">blocks</a>. Which means that everytime it +finds a word, it prepends it with <em>blevel</em> spaces. </li> +</ul> + +<p> +For proper execution, the sequence of words must follow +the <a href="grammar.html">execline grammar</a>. +</p> + +<h2> Options for block syntax checking </h2> + +<p> + External execline commands that read blocks, like +<a href="foreground.html">foreground</a>, use the <tt>EXECLINE_STRICT</tt> +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. +</p> + +<p> + Normally the <tt>EXECLINE_STRICT</tt> environment variable is +inherited from the caller. You can +force it unset, set to 1, or set to 2 by giving respectively the +<tt>-q</tt>, <tt>-w</tt> or <tt>-W</tt> option to <tt>execlineb</tt>. +</p> + +<h2> Options for environment management </h2> + +<p> + Normally, execline scripts are <em>reentrant</em>: environment variables +potentially overwritten by <tt>execlineb</tt>, such as <tt>#</tt> or +<tt>0</tt>, are +<a href="el_pushenv.html">pushed</a>. 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 <strong>optimization</strong>, 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. +</p> + +<ul> + <li> The <tt>-p</tt> option will bypass the +<a href="el_pushenv.html">push</a> phase: the current frame of positional +parameters will be <em>overwritten</em>. The script will <em>not</em> be +reentrant. </li> + <li> The <tt>-P</tt> option will bypass positional parameter handling +<em>completely</em>: the environment will not be pushed, and positional +parameters will be ignored. <tt>execlineb -P -c "<em>script</em>"</tt> is +equivalent to, but more efficient than, <tt>execlineb -c +"emptyenv -P <em>script</em>"</tt>. You should use the <tt>-P</tt> option +only in standalone scripts that take no arguments, such as +<a href="http://skarnet.org/software/s6/">s6</a>'s or +<a href="http://smarden.org/runit/">runit</a>'s <em>run scripts</em>. </li> + <li> The <tt>-S <em>nmin</em></tt> option <em>will</em> substitute the +positional parameters - up to at least <em>nmin</em> - but <em>will not</em> +push nor set environment +variables. <tt>execlineb -S3 -c "<em>script</em>"</tt> is equivalent to, +but more efficient than, <tt>execlineb -c "elgetpositionals -P3 emptyenv +-P <em>script</em>"</tt>. See +<a href="el_pushenv.html#integrated">the details</a>. </li> +</ul> + +<h2> Current limitations </h2> + +<p> + <tt>execlineb</tt> builds and executes a unique +<em>argv</em> with the script: hence scripts are subject to OS-dependent +limitations such as the kernel buffer size for <em>argv</em> and <em>envp</em> + - at least 64 kB on most systems. This means that <tt>execlineb</tt> cannot +execute arbitrarily large scripts. Be careful with deeply nested scripts too: +without the <tt>-p</tt>/<tt>-P</tt>/<tt>-S</tt> option, each execlineb +invocation uses up some space in the environment. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the exit program</title> + <meta name="Description" content="execline: the exit program" /> + <meta name="Keywords" content="execline command exit" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>exit</tt> program </h1> + +<p> +<tt>exit</tt> exits with a given exit code. +</p> + +<h2> Interface </h2> + +<pre> + exit [ <em>n</em> ] +</pre> + +<p> +<tt>exit</tt> exits with the exit code <em>n</em>, or 0 if <em>n</em> is not +given (in which case it's the same as <tt>true</tt>). If <em>n</em> is not +a number, <tt>exit</tt> exits 100. +</p> + + +<h2> Notes </h2> + +<p> +<tt>exit</tt> is a standard shell builtin, with the same function. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the export program</title> + <meta name="Description" content="execline: the export program" /> + <meta name="Keywords" content="execline command export environment variable" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>export</tt> program </h1> + +<p> +<tt>export</tt> sets an environment variable to a given value, then +executes a program. +</p> + +<h2> Interface </h2> + +<pre> + export <em>var</em> <em>value</em> <em>prog...</em> +</pre> + +<p> +<tt>export</tt> sets the <em>var</em> environment variable to +the string <em>value</em>, then execs into <em>prog</em> with +its arguments. +</p> + +<ul> + <li> <em>var</em> must be given without a dollar ! </li> + <li> <em>var</em> must not contain the character <tt>=</tt> . </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the fdblock program</title> + <meta name="Description" content="execline: the fdblock program" /> + <meta name="Keywords" content="execline command fdblock file descriptor blocking" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>fdblock</tt> program </h1> + +<p> +<tt>fdblock</tt> 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. +</p> + +<h2> Interface </h2> + +<pre> + fdblock [ -n ] <em>fd</em> <em>prog...</em> +</pre> + +<p> +<tt>fdblock</tt> makes the file descriptor number <em>fd</em> blocking, +no matter what its previous state was. It then execs into <em>prog</em> +with its arguments. +</p> + +<h2> Options </h2> + +<ul> + <li> <tt>-n</tt> : non-blocking. Sets <em>fd</em> 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. </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> <tt>fdblock</tt> has no portable shell equivalent. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the fdclose program</title> + <meta name="Description" content="execline: the fdclose program" /> + <meta name="Keywords" content="execline command fdclose file descriptor close" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>fdclose</tt> program </h1> + +<p> +<tt>fdclose</tt> closes a given file descriptor, then +executes a program. +</p> + +<h2> Interface </h2> + +<pre> + fdclose <em>fd</em> <em>prog...</em> +</pre> + +<p> +<tt>fdclose</tt> closes the file descriptor number <em>fd</em>, then +execs into <em>prog</em> with its arguments. +</p> + +<h2> Notes </h2> + +<ul> + <li> <tt>fdclose <em>n</em> prog...</tt> is roughly equivalent to +<tt>sh -c 'exec prog... <em>n</em><&-'</tt></li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the fdmove program</title> + <meta name="Description" content="execline: the fdmove program" /> + <meta name="Keywords" content="execline command fdmove file descriptor dup dup2" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>fdmove</tt> program </h1> + +<p> +<tt>fdmove</tt> moves or copies a given file descriptor, then +executes a program. +</p> + +<h2> Interface </h2> + +<pre> + fdmove [ -c ] <em>fdto</em> <em>fdfrom</em> <em>prog...</em> +</pre> + +<p> +<tt>fdmove</tt> moves the file descriptor number <em>fdfrom</em>, +to number <em>fdto</em>, then execs into <em>prog</em> with its arguments. +If <em>fdto</em> is open, <tt>fdmove</tt> closes it before moving +<em>fdfrom</em> to it. +</p> + +<h2> Options </h2> + +<ul> + <li> <tt>-c</tt> : duplicate <em>fdfrom</em> to <em>fdto</em> +instead of moving it; do not close <em>fdfrom</em>. </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> <tt>fdmove -c <em>a</em> <em>b</em> prog...</tt> is roughly equivalent to +<tt>sh -c 'exec prog... <em>a</em>>&<em>b</em>'</tt></li> + <li> <tt>fdmove <em>a</em> <em>b</em> prog...</tt> is roughly equivalent to +<tt>sh -c 'exec prog... <em>a</em>>&<em>b</em> <em>b</em><&-'</tt></li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the fdreserve program</title> + <meta name="Description" content="execline: the fdreserve program" /> + <meta name="Keywords" content="execline command fdreserve file descriptor" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>fdreserve</tt> program </h1> + +<p> +<tt>fdreserve</tt> updates the environment with file descriptors that +are guaranteed safe to use, then executes a program. +</p> + +<h2> Interface </h2> + +<pre> + fdreserve <em>n</em> <em>prog...</em> +</pre> + +<ul> + <li> <tt>fdreserve</tt> tries to reserve <em>n</em> file descriptors. </li> + <li> <tt>fdreserve</tt> sets the <tt>FD0</tt>, <tt>FD1</tt>, ..., +<tt>FD<em>n-1</em></tt> environment variables: each FD<em>i</em> contains a +valid file descriptor, that can be safely opened. </li> + <li> <tt>fdreserve</tt> then execs into <em>prog</em> with its arguments. +</ul> + +<h2> Common use </h2> + +<p> +<tt>fdreserve</tt> can be used when you do not want to hardcode file +descriptors in your scripts. For instance, to create a pipe, you could +use: +</p> + +<pre> + #!/command/execlineb + fdreserve 2 + multisubstitute + { + importas fdr FD0 + importas fdw FD1 + } + piperw $fdr $fdw + <em>prog...</em> +</pre> + +<p> + Warning: <tt>fdreserve</tt> does not allocate descriptors, it merely returns +descriptors that are free at the time it is run. A program like +</p> + +<pre> + #!/command/execlineb + fdreserve 3 + multisubstitute + { + importas fdr FD0 + importas fdw FD1 + } + piperw $fdr $fdw + fdreserve 1 + multisubstitute + { + importas oldfd FD2 + importas newfd FD0 + } + <em>prog...</em> +</pre> + +<p> +may fail, because <em>oldfd</em> and <em>newfd</em> may be the same. +To avoid that, you should make sure that all descriptors returned by +<tt>fdreserve</tt> are actually allocated before calling <tt>fdreserve</tt> +again. +(Thanks to <a href="http://code.dogmap.org/">Paul Jarc</a> for having +spotted that case.) +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the forbacktickx command</title> + <meta name="Description" content="execline: the forbacktickx command" /> + <meta name="Keywords" content="execline command forbacktickx" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>forbacktickx</tt> program </h1> + +<p> +<tt>forbacktickx</tt> runs a program and uses its output as loop elements to +run another program. +</p> + +<h2> Interface </h2> + +<p> + In an <a href="execlineb.html">execlineb</a> script: +</p> + +<pre> + forbacktickx [ -p | -x breakcode ] [ -n ] [ -C | -c ] [ -0 | -d <em>delim</em> ] <em>variable</em> { <em>gen...</em> } <em>loop...</em> +</pre> + +<ul> + <li> <tt>forbacktickx</tt> reads a +<a href="el_semicolon.html">block</a>, +<em>gen...</em>, and unquotes it. </li> + <li> It runs <em>gen...</em> as a child process. <em>gen</em>'s +output must not contain a null character. </li> + <li> It reads <em>gen</em>'s output as it needs, +<a href="el_transform.html#split">splitting</a> it automatically. </li> + <li> For every argument <em>x</em> in the split output, +<tt>forbacktickx</tt> runs <em>loop...</em> as a child process, with +<em>variable</em>=<em>x</em> added to its environment. </li> + <li><tt>forbacktickx</tt> then exits 0. +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-p</tt> : parallel mode. Do not wait for a <em>loop...</em> +instance to finish before spawning the next one. <em>forbacktickx</em> will +still wait for all instances of <em>loop</em> to terminate before +exiting, though. </li> + <li> <tt>-0</tt> : accept null characters from <em>gen</em>'s output, +using them as delimiters. If this option and a <tt>-d</tt> option are +used simultaneously, the rightmost one wins. </li> + <li> <tt>-x</tt> <em>breakcodes</em> : <em>breakcodes</em> must +be a comma-separated list of exit codes. If at some point <em>loop...</em> +exits with a code listed in <em>breakcodes</em>, forbacktickx will not keep +looping, but will exit immediately with the same exit code. This doesn't apply +if the <tt>-p</tt> option has been given. </li> + <li> Other options are used to <a href="el_transform.html">control +the substitution mechanism</a> for every <em>x</em>. Of course, you can't +split <em>x</em>. </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> You can start <em>loop...</em> with "import <em>variable</em> unexport <em>variable</em>" +to perform variable substitution. +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the foreground command</title> + <meta name="Description" content="execline: the foreground command" /> + <meta name="Keywords" content="execline command foreground" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>foreground</tt> program </h1> + +<p> +<tt>foreground</tt> executes a sequence of commands. +</p> + +<h2> Interface </h2> + +<p> + In an <a href="execlineb.html">execlineb</a> script: +</p> + +<pre> + foreground { <em>prog1...</em> } <em>prog2...</em> +</pre> + +<ul> + <li> <tt>foreground</tt> reads <em>prog1</em> in a +<a href="el_semicolon.html">block</a>. It forks and +executes it, then waits for it to complete. </li> + <li> <tt>foreground</tt> sets the <tt>?</tt> environment +variable to the exit code of <em>prog1</em>. If <em>prog1...</em> +did not exit normally, the <tt>?</tt> value is 111. </li> + <li> <tt>foreground</tt> then execs into <em>prog2...</em>. </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> <tt>foreground</tt> 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. </li> + <li> <tt>foreground <em>prog1...</em> "" <em>prog2...</em></tt> is +equivalent to <tt>sh -c '<em>prog1...</em> ; exec <em>prog2...</em>'</tt>. + </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the forx command</title> + <meta name="Description" content="execline: the forx command" /> + <meta name="Keywords" content="execline command forx" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>forx</tt> program </h1> + +<p> +<tt>forx</tt> runs a loop. +</p> + +<h2> Interface </h2> + +<p> + In an <a href="execlineb.html">execlineb</a> script: +</p> + +<pre> + forx [ -p | -x <em>breakcodes</em> ] <em>variable</em> { <em>args...</em> } <em>loop...</em> +</pre> + +<ul> + <li> <tt>forx</tt> reads a +<a href="el_semicolon.html">block</a> and unquotes it. +That block contains a list of <em>args</em>. </li> + <li> For each argument <em>x</em> in <em>args...</em>, +<tt>forx</tt> runs <em>loop</em> as a child process, with +<em>variable</em>=<em>x</em> added to its environment. </li> + <li> <tt>forx</tt> then exits 0. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-p</tt> : run in parallel. Do not wait for an instance of +<em>loop...</em> to exit before spawning the next one. <tt>forx</tt> +will still wait for all instances of <em>loop</em> to terminate before +exiting, though. </li> + <li> <tt>-x</tt> <em>breakcodes</em> : <em>breakcodes</em> must +be a comma-separated list of exit codes. If the <tt>-p</tt> flag +hasn't been given and <em>loop</em> exits with one of the codes in <em>breakcodes</em>, +forx will not run the following instances of the loop, but exit immediately with the +same exit code. </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> You can start <em>loop</em> with "import <em>variable</em> unexport <em>variable</em>" +if you want variable substitution. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the getpid program</title> + <meta name="Description" content="execline: the getpid program" /> + <meta name="Keywords" content="execline command getpid process id variable" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>getpid</tt> program </h1> + +<p> +<tt>getpid</tt> stores its process ID in a given environment variable, +then executes a program. +</p> + +<h2> Interface </h2> + +<pre> + getpid <em>var</em> <em>prog...</em> +</pre> + +<p> +<tt>getpid</tt> stores its PID in the <em>var</em> variable, then +execs into <em>prog</em> with its arguments. +</p> + +<h2> Notes </h2> + +<ul> + <li> <em>var</em> must be given without a dollar ! </li> + <li> <em>var</em> must not contain <tt>=</tt>. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: language design and grammar</title> + <meta name="Description" content="execline: language design and grammar" /> + <meta name="Keywords" content="execline language design grammar script shell" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>execline</tt> language design and grammar </h1> + +<a name="principles" /> +<h2> <tt>execline</tt> principles </h2> + +<p> + Here are some basic Unix facts: +</p> + +<ul> + <li> Unix programs are started with the <tt>execve()</tt> +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 <em>argv</em>, which specifies the program name and its +arguments, and the environment <em>envp</em>. </li> + <li> The <em>argv</em> structure makes it easy to read some +arguments at the beginning of <em>argv</em>, perform some action, +then <tt>execve()</tt> into the rest of <em>argv</em>. For +instance, the <tt>nice</tt> command works that way: +<pre> nice -10 echo blah </pre> will read <tt>nice</tt> and <tt>-10</tt> +from the argv, change the process' <em>nice</em> value, then exec into +the command <tt>echo blah</tt>. This is called +<a href"http://en.wikipedia.org/wiki/Chain_loading">chain loading</a> +by some people, and <a href="http://www.faqs.org/docs/artu/ch07s02.html"> +Bernstein chaining</a> by others. </li> + <li> The purpose of the environment is to preserve some state across +<tt>execve()</tt> calls. This state is usually small: most programs +keep their information in the filesystem. </li> + <li> A <em>script</em> 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 <tt>/bin/sh</tt>: scripts are written +in the <em>shell</em> language. </li> + <li> 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. </li> + <li> Standard shells have lots of built-in features and commands, so +they are big. Spawning (i.e. <tt>fork()</tt>ing then <tt>exec()</tt>ing) +a shell script takes time, because the shell program itself must be +initialized. For simple programs like <tt>nice -10 echo blah</tt>, +a shell is overpowered - we only need a way to make an <em>argv</em> +from the "<tt>nice -10 echo blah</tt>" string, and <tt>execve()</tt> +into that <em>argv</em>. </li> + <li> Unix systems have a size limit for <em>argv</em>+<em>envp</em>, +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. </li> +</ul> + +<p> + 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 <em>argv</em>, and just execute into that <em>argv</em>, +relying on external commands (which will be called from within the +script) to control the execution flow ?" +</p> + +<p> <tt>execline</tt> was born. </p> + +<ul> + <li> <tt>execline</tt> is the first script language to rely +<em>entirely</em> on chain loading. An execline script is a +single <em>argv</em>, made of a chain of programs designed to +perform their action then <tt>exec()</tt> into the next one. </li> + <li> The <a href="execlineb.html">execlineb</a> command is a +<em>launcher</em>: it reads and parses a text file, converting it +to an <em>argv</em>, then executes into that <em>argv</em>. It +does nothing more. </li> + <li> Straightforward scripts like <tt>nice -10 echo blah</tt> +will be run just as they are, without the shell overhead. +Here is what the script could look like: +<pre> +#!/command/execlineb -P +nice -10 +echo blah +</pre> + </li> + <li> More complex scripts will include calls to other <tt>execline</tt> +commands, which are meant to provide some control over the process state +and execution flow from inside an <em>argv</em>. </li> +</ul> + +<a name="grammar" /> +<h2> Grammar of an execline script </h2> + +<p> +An execline script can be parsed as follows: +</p> + +<pre> + <instruction> = <> | external options <arglist> <instruction> | builtin options <arglist> <blocklist> <instruction> + <arglist> = <> | arg <arglist> + <blocklist> = <> | <block> <blocklist> + <block> = { <arglist> } | { <instrlist> } + <instrlist> = <> | <instruction> <instrlist> +</pre> + +<p> +(This grammar is ambivalent, but much simpler to understand than the +non-ambivalent ones.) +</p> + +<ul> + <li> An execline script is valid if it reduces to an +<em>instruction</em>. </li> + <li> The empty <em>instruction</em> is the same as the <tt>true</tt> +command: when an execline component must exec into the empty +instruction, it exits 0. </li> + <li> Basically, every non-empty <em>instruction</em>, be it +"<em>builtin</em>" - an execline command - or "<em>external</em>" +- a program such as <tt>echo</tt> or <tt>cp</tt> - takes a number of +arguments, the <em>arglist</em>, then executes into a (possibly empty) +<em>instruction</em>. </li> + <li> Some <em>builtin</em>s are special because they also take a +non-empty <em>blocklist</em> after their <em>arglist</em>. For instance, +the <a href="foreground.html">foreground</a> command takes an empty +<em>arglist</em> and one <em>block</em>: <pre> + #!/command/execlineb -P + foreground { sleep 1 } echo blah +</pre> is a valid <a href="execlineb.html">execlineb</a> script. +The <a href="foreground.html">foreground</a> command uses the +<tt>sleep 1</tt> <em>block</em> then execs into the +remaining <tt>echo blah</tt> <em>instruction</em>. </li> +</ul> + +<a name="features"></a> +<h2> execline features </h2> + +<p> + <tt>execline</tt> commands can perform some transformations on +their <em>argv</em>, to emulate some aspects of a shell. Here are +descriptions of these features: +</p> + +<ul> + <li> <a href="el_semicolon.html">Block management</a> </li> + <li> <a href="el_substitute.html">Variable substitution</a> </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the heredoc program</title> + <meta name="Description" content="execline: the heredoc program" /> + <meta name="Keywords" content="execline command heredoc here document" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>heredoc</tt> program </h1> + +<p> +<tt>heredoc</tt> runs a command with a certain string fed to a +file descriptor. +</p> + +<h2> Interface </h2> + +<pre> + heredoc [ -d ] <em>fd</em> <em>string</em> <em>prog...</em> +</pre> + +<ul> + <li> <tt>heredoc</tt> execs into <em>prog...</em> with +<em>string</em> available on the <em>fd</em> file +descriptor. </li> + <li> <em>string</em> must not contain a null character. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-d</tt> : run the process feeding <em>string</em> to <em>fd</em> +as a grandchild of <tt>heredoc</tt>. This is meant to prevent a zombie +from hanging around if <em>prog...</em> has read <em>string</em> and fails +to wait for its children.</li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> <tt>heredoc</tt> is meant to be used in place of the shell +<tt><<</tt> construct, which includes <em>here-documents</em> +into scripts. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the homeof program</title> + <meta name="Description" content="execline: the homeof program" /> + <meta name="Keywords" content="execline command homeof" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>homeof</tt> program </h1> + +<p> +<tt>homeof</tt> prints the home directory of a user. +</p> + +<h2> Interface </h2> + +<pre> + homeof <em>user</em> +</pre> + +<p> +<tt>homeof</tt> finds the name of <em>user</em>'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. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the if command</title> + <meta name="Description" content="execline: the if command" /> + <meta name="Keywords" content="execline command if" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>if</tt> program </h1> + +<p> +<tt>if</tt> performs conditional execution. +</p> + +<h2> Interface </h2> + +<p> + In an <a href="execlineb.html">execlineb</a> script: +</p> + +<pre> + if [ -X ] [ -n ] [ -t | -x <em>exitcode</em> ] { <em>prog1...</em> } <em>prog2...</em> +</pre> + +<ul> + <li> <tt>if</tt> reads <em>prog1...</em> in a +<a href="el_semicolon.html">block</a>. It forks and executes it, +then waits for it to complete. </li> + <li> If <em>prog1</em> crashes, <tt>if</tt> exits 1 with a special +error message. </li> + <li> If <em>prog1</em> exits a non-zero status, +<tt>if</tt> exits 1.</li> + <li> Else <tt>if</tt> execs into <em>prog2</em>. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-X</tt> : treat a crash of <em>prog1</em> as a non-zero ("false") exit. + <li> <tt>-n</tt> : negate the test (exit on true, exec into <em>prog2</em> on false) </li> + <li> <tt>-x</tt> <em>exitcode</em> : exit <em>exitcode</em> instead of 1 if the test fails. </li> + <li> <tt>-t</tt> : exit 0 instead of 1 if the test fails. +This is equivalent to <tt>-x 0</tt>. </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> <tt>if</tt> will exit if <em>prog1...</em> exits false. To use it in +an execline script that must run <em>prog3...</em> no matter the result of +the test, use a <tt>foreground</tt> wrapper: +<pre> foreground { if { <em>prog1...</em> } <em>prog2...</em> } <em>prog3...</em> </pre> +(in <a href="execlineb.html">execlineb</a> syntax) </li> + <li> <tt>if <em>prog1...</em> "" <em>prog2...</em></tt> is +equivalent to <tt>sh -c '<em>prog1...</em> && exec <em>prog2...</em>'</tt>. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the ifelse command</title> + <meta name="Description" content="execline: the ifelse command" /> + <meta name="Keywords" content="execline command ifelse" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://www.skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>ifelse</tt> program </h1> + +<p> + <tt>ifelse</tt> performs conditional execution, with two branches. +</p> + +<h2> Interface </h2> + +<p> + In an <a href="execlineb.html">execlineb</a> script: +</p> +<pre> + ifelse [ -X ] [ -n ] { <em>prog1...</em> } { <em>prog2...</em> } <em>prog3...</em> +</pre> + +<ul> + <li> <tt>ifelse</tt> reads <em>prog1...</em> in a +<a href="el_semicolon.html">block</a>. It forks and executes it, +then waits for it to complete. </li> + <li> If <em>prog1</em> crashes, <tt>ifelse</tt> exits 1 with an error message. </li> + <li> If <em>prog1</em> exits with a return code equal to 0, +<tt>ifelse</tt> execs into <em>prog2</em>. </li> + <li> Else <tt>ifelse</tt> execs into <em>prog3</em>. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-n</tt> : negate the test. </li> + <li> <tt>-X</tt> : do not die if <em>prog1</em> crashes; treat a crash +as a non-zero ("false") exit. </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> <tt>ifelse <em>prog1...</em> "" <em>prog2...</em> "" <em>prog3...</em></tt> is +roughly equivalent to <tt>sh -c '<em>prog1...</em> && exec <em>prog2...</em> || exec <em>prog3...</em>'</tt>. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the ifte command</title> + <meta name="Description" content="execline: the ifte command" /> + <meta name="Keywords" content="execline command ifte" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>ifte</tt> program </h1> + +<p> +<tt>ifte</tt> performs a conditional alternative. +</p> + +<h2> Interface </h2> + +<p> + In an <a href="execlineb.html">execlineb</a> script: +</p> + +<pre> + ifte [ -X ] [ -n ] { <em>progthen...</em> } { <em>progelse...</em> } <em>progif...</em> +</pre> + +<ul> + <li> <tt>ifte</tt> reads <em>progthen...</em> and <em>progelse...</em> in two +consecutive <a href="el_semicolon.html">blocks</a>. </li> + <li> <tt>ifte</tt> runs <em>progif...</em> as a child process +and waits for it to complete. </li> + <li> If <em>progif...</em> crashes (i.e. is killed by a signal), <tt>ifte</tt> +exits 1 with an error message. </li> + <li> If <em>progif...</em> exits zero, <tt>ifte</tt> execs into +<em>progthen...</em>, else it execs into <em>progelse...</em>. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-X</tt> : do not exit if <em>progif</em> crashes; instead, +proceed as if the test had returned false. </li> + <li> <tt>-n</tt> : negate the test. <em>progthen...</em> will be run +iff <em>progif...</em> exits nonzero. </li> +</ul> + +<h2> Notes </h2> + +<p> + <tt>ifte</tt> is a simpler version of <a href="ifthenelse.html">ifthenelse</a>. +It performs <em>only</em> conditional execution, not instruction sequence. +</p> + +<p> +"<tt>ifthenelse { progif } { progthen } { progelse } remainder</tt>" is the +equivalent of "<tt>foreground { ifte { progthen } { progelse } progif } remainder</tt>". +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the ifthenelse command</title> + <meta name="Description" content="execline: the ifthenelse command" /> + <meta name="Keywords" content="execline command ifthenelse" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>ifthenelse</tt> program </h1> + +<p> +<tt>ifthenelse</tt> performs a conditional alternative. +</p> + +<h2> Interface </h2> + +<p> + In an <a href="execlineb.html">execlineb</a> script: +</p> + +<pre> + ifthenelse [ -X ] [ -s ] { <em>progif...</em> } { <em>progthen...</em> } { <em>progelse...</em> } <em>prog...</em> +</pre> + +<ul> + <li> <tt>ifthenelse</tt> reads +<em>progif...</em>, <em>progthen...</em> and <em>progelse...</em> in 3 +consecutive <a href="el_semicolon.html">blocks</a>. </li> + <li> <tt>ifthenelse</tt> runs <em>progif...</em> as a child process +and waits for it to complete. </li> + <li> If <em>progif...</em> crashes (i.e. is killed by a signal), <tt>ifthenelse</tt> +exits 1 with an error message. </li> + <li> If <em>progif...</em> exits zero, <tt>ifthenelse</tt> runs +<em>progthen...</em> as a child process, else it runs <em>progelse...</em>. </li> + <li> <tt>ifthenelse</tt> waits for its child to complete and puts the exit +status in the <tt>?</tt> environment variable. It then +execs into <em>prog...</em>. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-X</tt> : if <em>progif</em> crashes, do not exit; proceed +as if it had returned false. </li> + <li> <tt>-s</tt> : magic scoping hack. This option does powerful but +ugly things, and is left undocumented on purpose. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the import program</title> + <meta name="Description" content="execline: the import program" /> + <meta name="Keywords" content="execline command import environment variable" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>import</tt> program </h1> + +<p> +<tt>import</tt> replaces an environment variable name with its value, +then executes another program. +</p> + +<h2> Interface </h2> + +<pre> + import [ -i | -D <em>default</em> ] [ -s ] [ -C | -c ] [ -n ] [ -d <em>delim</em> ] <em>envvar</em> <em>prog...</em> +</pre> + +<ul> + <li> <tt>import</tt> behaves exactly as +<tt><a href="importas.html">importas</a> <em>envvar</em> <em>envvar</em></t>. +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the importas program</title> + <meta name="Description" content="execline: the importas program" /> + <meta name="Keywords" content="execline command importas import environment variable" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>importas</tt> program </h1> + +<p> +<tt>importas</tt> replaces a literal with the value of an +environment variable, then executes another program. +</p> + +<h2> Interface </h2> + +<pre> + importas [ -i | -D default ] [ -s ] [ -C | -c ] [ -n ] [ -d <em>delim</em> ] <em>variable</em> <em>envvar</em> <em>prog...</em> +</pre> + +<ul> + <li> <tt>importas</tt> fetches the value of <em>envvar</em> in the +environment. If neither the <em>-D</em> nor the <em>-i</em> option is given, +and <em>envvar</em> is undefined, the <strong>null word</strong> is returned. </li> + <li> <tt>importas</tt> then performs +<a href="el_substitute.html">variable substitution</a> on <em>prog...</em>, +with <em>variable</em> as key and that string as value. + <li><tt>importas</tt> then execs into the modified <em>prog...</em>. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-D</tt> <em>default</em> : If <em>envvar</em> is +undefined, and this option is not given, substitute zero word for +<em>variable</em> instead of the empty word; and if it is given, +substitute <em>default</em> instead. To substitute the empty word, +use <tt>-D ""</tt>. </li> + <li> <tt>-i</tt> : Insist. If <em>envvar</em> is undefined, +<tt>importas</tt> will not do anything; instead, it will exit 100 with an +error message. This has precedence over any <tt>-D</tt> option. </li> + <li> Other options are used to <a href="el_transform.html">control +the substitution mechanism</a>. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: a small scripting language</title> + <meta name="Description" content="execline: a small scripting language" /> + <meta name="Keywords" content="execline script scripting language shell embedded chain loading bernstein chaining unix" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> execline </h1> + +<h2> What is it ? </h2> + +<p> + execline is a (non-interactive) scripting language, like <tt>sh</tt> ; +but its syntax is quite different from a traditional shell syntax. +The <tt>execlineb</tt> program is meant to be used as an interpreter for a +text file; the other commands are essentially useful inside an +<tt>execlineb</tt> script. +</p> + +<p> + execline is as powerful as a shell: it features +<a href="loopwhilex.html">conditional loops</a>, +<a href="elgetopt.html">getopt-style option handling</a>, +<a href="elglob.html">filename globbing</a>, and more. + Meanwhile, its syntax is far more logic and predictable than the +shell's syntax, and has no security issues. +</p> + +<ul> +<li> <a href="grammar.html">The execline design and grammar</a></li> +<li> <a href="dieshdiedie.html">Why not just use <tt>/bin/sh</tt> ?</a></li> +</ul> + +<hr /> + +<h2> Installation </h2> + +<h3> Requirements </h3> + +<ul> + <li> A POSIX-compliant system with a standard C development environment </li> + <li> GNU make, version 3.81 or later </li> + <li> <a href="http://skarnet.org/software/skalibs/">skalibs</a> version +2.0.0.0 or later </li> +</ul> + +<h3> Licensing </h3> + +<p> + execline is free software. It is available under the +<a href="http://opensource.org/licenses/ISC">ISC license</a>. +</p> + +<h3> Download </h3> + +<ul> + <li> The current execline version is <a href="execline-2.0.0.0.tar.gz">2.0.0.0</a>. </li> +</ul> + +<h3> Compilation </h3> + +<ul> + <li> See the enclosed INSTALL file for installation details. </li> +</ul> + +<h3> Upgrade notes </h3> + +<ul> + <li> <a href="upgrade.html">This page</a> lists the differences to be aware of between +the previous versions of execline and the current one. </li> +</ul> + +<hr /> + +<h2> Special note </h2> + +<p> + 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 <tt>#!/command/execlineb</tt> as their shebang line, and assume that +the execline binaries are available in <tt>/command</tt>. Adapt them according +to your installation: the shebang lines for your system might be something like +<tt>#!/bin/execlineb</tt>, or <tt>#!/usr/bin/execlineb</tt>, or +<tt>#!/usr/local/bin/execlineb</tt>, or something else entirely. +</p> + +<hr /> + +<h2> Reference </h2> +<h3> Commands </h3> + +<p> + All these commands exit 111 if they encounter a temporary error, and +100 if they encounter a permanent error - such as a misuse. +</p> +<p> + (Script parser / launcher) +</p> +<ul> +<li><a href="execlineb.html">The <tt>execlineb</tt> program</a></li> +</ul> +<p> + (Process state control) +</p> +<ul> +<li><a href="cd.html">The <tt>cd</tt> program</a></li> +<li><a href="umask.html">The <tt>umask</tt> program</a></li> +<li><a href="emptyenv.html">The <tt>emptyenv</tt> program</a></li> +<li><a href="export.html">The <tt>export</tt> program</a></li> +<li><a href="unexport.html">The <tt>unexport</tt> program</a></li> +<li><a href="fdclose.html">The <tt>fdclose</tt> program</a></li> +<li><a href="fdblock.html">The <tt>fdblock</tt> program</a></li> +<li><a href="fdmove.html">The <tt>fdmove</tt> program</a></li> +<li><a href="fdreserve.html">The <tt>fdreserve</tt> program</a></li> +<li><a href="redirfd.html">The <tt>redirfd</tt> program</a></li> +<li><a href="piperw.html">The <tt>piperw</tt> program</a></li> +<li><a href="heredoc.html">The <tt>heredoc</tt> program</a></li> +<li><a href="pipeline.html">The <tt>pipeline</tt> program</a></li> +<li><a href="wait.html">The <tt>wait</tt> program</a></li> +<li><a href="getpid.html">The <tt>getpid</tt> program</a></li> +<li><a href="exec.html">The <tt>exec</tt> program</a></li> +<li><a href="tryexec.html">The <tt>tryexec</tt> program</a></li> +<li><a href="exit.html">The <tt>exit</tt> program</a></li> +</ul> +<p> + (<a href="el_semicolon.html">Basic block management</a>) +</p> +<ul> +<li><a href="foreground.html">The <tt>foreground</tt> program</a></li> +<li><a href="background.html">The <tt>background</tt> program</a></li> +<li><a href="if.html">The <tt>if</tt> program</a></li> +<li><a href="ifelse.html">The <tt>ifelse</tt> program</a></li> +<li><a href="ifte.html">The <tt>ifte</tt> program</a></li> +<li><a href="ifthenelse.html">The <tt>ifthenelse</tt> program</a></li> +<li><a href="backtick.html">The <tt>backtick</tt> program</a></li> +<li><a href="runblock.html">The <tt>runblock</tt> program</a></li> +</ul> +<p> + (<a href="el_substitute.html">Variable management</a>) +</p> +<ul> +<li><a href="define.html">The <tt>define</tt> program</a></li> +<li><a href="importas.html">The <tt>importas</tt> program</a></li> +<li><a href="import.html">The <tt>import</tt> program</a></li> +<li><a href="elglob.html">The <tt>elglob</tt> program</a></li> +<li><a href="elgetpositionals.html">The <tt>elgetpositionals</tt> program</a></li> +<li><a href="multidefine.html">The <tt>multidefine</tt> program</a></li> +<li><a href="multisubstitute.html">The <tt>multisubstitute</tt> program</a></li> +</ul> +<p> + (Loops) +</p> +<ul> +<li><a href="forx.html">The <tt>forx</tt> program</a></li> +<li><a href="forbacktickx.html">The <tt>forbacktickx</tt> program</a></li> +<li><a href="loopwhilex.html">The <tt>loopwhilex</tt> program</a></li> +</ul> +<p> + (Positional parameters and options management) +</p> +<ul> +<li><a href="elgetopt.html">The <tt>elgetopt</tt> program</a></li> +<li><a href="shift.html">The <tt>shift</tt> program</a></li> +<li><a href="dollarat.html">The <tt>dollarat</tt> program</a></li> +</ul> +<p> + (Miscellaneous) +</p> +<ul> +<li><a href="homeof.html">The <tt>homeof</tt> program</a></li> +</ul> + +<h3> Provided scripts: example <tt>.profile</tt> replacement </h3> + +<ul> +<li><a href="execline-shell.html">The <tt>execline-shell</tt> script</a></li> +<li><a href="execline-startup.html">The <tt>execline-startup</tt> script</a></li> +</ul> + +<h3> Fun stuff </h3> + +<ul> +<li>An execline <a href="quine-jriou.txt">quine</a>. This was quinely provided by +<a href="http://jriou.org/">Joël Riou</a>. The only +external command used is <tt>echo</tt>. </li> +<li> Another <a href="quine-prj.txt">quine</a>, provided by +<a href="http://code.dogmap.org/">Paul Jarc</a>. It is much shorter, but +uses the external commands <tt>echo</tt> and <tt>env</tt>. Later, Paul rewrote +it <a href="quine-prj-2.txt">using only <tt>echo</tt></a>, then +<a href="quine-prj-3.txt">using only <tt>echo</tt> and the environment</a>. </li> +<li> Another <a href="quine-dam.txt">quine</a>, provided by +<a href="http://www.madore.org/~david/">David Madore</a>. It uses the +external command <tt>printf</tt>. It is longer, but quite stylish. </li> +</ul> + +<h2> Related resources </h2> + +<ul> + <li> <tt>execline</tt> is discussed on the +<a href="http://skarnet.org/lists.html#skaware">skaware</a> mailing-list. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the loopwhilex command</title> + <meta name="Description" content="execline: the loopwhilex command" /> + <meta name="Keywords" content="execline command loopwhilex" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>loopwhilex</tt> program </h1> + +<p> +<tt>loopwhilex</tt> performs a conditional loop. +</p> + +<h2> Interface </h2> + +<pre> + loopwhilex [ -n ] [ -x <em>exitcodes</em> ] <em>prog...</em> +</pre> + +<ul> + <li> <tt>loopwhilex</tt> runs <em>prog...</em> as a child process and +waits for it to complete. </li> + <li> As long as <em>prog</em> exits zero, <tt>loopwhile</tt> runs it again. </li> + <li> <tt>loopwhilex</tt> then exits 0. If <em>prog</em> was killed by a signal, +<tt>loopwhilex</tt> exits that signal's number instead. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-x</tt> <em>exitcodes</em> : <em>exitcodes</em> must be a comma-separated +list of valid exit codes. If this option is given, <tt>loopwhilex</tt> will exit if <em>prog...</em>'s +exit code is listed in <em>breakcodes</em>. </li> + <li> <tt>-n</tt> : negate the test: run <em>prog...</em> as long as it exits non-zero +(or exits a code that is <em>not</em> listed in <em>breakcodes</em>). </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> <tt>loopwhilex <em>prog</em>...</tt> is equivalent to <tt>loopwhilex -n -x 0 <em>prog...</em></tt>. </li> + <li> Be careful: execline <strong>maintains no state</strong>, in particular it +uses <strong>no real variables</strong>, and environment will +be of no use here since every instance of <em>prog...</em> runs as a separate +child process. To avoid being stuck in an infinite loop, <em>prog...</em> +should modify some external state - for instance, the filesystem. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the multidefine command</title> + <meta name="Description" content="execline: the multidefine command" /> + <meta name="Keywords" content="execline command multidefine" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>multidefine</tt> program </h1> + +<p> +<tt>multidefine</tt> splits a value and defines several variables at once, +then executes another program. +</p> + +<h2> Interface </h2> + +<p> + In an <a href="execlineb.html">execlineb</a> script: +</p> + +<pre> + multidefine [ -0 ] [ -r ] [ -C | -c ] [ -n ] [ -d <em>delim</em> ] <em>value</em> { <em>variables...</em> } <em>prog...</em> +</pre> + +<ul> + <li> <tt>multidefine</tt> reads a <a href="el_semicolon.html">block</a> +containing a list of variables. </li> + <li> <tt>multidefine</tt> <a href="el_transform.html">splits</a> +<em>value</em>, and performs other operations depending on the given +options. </li> + <li> <tt>multidefine</tt> performs +<a href="el_substitute.html">parallel substitution</a> on +<em>prog...</em>, using all of the <em>variables</em> in the block as keys. +The first word in the split <em>value</em> is assigned to the first +<em>variable</em>, the second word is assigned to the second <em>variable</em>, +and so on. Every <em>variable</em> is substituted with exactly one word. </li> + <li> If a <em>variable</em> is the empty word, then the word in the split +<em>value</em> 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. </li> + <li> <tt>multidefine</tt> then execs into the modified <em>prog...</em>. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-0</tt> : if there are more <em>variables</em> in the block than +there are words in the split <em>value</em>, the excess variables +will be replaced with zero word. Without this option, the excess variables are +replaced with the empty word. </li> + <li> <tt>-r</tt> : behave similarly to the "read" shell command. +If there are more words in the split <em>value</em> than there are +<em>variables</em> 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. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the multisubstitute command</title> + <meta name="Description" content="execline: the multisubstitute command" /> + <meta name="Keywords" content="execline command multisubstitute" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>multisubstitute</tt> program </h1> + +<p> +<tt>multisubstitute</tt> performs several substitutions at once in +its <em>argv</em>, then executes another program. +</p> + +<h2> Interface </h2> + +<p> + In an <a href="execlineb.html">execlineb</a> script: +</p> + +<pre> + multisubstitute + { + [ <a href="define.html">define</a> [ -n ] [ -s ] [ -C | -c ] [ -d <em>delim</em> ] <em>variable</em> <em>value</em> ] + [ <a href="importas.html">importas</a> [ -i | -D <em>default</em> ] [ -n ] [ -s ] [ -C | -c ] [ -d <em>delim</em> ] <em>variable</em> <em>envvar</em> ] + [ <a href="import.html">import</a> [ -i | -D <em>default</em> ] [ -n ] [ -s ] [ -C | -c ] [ -d <em>delim</em> ] <em>envvar</em> ] + [ <a href="elglob.html">elglob</a> [ -v ] [ -w ] [ -s ] [ -m ] [ -e ] [ -0 ] <em>variable</em> <em>pattern</em> ] + [ <a href="elgetpositionals.html">elgetpositionals</a> [ -P <em>sharp</em> ] ] + [ <a href="multidefine.html">multidefine</a> <em>value</em> { <em>variable...</em> } ] + <em>...</em> + } + <em>prog...</em> +</pre> + +<ul> + <li> <tt>multisubstitute</tt> reads a <a href="el_semicolon.html">block</a> +containing a series of substitution commands. It performs all +those <a href="el_substitute.html">substitutions</a> on +<em>prog...</em> in parallel. Check the relevant documentation page +to learn about the syntax of each substitution command. </li> + <li> <tt>multisubstitute</tt> then execs into the modified <em>prog...</em>. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> If a <tt>backtick</tt> directive was given with the <tt>-i</tt> option, +and <em>command</em> crashes or exits nonzero, <tt>multisubstitute</tt> will +also exit with the same exit code. </li> + <li> If an <tt>import</tt> or <tt>importas</tt> directive was given with the +<tt>-i</tt> option, and the looked up variable is undefined, +<tt>multisubstitute</tt> will exit 100. </li> +</ul> + +<h2> Rationale </h2> + +<h3> Security </h3> + +<p> + <tt>multisubstitute</tt> can be used to avoid unwanted +<em>serial substitutions</em>. Consider the following script: +</p> + +<pre> + #!/command/execlineb + export A wrong + define B ${A} + import A + echo ${B} +</pre> + +<p> + Running it will print <tt>wrong</tt>, because <tt>A</tt> is substituted +<em>after</em> B. On the contrary, the following script: +</p> + +<pre> + #!/command/execlineb + export A wrong + multisubstitute + { + define B ${A} + import A + } + echo ${B} +</pre> + +<p> + will print <tt>${A}</tt>, 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. +</p> + +<h3> Efficiency </h3> + +<p> +<a href="el_substitute.html">Substitution</a> is a costly mechanism: +the whole <em>argv</em> 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. +</p> + +<h2> Credits </h2> + +<p> +<a href="http://code.dogmap.org/">Paul Jarc</a> first originated the +idea of the <tt>multisubstitute</tt> command and a possible syntax. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the pipeline command</title> + <meta name="Description" content="execline: the pipeline command" /> + <meta name="Keywords" content="execline command pipeline" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>pipeline</tt> program </h1> + +<p> +<tt>pipeline</tt> runs two commands with a pipe between them. +</p> + +<h2> Interface </h2> + +<p> + In an <a href="execlineb.html">execlineb</a> script: +</p> + +<pre> + pipeline [ -d ] [ -r | -w ] { <em>prog1...</em> } <em>prog2...</em> +</pre> + +<ul> + <li> <tt>pipeline</tt> reads <em>prog1...</em> in a +<a href="el_semicolon.html">block</a> and unquotes it. </li> + <li> It runs <em>prog1...</em> as a child process and execs into +<em>prog2...</em>, with a pipe between <em>prog1</em>'s stdout and +<em>prog2</em>'s stdin. </li> + <li> <em>prog1</em>'s pid is available in <em>prog2</em> as the ! +environment variable. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-d</tt> : run <em>prog1...</em> +as a grandchild of <tt>pipeline</tt>. This is meant to prevent a zombie +from hanging around if <em>prog2...</em> fails to wait for its children.</li> + <li> <tt>-r</tt> : make <em>prog1...</em> the writer and +<em>prog2...</em> the reader. This is the default. </li> + <li> <tt>-w</tt> : make <em>prog1...</em> the reader and +<em>prog2...</em> the writer. </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> You can easily create a chain of pipes: <tt>pipeline a "" pipeline b "" c</tt> +is roughly equivalent to +<tt>sh -c 'exec a | b | c'</tt>, except that shells usually run <tt>c</tt> +as a child process like <tt>a</tt> and <tt>b</tt>, and <tt>exec</tt> has no +effect. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the piperw command</title> + <meta name="Description" content="execline: the piperw command" /> + <meta name="Keywords" content="execline command piperw" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>piperw</tt> program </h1> + +<p> +<tt>piperw</tt> creates a pipe (an anonymous one), then +executes a program. +</p> + +<h2> Interface </h2> + +<pre> + piperw <em>fdr</em> <em>fdw</em> <em>prog...</em> +</pre> + +<p> +<tt>piperw</tt> creates a pipe with descriptor <em>fdw</em> as the +writing end and descriptor <em>fdr</em> as the reading end. +It then execs into <em>prog</em> with its arguments. +</p> + +</body> +</html> 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 <david.madore@ens.fr> - see +${p} <URL: http://www.eleves.ens.fr:8080/home/madore/computers/quine.html > +${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 <david.madore@ens.fr> - see +# <URL: http://www.eleves.ens.fr:8080/home/madore/computers/quine.html > +# 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the redirfd command</title> + <meta name="Description" content="execline: the redirfd command" /> + <meta name="Keywords" content="execline command redirfd" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>redirfd</tt> program </h1> + +<p> +<tt>redirfd</tt> redirects a given file descriptor to a file, then +executes a program. +</p> + +<h2> Interface </h2> + +<pre> + redirfd [ -r | -w | -u | -a | -c | -x ] [ -n | -b ] <em>fd</em> <em>file</em> <em>prog...</em> +</pre> + +<p> +<tt>redirfd</tt> redirects the file descriptor number <em>fd</em> +to <em>file</em>, then execs into <em>prog...</em>. +</p> + +<h2> Options </h2> + +<p> + 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. +</p> + +<ul> + <li> <tt>-r</tt> : open <em>file</em> for reading. </li> + <li> <tt>-w</tt> : open <em>file</em> for writing, truncating it if it already exists. </li> + <li> <tt>-u</tt> : open <em>file</em> for reading and writing. </li> + <li> <tt>-a</tt> : open <em>file</em> for appending, creating it if it doesn't exist. </li> + <li> <tt>-c</tt> : open <em>file</em> for appending. Do not create it if it doesn't exist. </li> + <li> <tt>-x</tt> : open <em>file</em> for writing, creating it, failing if it already exists. </li> + <li> <tt>-n</tt> : open <em>file</em> in non-blocking mode. </li> + <li> <tt>-b</tt> : change mode of <em>file</em> after opening it: +to non-blocking mode if the <tt>-n</tt> option was not given, +to blocking mode if it was. </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> <tt>redirfd -r <em>n</em> <em>file</em> prog...</tt> is roughly equivalent to +<tt>sh -c 'exec prog... <em>n</em><<em>file</em>'</tt></li> + <li> <tt>redirfd -w <em>n</em> <em>file</em> prog...</tt> is roughly equivalent to +<tt>sh -c 'exec prog... <em>n</em>><em>file</em>'</tt></li> + <li> <tt>redirfd -u <em>n</em> <em>file</em> prog...</tt> is roughly equivalent to +<tt>sh -c 'exec prog... <em>n</em><><em>file</em>'</tt></li> + <li> <tt>redirfd -a <em>n</em> <em>file</em> prog...</tt> is roughly equivalent to +<tt>sh -c 'exec prog... <em>n</em>>><em>file</em>'</tt></li> + <li> <tt>redirfd -c <em>n</em> <em>file</em> prog...</tt> has no portable +shell equivalent. Some shells provide the <em>noclobber</em> option for +a similar feature. </li> + <li> <tt>redirfd -x <em>n</em> <em>file</em> prog...</tt> has no portable +shell equivalent.</tt> </li> +</ul> + +<h2> Special fifo handling </h2> + +<p> + The <tt>-n</tt> and <tt>-b</tt> options are especially useful with +named pipes. +</p> + +<ul> + <li> Opening a fifo for reading, blocking if there is no writer: +<tt>redirfd -r <em>n</em> <em>fifo</em> prog...</tt></li> + <li> Opening a fifo for reading, with instant success even if +there is no writer, and blocking at the first attempt to read from it: +<tt>redirfd -r -nb <em>n</em> <em>fifo</em> prog...</tt></li> + <li> Opening a fifo for writing, blocking if there is no reader: +<tt>redirfd -w <em>n</em> <em>fifo</em> prog...</tt></li> + <li> Opening a fifo for writing, with instant success even if +there is no reader: +<tt>redirfd -w -nb <em>n</em> <em>fifo</em> prog...</tt>. 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 <tt>redirfd</tt> +this way. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the runblock program</title> + <meta name="Description" content="execline: the runblock program" /> + <meta name="Keywords" content="execline command runblock" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">www.skarnet.org</a> +</p> + +<h1> The <tt>runblock</tt> program </h1> + +<p> +<tt>runblock</tt>'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, <tt>runblock</tt> +allows you to execute one of the blocks individually. +</p> + +<h2> Interface </h2> + +<pre> + runblock [ -P ] [ -n <em>argshift</em> ] [ -r ] <em>n</em> +</pre> + +<ul> + <li> <tt>runblock</tt> skips the first <em>argshift</em> positional +parameters. It does that to allow you to design commands that take simple +arguments <em>and</em> blocks. </li> + <li> Then <tt>runblock</tt> looks for and parses +<a href="el_semicolon.html">blocks</a> in the positional parameters. </li> + <li> If the <tt>-r</tt> option is present: <tt>runblock</tt> skips +<em>n</em> blocks and execs into the remaining arguments. </li> + <li> Else it skips <em>n</em>-1 blocks and execs into the <em>n</em>th +one. </li> + <li> Normally <tt>runblock</tt> <a href="el_pushenv.html#pop">pops</a> +its environment frame before executing. If the <tt>-P</tt> option has +been given, it <em>does not</em> pop. </li> + <li> Of course, if the block structure doesn't match, <tt>runblock</tt> +exits 100 with an error message. </li> +</ul> + +<h2> Example: implementing the <a href="ifelse.html">ifelse</a> command </h2> + +<p> + Suppose that we want to implement the <a href="ifelse.html">ifelse</a> command as +an execline script, using the <a href="ifte.html">ifte</a> command. +<tt>runblock</tt> allows us to do it in a simple way: +</p> + +<pre> + #!/command/execlineb + ifte { runblock 2 } { runblock -r 2 } runblock 1 +</pre> + +<p> + That's it. +</p> + +<h2> Credits </h2> + +<p> + The <tt>runblock</tt> idea, as well as the <tt>ifelse</tt> idea, comes +from <a href="http://code.dogmap.org/">Paul Jarc</a>. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the shift program</title> + <meta name="Description" content="execline: the shift program" /> + <meta name="Keywords" content="execline command shift" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">www.skarnet.org</a> +</p> + +<h1> The <tt>shift</tt> program </h1> + +<p> +<tt>shift</tt> shifts the positional parameters of an execline script. +</p> + +<h2> Interface </h2> + +<pre> + shift [ -n <em>argn</em> ] [ -b <em>blockn</em> ] <em>prog...</em> +</pre> + +<ul> + <li> <tt>shift</tt> shifts <em>argn</em> positional parameters, +then <em>blockn</em> blocks. It then execs <em>prog...</em>. </li> + <li> By default, <em>argn</em> and <em>blockn</em> are both zero; +but if neither the <tt>-n</tt> nor the <tt>-b</tt> option is given, +then <em>argn</em> is 1 and <em>blockn</em> is 0. </li> +</ul> + +<h2> Details </h2> + +<ul> + <li> <tt>shift</tt> reads the number of "positional parameters" in the +<tt>#</tt> environment variable. Let <em>n</em> be that number. </li> + <li> If the <tt>#</tt> environment variable is not set or does not +contain a valid number, or one of the <tt>0</tt>, <tt>1</tt>, ..., +<tt><em>n</em></tt> environment variables is not set, <tt>shift</tt> +exits 100 with an error message. </li> + <li> <tt>shift</tt> calculates a shift value <em>m</em>, corresponding +to <em>argn</em> arguments followed by enough arguments to make +<em>blockn</em> blocks. </li> + <li> It shifts the positional parameters <em>m</em> times: the +value of the <tt><em>m</em>+1</tt> variable becomes the value of the +<tt>1</tt> variable, <tt><em>m</em>+2</tt> becomes <tt>2</tt> and so on, +and <tt>#</tt> is set to <em>n</em>-<em>m</em> (floored at zero). </li> + <li> <tt>shift</tt> then execs into <em>prog...</em>. </li> +</ul> + +<h2> Notes </h2> + +<ul> + <li> <tt>shift</tt> is a standard shell builtin. Be careful if you +want to use it outside of an execline script. </li> + <li> The <tt>-b</tt> option is only useful to implement execline +commands in the execline language. You shouldn't normally have to +use it. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the tryexec command</title> + <meta name="Description" content="execline: the tryexec command" /> + <meta name="Keywords" content="execline command tryexec" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>tryexec</tt> program </h1> + +<p> +<tt>tryexec</tt> executes into a command line, with a fallback. +</p> + +<h2> Interface </h2> + +<p> + In an <a href="execlineb.html">execlineb</a> script: +</p> + +<pre> + tryexec [ -n ] [ -c ] [ -l ] [ -a argv0 ] { <em>prog1...</em> } <em>prog2...</em> +</pre> + +<ul> + <li> <tt>tryexec</tt> reads <em>prog1...</em> in a +<a href="el_semicolon.html">block</a>. It then executes into it, +completely forgetting <em>prog2...</em> </li> + <li> If for some reason the <tt>execve()</tt> fails - for instance, +a non-executable <em>prog1</em> - then <tt>tryexec</tt> executes +into <em>prog2...</em> instead. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-n</tt> : reverse <em>prog1...</em> and <em>prog2...</em>'s +role. The latter becomes the main execution path and the former becomes +the fallback. </li> +</ul> + +<p> + The <tt>-c</tt>, <tt>-l</tt> and <tt>-a</tt> options have the same +semantics as with the <a href="exec.html">exec</a> program. +</p> + +<h2> Notes </h2> + +<ul> + <li> <tt>tryexec <em>prog1...</em> "" <em>prog2...</em></tt> would be +equivalent to +<tt>sh -c 'exec <em>prog1...</em> || exec <em>prog2...</em>'</tt>, if +such a shell construct existed. Unfortunately, the shell language does +not offer that functionality. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the umask command</title> + <meta name="Description" content="execline: the umask command" /> + <meta name="Keywords" content="execline command umask" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>umask</tt> program </h1> + +<p> +<tt>umask</tt> sets the umask (file creation mask), +then executes a program. +</p> + +<h2> Interface </h2> + +<pre> + umask <em>mask</em> <em>prog...</em> +</pre> + +<p> +<tt>umask</tt> sets the current umask to <em>mask</em>, +then execs into <em>prog...</em>. +</p> + +<h2> Notes </h2> + +<p> +<tt>umask</tt> is a standard shell builtin. Be careful if you want to +use the <tt>umask</tt> command outside of an <tt>execline</tt> script. +</p> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the unexport command</title> + <meta name="Description" content="execline: the unexport command" /> + <meta name="Keywords" content="execline command unexport environment" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>unexport</tt> program </h1> + +<p> +<tt>unexport</tt> removes a variable from the environment, then +executes a program. +</p> + +<h2> Interface </h2> + +<pre> + unexport <em>var</em> <em>prog...</em> +</pre> + +<p> +<tt>unexport</tt> removes the <em>var</em> variable from the +environment, then execs into <em>prog</em> with +its arguments. +</p> + +<h2> Notes </h2> + +<ul> + <li> Unsetting <em>var</em> is quite different from setting it to an +empty value. Shell scripts usually won't make the distinction; +execline does. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: how to upgrade</title> + <meta name="Description" content="execline: how to upgrade" /> + <meta name="Keywords" content="execline installation upgrade" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + + +<h2> to 2.0.0.0 </h2> + +<ul> + <li> The build system has completely changed. It is now a standard +<tt>./configure && make & & sudo make install</tt> +build system. See the enclosed INSTALL file for details. </li> + <li> slashpackage is not activated by default. </li> + <li> shared libraries are neither built nor used by default. </li> + <li> skalibs dependency bumped to 2.0.0.0 </li> + <li> The obsolete -E option to backtick, forx and forbacktickx is not +supported anymore. </li> + <li> multisubstitute does not support the "backtick" directive +anymore. </li> +</ul> + +</body> +</html> 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 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: the wait command</title> + <meta name="Description" content="execline: the wait command" /> + <meta name="Keywords" content="execline command wait" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> The <tt>wait</tt> program </h1> + +<p> +<tt>wait</tt> waits for a set of children, then executes a program. +</p> + +<h2> Interface </h2> + +<p> + In an <a href="execlineb.html">execlineb</a> script: +</p> + +<pre> + wait [ -r ] { [ <em>pids...</em> ] } <em>prog...</em> +</pre> + +<ul> + <li> <tt>wait</tt> reads a list of <em>pids</em> in a +(possibly empty) <a href="el_semicolon.html">block</a>, +and unquotes it. </li> + <li> <tt>wait</tt> waits for every child whose pid is +listed in <em>pids...</em>. If <em>pids...</em> is an +empty list, it waits for every child process it has. </li> + <li><tt>wait</tt> then execs into <em>prog...</em>. </li> +</ul> + +<h2> Options </h2> + +<ul> + <li> <tt>-r</tt> : 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. </li> +</ul> + +</body> +</html> |