So there are several things.
- "=" is not a legit envvar name: envvar names cannot include a '='
character. "!" is absolutely a legit envvar name, though, and execline
uses it with commands such as background or pipeline.
- execline does not understand single quotes. '!' will translate into
the word "'!'". So, don't use single quotes in execline, ever. Only
- It is a peculiarity, and *the* non-posix behaviour, of s6-test, that
when an argument starts with a backslash, the backslash is ignored,
and the remainder of an argument is used as data, and never as an
operator. s6-test uses this to disambiguate, instead of relying on the
total number of arguments (and doing unspecified, unpredictable things
when given more than 4 arguments). For instance,
"s6-test -r = -r" will fail with a parsing error (which is
to the "test" specification), because there is a parsing ambiguity with
"-r =", and s6-test does not use the fact that there is another argument
behind "=" to lift the ambiguity.
- "s6-test -v !" sounds like a simple case, but it's not, because "!"
is a valid operator for s6-test, and s6-test does not look past "!" to
see there are no further arguments and "!" cannot be an operator. So it
fails for the same reason described above. The way to avoid that is to
backslash the argument: "s6-test -v \!"
- execline uses \ as a quoting character, so when writing an execline
script, you need to double the amount of backslashes that you want to
appear in your argv. Here, you want one backslash before the "!", so
you would write
s6-test -v \\!
and that should work.
- I know that the s6-test behaviour is non-conforming when you provide
fewer than 4 arguments, and is non-intuitive and annoying, especially
when "test" just works. But it is *mighty hard* to implement the POSIX
disambiguation method without exploding the code size. Doing it would
take some real serious effort and probably double the size of the
source code - and it would *still* need to provide a different way to
disambiguate for 5 arguments or more, because s6-test explicitly
an infinite number of arguments. (Or, rather, as many as fit into your
argv.) This is the very reason why I didn't bother making it a
"test" implementation: the POSIX requirements require ad-hoc operator
priority rules that do not fit the shift-reduce engine *at all* and that
are super difficult to implement cleanly.
- I wrote s6-test when I was first reading the Dragon Book on compiler
implementation, specifically the chapters on parsing, as an exercise to
check I understood how pushdown automata worked. s6-test and s6-expr are
prime examples of pushdown automata. So that is why 1. I needed a shift-
reduce disambiguation method that meshed well with the engine, which
the POSIX test disambiguation method is not, and 2. the code may not be
intuitive, because it's the most "computer science academia" thing I've
ever written. :)
(Yes, that includes the execline/mdevd/... parsers. These parsers are
table-driven parsers, aka deterministic finite automata. That's
The tables look intimidating, but the code itself is very
Pushdown automata are a different story, you really need the theoretical
background to wrap your mind around them.)
TL;DR: s6-test is not test, please use s6-test -v \\!
in your execline scripts, and basically prepend any argument that looks
like a possible test operator with two backslashes (because execline
eats one, and a shell would as well).