A command line (and thus an execline script) is one-dimensional. But a Unix execution flow can be two-dimensional: when two instructions are sequenced, for instance. In that case, we need a way to extract two command lines from one argv. That is precisely what blocks are made for.
execline commands that need more than one linear set of arguments use blocks. For instance, the ; command needs to spawn a first process, then execute into a second one. It reads the command line for the first process from a block, and the command line for the second process from the rest of the argv. In the following script:
#!/command/execlineb ; { echo 1 } echo 2
echo 1 is read from a block and spawned; then echo 2 is executed.
In execlineb scripts, blocks are delimited by braces. They can be nested.
execlineb reads and parses the script, and converts it into an argv (a simple Unix command line) with a different syntax for blocks. In an argv, blocks are not delimited by braces; they are made of quoted arguments and terminated by an empty word (""). A quoted argument begins with a space. Nested blocks are represented by arguments being quoted several times, i.e. having several spaces in front of them; an empty word inside a block gets quoted too, i.e. it will be represented as a series of spaces.
Actually, the block-reading commands know nothing about braces; they only understand the "quoted arguments + empty word" syntax. So if you want to use ; from your shell to sequence echo 1 and echo 2, you will have to write
$ ; ' echo' ' 1' '' echo 2
You do not really need to quote every argument inside a block in that simple case. The following command works as well:
$ ; echo 1 '' echo 2
However, this is bad practice, because it leads to a security hole: commands that perform substitution inside a block may produce empty words, which may modify your script's execution flow.
\$ = FOO '' \; ' echo' ' ${FOO}' ' rm' ' -rf' ' /' '' echo blah
is safe, whereas
\$ = FOO '' \; echo '${FOO}' rm -rf / '' echo blah
has very much unwanted results. (Don't try this at home.)
You can use the EXECLINE_STRICT environment variable to
check proper block quoting. If that variable contains 1,
commands that read blocks will print a warning message everytime
they find an unquoted argument inside a block. If that variable
contains 2 or a bigger integer, commands will print an
error message and die on unquoted arguments.
You can use execlineb's
-w or -W
switch to set EXECLINE_STRICT to 1 or 2.