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	avail-
       able.   Notably,	 absolutely  none  of  the standard environment	is in-
       cluded.	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 configu-
       ration.	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  environ-
	       ment 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 con-
	       text, then it will immediately call the function	instead	of en-
	       queueing	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	termi-
	       nated,  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	termi-
		       nation 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  com-
	       mand.   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 han-
	       dler.  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  han-
	       dler  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  con-
	       tents.

       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 ap-
	       plies for every pattern matcher.	 e.g.,	"\r"  will  be	inter-
	       preted  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  expres-
		       sion.  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 implic-
	       itly 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 re-
	       cent  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, un-
	       less 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  ex-
	       plicit 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 ac-
	       cepted.	orch relies on kill(2) to validate the signal for max-
	       imum 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  cur-
	       rent 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.	 Frac-
	       tional 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 tra-
	       ditional	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 in-
	       stance, 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	corre-
	       spond to	supported characters, e.g., "tty.cc.VEOF", and the as-
	       sociated	values are all truthy to indicate that they  are  sup-
	       ported.

	       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 sec-
	       onds.

	       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  de-
	       fault,  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 exam-
	       ple, 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.	Execu-
	       tion 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 cur-
	       rent 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 ac-
		       cepts a delay item to describe how long to wait in  be-
		       tween  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
	       measured	in seconds.

   One Blocks
       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  ex-
       pect.   orch will effectively wait the full length of the longest time-
       out 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 considera-
       tion and	we will	wait up	until the next shortest	timeout	would have ex-
       pired.  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.0		 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.0>

home | help