goosh 1.0: A small process-control library for Guile.
Goosh is a library for execution of other programs from Guile. It
also allows communication using pipes (or a pseudo terminal device, but
that's not currently implemented). This was part of goonix in one of
Guile's past lives.
To load the library use:
(use-modules (goosh))
The following will hold when starting programs:
1. If the name of the program does not contain a `/' then the
directories listed in the current `PATH' environment variable are
searched to locate the program.
2. Unlike for the corresponding primitive exec procedures, e.g.,
`execlp', the name of the program can not be set independently of
the path to execute: the zeroth and first members of the argument
vector are combined into one.
- Function: tail-call-program prog arg ...
Replace the current process image by executing PROG with the
supplied list of arguments.
This procedure will reset the signal handlers, flush output buffers
and set up file descriptors as follows, but does not close any
ports.
1. File descriptor 0 is set from (current-input-port).
2. File descriptor 1 is set from (current-output-port).
3. File descriptor 2 is set from (current-error-port).
If a port can not be used then the file descriptor is opened on
the file specified by `*null-device*' instead.
Examples:
(tail-call-program "cat" "/etc/passwd")
(with-input-from-file "/etc/passwd"
(lambda ()
(tail-call-program "cat")))
- Function: tail-call-pipeline (prog arg ...) ...
Replace the current process image with a pipeline of connected
processes.
The expressions in the pipeline are run in new background
processes. The foreground process waits for them all to
terminate. The exit status is derived from the status of the
process at the tail of the pipeline: its exit status if it
terminates normally, otherwise 128 plus the number of the signal
that caused it to terminate.
The signal handlers will be reset, output buffers flushed and file
descriptors set up as for `tail-call-program'. Like
`tail-call-program' it does not close open ports.
Example:
(tail-call-pipeline ("ls" "/etc") ("grep" "passwd"))
- Function: tail-call-pipeline+ expr connections expr ...
Replace the current process image with a pipeline of connected
processes.
Each process is specified by an expression and each pair of
processes has a connection list with pairs of file descriptors.
E.g., `((1 0) (2 0))' specifies that file descriptors 1 and 2 are
to be connected to file descriptor 0. This may also be written as
`((1 2 0))'.
The expressions in the pipeline are run in new background
processes. The foreground process waits for them all to
terminate. The exit status is derived from the status of the
process at the tail of the pipeline: its exit status if it
terminates normally, otherwise 128 plus the number of the signal
that caused it to terminate.
The signal handlers will be reset, output buffers flushed and file
descriptors set up as for `tail-call-program'. Like
`tail-call-program' it does not close open ports.
Example:
(tail-call-pipeline+ (tail-call-program "ls" "/etc") ((1 0))
(tail-call-program "grep" "passwd"))
- Function: run prog arg ...
Execute PROG in a new foreground process and wait for its
completion. The value returned is the exit status of the new
process as returned by the `waitpid' procedure.
Example:
(run "cat" "/etc/passwd")
- Function: run+ expr keywords connections ...
Evaluate an expression in a new foreground process and wait for its
completion. If no connection terms are specified, then all ports
except `current-input-port', `current-output-port' and
`current-error-port' will be closed in the new process. The file
descriptors underlying these ports will not be changed.
The value returned is the exit status from the new process as
returned by the `waitpid' procedure.
The KEYWORDS and CONNECTIONS arguments are optional: see
`run-concurrently+', which is documented below. The
`#:foreground' keyword is implied.
(run+ (begin (write (+ 2 2)) (newline) (quit 0)))
(run+ (tail-call-program "cat" "/etc/passwd"))
- Function: run-with-pipe mode prog arg ...
Start PROG running in a new background process. The value
returned is a pair: the CAR is the pid of the new process and the
CDR is either a port or a pair of ports (with the CAR containing
the input port and the CDR the output port). The port(s) can be
used to read from the standard output of the process and/or write
to its standard input, depending on the MODE setting. The value
of MODE should be one of "r", "w" or "r+".
When the process terminates its exit status can be collected using
the `waitpid' procedure.
Example:
(define catport (cdr (run-with-pipe "r" "cat" "/etc/passwd")))
- Function: run-with-pty prog arg ...
This procedure is not currently implemented.
Start PROG running in a new background process, with communication
through a newly allocated pseudo terminal device (pty). The value
returned is a pair containing the pid of the new process and the
read/write port corresponding to the master side of the pty.
When the process terminates its exit status can be collected using
the `waitpid' procedure.
Example:
(define telport (cdr (run-with-pty "telnet")))
- Function: run-concurrently prog arg ...
Start a program running in a new background process. The value
returned is the pid of the new process.
When the process terminates its exit status can be collected using
the `waitpid' procedure.
Example:
(run-concurrently "cat" "/etc/passwd")
- Function: run-concurrently+ expr keywords connections ...
Evaluate an expression in a new background process. If no
connection terms are specified, then all ports except
`current-input-port', `current-output-port' and
`current-error-port' will be closed in the new process. The file
descriptors underlying these ports will not be changed.
The value returned in the parent is the pid of the new process.
When the process terminates its exit status can be collected using
the `waitpid' procedure.
Keywords can be specified before the connection list:
`#:slave' causes the new process to be put into a new session. If
`current-input-port' (after redirections) is a tty it will be
assigned as the controlling terminal. This option is used when
controlling a process via a pty.
`#:no-auto-close' prevents the usual closing of ports which occurs
by default.
`#:foreground' makes the new process the foreground job of the
controlling terminal, if the current process is using job control.
(not currently implemented). The default is to place it into the
background
The optional connection list can take several forms:
`(port)' usually specifies that a given port not be closed.
However if `#:no-auto-close' is present it specifies instead a
port which should be closed.
`(port 0)' specifies that a port be moved to a given file
descriptor (e.g., 0) in the new process. The order of the two
components is not significant, but one must be a number and the
other must evaluate to a port. If the file descriptor is one of
the standard set `(0, 1, 2)' then the corresponding standard port
(e.g., `current-input-port') will be set to the specified port.
Example:
(let ((p (open-input-file "/etc/passwd")))
(run-concurrently+ (tail-call-program "cat") (p 0)))