Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
ORCH(5) 		       File Formats Manual			 ORCH(5)

NAME
     orch -- orchestration script file format

DESCRIPTION
     The  porch(1)  program  spawns other command-line utilities and drives them
     via a pts(4), using scripts referred to as orch scripts.

SCRIPT FILES
     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 conjunc-
     tion 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 time-
     out() 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 exe-
     cuted 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  en-
	     queue()  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 as-
	     sertion 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 wait-
	     ing 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  sig-
		     naled 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	termina-
		     tion 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()  ac-
	     tion  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  de-
	     fault  exit,  but	may itself call exit().  The return value is ig-
	     nored.

	     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 accord-
	     ingly.  Note that Lua string processing  still  applies  for  every
	     pattern  matcher.	e.g., "\r" will be interpreted as a carriage re-
	     turn 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  sig-
	     nal 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 sig-
	     nal 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 sig-
	     nal 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  re-
	     lease(),  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  ac-
	     cepted.   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 al-
	     ways 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 tradi-
	     tional argv style.  They may either be specified directly as  argu-
	     ments to the function, or they may instead be constructed as a sin-
	     gle 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",  cor-
	     responding  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 sup-
	     ported 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 es-
	     cape sequences and control characters will be processed.  Note that
	     lua strings are naturally escape-processed in addition to	any  es-
	     caping  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  com-
	     pletely 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  ta-
		     ble  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.

BLOCK PRIMITIVES
   Match Blocks
     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  mea-
	     sured in seconds.

   One Blocks
     Constructing  a "one" block is as simple as calling one().  The one() func-
     tion 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  dis-
     carded.   The  usual rules of match() blocks apply at this point; the call-
     back 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  time-
     outs 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.

EXAMPLES
     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.

SEE ALSO
     porch(1), pts(4), termios(4)

FreeBSD ports 15.quarterly	  June 4, 2025				 ORCH(5)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=orch&sektion=5&manpath=FreeBSD+Ports+15.1.quarterly>

home | help