 |
|
| |
ORCH(5) |
FreeBSD File Formats Manual |
ORCH(5) |
orch —
orchestration script file format
The
porch(1)
program spawns other command-line utilities and drives them via a
pts(4),
using scripts referred to as orch scripts.
orch script files are written in Lua with
a limited environment available. Notably, absolutely none of the standard
environment is included. orch scripts are built
around constructing
match ()
blocks, sometimes in conjunction with multiplexing
one () blocks.
match ()
blocks in the same context are executed in the specified order. When a match
is successful, the beginning of the program output buffer is trimmed up to
the character just after the successful match. Future
match () blocks are left with the trimmed output
buffer to match against. The default timeout for a match to succeed is 10
seconds, and may be changed by specifying a timeout
parameter in the match configuration. The timeout may also be changed
globally for future match blocks with the timeout ()
function described below. match () blocks may also
have a callback specified, which itself may contain
any number of match () or
one () blocks.
orch imports only some parts
of the Lua standard library for use in the scriptfile,
to minimize the chance of being able to conduct actions that are inherently
incompatible with the queuing model that scripts are executed with.
Currently, only the
assert () and
type ()
functions, and the “string” and “table” modules
are exposed.
The following functions exist for usage within the
scriptfile:
cfg (cfg)
- Set configuration for the current process using the
cfg table. The specified cfg
is merged into the current configuration. Currently, the only recognized
configuration items are those described for the
write () function.
chdir ()
- Change the directory of the program most recently spawned. This must be
called after
spawn () and before the process is
releeased. There is currently no way to persistly
chdir(2)
for every spawned process.
clearenv (local)
- Clear the environment. If local is truthy, then the
environment is only cleared for the most recent
spawn ().
debug (string)
- Writes string out to the stderr of
orch , with “DEBUG:” prepended and a
newline appended to it.
This directive is enqueued, not processed immediately unless
it is called from within a failure handler.
enqueue (function)
- Add function to the queue to be executed in script
order. If
enqueue () is used in a context that does
not execute the queue, such as from another enqueued callback or from a
failure context, then it will immediately call the function instead of
enqueueing it.
eof (timeout,
termfn)
- Check for EOF from the process. If the process has closed its side because
it was killed by signal, then
orch will crash with
an assertion unless it was terminated by a signal that was sent by the
user with the signal () function. If
timeout is not specified, the default timeout will
be used. The timeout is applied both to waiting for
an actual EOF, and an additional wait for the process to have terminated.
The termfn callback will be invoked if
the process was terminated, with a wait status object as the only
argument to the callback. This wait status object has the following
methods:
is_exited ()
- Returns a boolean indicating whether the process exited or not.
is_signaled ()
- Returns a boolean indicating whether the process was signaled or
not.
is_stopped ()
- Returns a boolean indicating whether the process was stopped or
not.
status ()
- Returns the exit code or signal that resulted in termination or
stopping.
raw_status ()
- Returns the raw
wait(2)
status code.
This directive is enqueued, not processed immediately.
exec (commandstr,
collectfn, termfn)
- Execute commandstr without piping its output to a
spawned command. Note that, unlike other actions that take commands, the
exec () action will only take the command as a
string or a table that can be coerced into a command string. The result
will be passed directly to
io.popen ().
The output can be collected by specifying a
collectfn that takes a line and will be called for
every line until we reach EOF. If a collectfn is
not specified, then the output will be discarded. The
termfn will be called whether the output is
collected or not, and it will be passed a wait status object as
described above by the
eof ()
function.
This directive is enqueued, not processed immediately.
exit (status)
- Exit with the designed status code.
This directive is enqueued, not processed immediately unless
it is called from within a failure handler.
fail (function)
- Sets up a failure handler. Pass
nil to reset the
failure handler. The function will receive one
argument, the contents of the buffer, to aide in debugging. By default,
orch will exit with a status of 1 when a match
block fails. The failure handler prevents the default exit, but may itself
call exit (). The return value is ignored.
This directive is enqueued, not processed
immediately. The
fail ()
function is not available as a direct child of a
one () block.
flush (timeout)
- Flushes all output received within timeout seconds.
If timeout is 0 or unspecified, waits indefinitely
for EOF from the process.
This directive is enqueued, not processed immediately.
getenv (key)
- Get the value of key from the current environment.
This directive is always processed immediately
and may not be used in a queued context.
getenv ()
is expected to mostly be used for debugging purposes.
hexdump (string)
- Writes an
hd(1)
style hexdump output to stderr of the input string.
This directive is always processed immediately, and is
intended to be used within a failure context to aide in analysis of why
a match failed.
log (logfile)
- Sets a logfile for subsequent input and output to the process. The
logfile may be a string specifying a filename or an
open file (for lib users). If a filename is specified, then
orch will open it in write-append mode and
preserve existing contents.
matcher (type)
- Changes the default matcher for subsequent match blocks to the type
described by type. The default
type is the “lua” matcher, which
interprets match patterns as lua patterns and executes them accordingly.
Note that Lua string processing still applies for every pattern matcher.
e.g., “\r” will be interpreted as a carriage return for
these non-default pattern matchers.
The following matcher options are available:
- “lua”
- Uses Lua pattern matching to match patterns.
- “plain”
- Treats the pattern as a plain old string; no characters are
special.
- “posix”
- Treats the pattern as a POSIX extended regular expression. See
re_format(7)
for more details.
- “default”
- An alias for the “lua” matcher.
pipe (commandstr,
linefilter)
- Execute the command in commandstr and pipe any
output from it into the spawned process. Note that, unlike other actions
that take commands, the
pipe () action will only
take the command as a string or a table that can be coerced into a command
string. The result will be passed directly to
io.popen ().
If a linefilter callback is passed, then
every line from the given command will be ran through it and the result
of the call written to the process instead. If the callback returns nil,
then the line is skipped.
raw (boolean)
- Changes the raw
write () state on the process.
release ()
- Releases a spawned process for execution. This is done implicitly when a
match () block is first encountered.
This directive is enqueued, not processed immediately.
setenv (key,
value, local),
setenv (table,
local)
- Set the environment variable key to
value in the environment. If
local is truthy, then the value is only set for the
most recent
spawn (). The
table variant may be used to set multiple
environment variables at once.
sigblock (signo,
...)
- Block all signal signo specified. Each
signo may either be a signal number or a table with
signal numbers as values.
This directive is enqueued, not processed immediately.
sigcatch (signo,
...)
- Catch all signal signo specified. Each
signo may either be a signal number or a table with
signal numbers as values.
This directive is enqueued, not processed immediately.
sigclear ()
- Clear the signal mask.
This directive is enqueued, not processed immediately.
sigignore (signo,
...)
- Ignore all signal signo specified. Each
signo may either be a signal number or a table with
signal numbers as values.
This directive is enqueued, not processed immediately.
sigreset (preserve_sigmask)
- Resets all signals to be caught and clears the signal mask, unless
preserve_sigmask is truthy.
This directive is enqueued, not processed immediately.
sigunblock (signo,
...)
- Unblock all signal signo specified. Each
signo may either be a signal number or a table with
signal numbers as values.
This directive is enqueued, not processed immediately.
signal (signal)
- Send the specified signal to the current process.
The process must have already been released, either implicitly or by
explicit
release (),
prior to sending a signal. It is recommended to match at least one known
output from the process before sending a signal.
Signal names known on the current platform are exposed in the
signals table. The keys of this table are signal
names with a “SIG” prefix. Signals not described in this
table are also accepted. orch relies on
kill(2)
to validate the signal for maximum flexibility.
size (width,
height)
- Set or get the size of the terminal associated with the process. If at
least one of width or height
are not nil, then
size () will resize that
dimension of the window. The new current size of the window is always
returned.
The window will start off on a fresh spawn with a width and
height of 0. The size of the window is never persisted across
processes.
This directive is always processed immediately,
and thus should always be used in either an
enqueue ()
or fail context.
sleep (duration)
- Sleeps for at least the specified duration, in
seconds. Fractional seconds are supported. As implemented,
orch may delay execution for a little longer than
the specified duration, but not for any less time.
This directive is enqueued, not processed immediately unless
it is called from within a failure handler.
spawn (...)
- Spawns a new process. The arguments to
spawn () are
in the traditional argv style. They may either be specified directly as
arguments to the function, or they may instead be constructed as a single
table. orch will execute a standard
PATH search via
execvp(3).
Note that the script's directory is added to PATH
before execution begins. The spawned process will inherit the running
environment.
If the process cannot be spawned, then
orch will exit. Note that only one process at a
time may be matched against. If a new process is spawned, then the
previous process will be killed and subsequent matches will be against
the new process.
This directive is enqueued, not processed immediately.
stty (field,
set, unset)
- Change the specified field as described by
set and unset.
field should be one of “cflag”,
“iflag”, “lflag”, “oflag”, or
“cc”, corresponding to the similarly named fields in
termios(4).
For the flag fields, the bits in set will be set in
the new mask, and the bits in unset will be unset in
the new mask. Either may be 0 or nil to indicate no bits to be set or
unset respectively. The masks for each field may be found in the
“tty” table in the script's global environment. For
instance, ICANON's mask may be referenced as
“tty.lflag.ICANON”.
For “cc”, the unset
argument is ignored, and set should be a table
whose keys correspond to a defined “V*” constant, and
whose values are either the empty string to indicate that the field
should be disabled, an integer for VMIN and VTIME, or a string of the
form “^X” to indicate ctrl-X.
Supported entries may be found in the “tty”
table in the script's global environment. The “tty.cc”
table's keys correspond to supported characters, e.g.,
“tty.cc.VEOF”, and the associated values are all truthy to
indicate that they are supported.
This directive is enqueued, not processed immediately.
timeout (val)
- Adjust the default timeout to val seconds for
subsequent
match () blocks. The default timeout at
script start is 10 seconds.
This directive is processed immediately.
write (str,
cfg)
- Write str to stdin of the spawned process. If the
process is in
raw () mode, then
write () will write the entire
str ()
out as given. If the process is not in raw () mode,
which is the default, then escape sequences and control characters will be
processed. Note that lua strings are naturally escape-processed in
addition to any escaping done by orch . For
example, if one wants to send a literal “^D” in non-raw
mode, then “\\^D” is the correct sequence to do so. The
first backslash escapes the second backslash, then
orch sees just a single backslash preceding the
circumflex.
This directive is enqueued, not processed immediately.
Execution does not continue to the next command until the
str has been completely written.
The cfg argument is a table of
configuration items for the current send. The following elements are
supported:
- rate
- The rate at which to send str. This is specified
as a table with, at a minimum, a bytes item to
describe how many bytes to send in a single batch.
orch also accepts a
delay item to describe how long to wait in
between each batch, in seconds. As with the
sleep ()
function, fractional seconds are supported. With a
delay of 0, orch will
still call into sleep () with no delay. With no
delay, orch will send
each batch with no delay in between them.
The “match” blocks are the core primitive of
orch scripts. Setting them up sounds complicated,
but some Lua-supplied sugar actually makes construction of
match () blocks relatively elegant. More on this will
be demonstrated in the EXAMPLES
section.
The
match ()
function takes exactly one argument: a pattern to match against. These
patterns are Lua patterns, used without modification to check the output
buffer. The match () returns an anonymous function
that may be called again with a table to describe the properties of the
match () block.
The following properties are available:
- callback
- Specifies a function to call if the match succeeds. The
callback function may itself construct additional
“match /” “any” blocks, that will then be used
for output matching before proceeding after the successfully matched
match ()
block.
- timeout
- Overrides the current global timeout. The timeout
value is measured in seconds.
Constructing a “one” block is as simple as calling
one (). The one () function
takes a callback as its argument, and this function should setup two or more
match () blocks to multiplex between. The first
matching pattern, as specified in script order, will be used and the rest of
the block discarded. The usual rules of match ()
blocks apply at this point; the callback will be executed, and the callback
may also do further matching.
Note that timeout likely does work
in a one ()
block as you might expect. orch will effectively
wait the full length of the longest timeout for any of the
match () blocks that it contains. If some blocks have
shorter timeouts than others, then orch will timeout
after the shortest timeout it sees in the block at the time. If the shorter
timeout block still does not match, it will be removed from consideration
and we will wait up until the next shortest timeout would have expired. That
is, a match will not be granted if the matching output comes in after the
timeout would have elapsed, even if we are still waiting on input for other
blocks.
This listing demonstrates the basic features:
-- Literally spawns a new command: "Hello there", that we will be examining.
spawn("echo", "Hello there")
-- Sets a new default for subsequent match blocks
timeout(3)
-- Just matches the initial "Hello", output buffer now contains " there" to
-- match against.
match "Hello"
-- You are also welcome to do this, if it feels more natural to you:
match("t")
-- This is effectively ignored since the only match block after it specifies an
-- explicit timeout. If we had another match block after that one, though, then
-- it would use a one second timeout by default.
timeout(1)
-- This one will fail to match, but we have configured a higher timeout than the
-- global timeout we configured above (one second).
match "Friend" {
timeout = 5,
}
This block demonstrates bidirectional communication:
spawn("cat")
-- The tty we setup is in canonical mode by default, so the trailing \r is
-- necessary for the spawned process to read it (unless the process turns off
-- canonical mode).
write "Hello there\r"
match "Hello" {
callback = function()
debug("Hello matched")
end
}
This block demonstrates more complex nested match blocks:
spawn("cat")
write "Hello world\r"
match "Hello" {
callback = function()
-- This will match the world sent above...
match "world" {
callback = function()
-- ... and additionally write "FRIENDS" out
write "FRIENDS\r"
end
}
end
}
match "FRIENDS" {
callback = function()
debug "FRIENDS seen!"
end
}
This block demonstrates one blocks:
spawn("cat")
write "One\r"
-- These might feel a little bit awkward
one(function()
-- This match block will end up used because it is specified first.
match "ne" {
callback = function()
debug("This one will be called.")
-- Script execution continues after the one() block that contains
-- this match.
write "One\r"
end
}
-- This match block will effectively be thrown away.
match "One" {
callback = function()
debug("This one will not be called")
end
}
end)
-- This one will match, because the "ne" block's callback wrote it out.
match "One"
More examples can be found in
/usr/share/porch/examples.
Visit the GSP FreeBSD Man Page Interface. Output converted with ManDoc.
|