# Running Other Programs as Subprocesses

## Overview

&CCL; provides primitives to run external Unix programs, to select and connect Lisp streams to their input and output sources, to (optionally) wait for their completion and to check their execution and exit status.

All of the global symbols described below are exported from the CCL package.

This implementation is modeled on - and uses some code from - similar facilities in CMUCL.

## Examples

    ;;; Capture the output of the "uname" program in a lisp string-stream
    ;;; and return the generated string (which will contain a trailing
    ;;; newline.)
    ? (with-output-to-string (stream)
        (run-program "uname" '("-r") :output stream))
    ;;; Write a string to *STANDARD-OUTPUT*, the hard way.
    ? (run-program "cat" () :input (make-string-input-stream "hello") :output t)
    ;;; Find out that "ls" doesn't expand wildcards.
    ? (run-program "ls" '("*.lisp") :output t)
    ;;; Let the shell expand wildcards.
    ? (run-program "sh" '("-c" "ls *.lisp") :output t)

These last examples will only produce output if &CCL;'s current directory contains .lisp files, of course.

## Limitations and known bugs

- &CCL; and the external process may get confused about who owns which streams when input, output, or error are specified as T and wait is specified as NIL.

- External processes that need to talk to a terminal device may not work properly; the environment (SLIME, ILISP) under which &CCL; is run can affect this.

## External-Program Dictionary

### RUN-PROGRAM

Invokes an external program as an OS subprocess of lisp.
Function

    run-program
    	    program args &key; (wait t) pty sharing input
    	    if-input-does-not-exist output (if-output-exists :error) (error
    	    :output) (if-error-exists :error) status-hook
    	    external-format env (silently-ignore-catastrophic-failures
                *silently-ignore-catastrophic-failure-in-run-program*)

#### Arguments and Values

program

  A string or pathname which denotes an executable file. The PATH environment variable is used to find programs whose name doesn't contain a directory component.

args

  A list of simple-strings

wait

  Indicates whether or not run-program should wait for the EXTERNAL-PROCESS to complete or should return immediately.

pty

  This option is accepted but currently ignored; it's intended to make it easier to run external programs that need to interact with a terminal device.

sharing

  Sets a specific sharing mode (see ) for any streams created within RUN-PROGRAM when INPUT, OUTPUT or ERROR are requested to be a :STREAM.

input

  Selects the input source used by the EXTERNAL-PROCESS. May be any of the following:

  - NIL Specifies that a null input stream (e.g., /dev/null) should be used.

  - T Specifies that the EXTERNAL-PROCESS should use the input source with which &CCL; was invoked.

  - A string or pathname. Specifies that the EXTERNAL-PROCESS should receive its input from the named existing file.

  - :STREAM Creates a Lisp stream opened for character output. Any data written to this stream (accessible as the EXTERNAL-PROCESS-INPUT-STREAM of the EXTERNAL-PROCESS object) appears as input to the external process.

  - A stream. Specifies that the lisp stream should provide input to the EXTERNAL-PROCESS.

if-input-does-not-exist

  If the input argument specifies the name of an existing file, this argument is used as the if-does-not-exist argument to OPEN when that file is opened.

output

  Specifies where standard output from the external process should be sent. Analogous to input above.

if-output-exists

  If output is specified as a string or pathname, this argument is used as the if-exists argument to OPEN when that file is opened.

error

  Specifies where error output from the external process should be sent. In addition to the values allowed for output, the keyword :OUTPUT can be used to indicate that error output should be sent where standard output goes.

if-error-exists

  Analogous to if-output-exists.

status-hook

  A user-defined function of one argument (the EXTERNAL-PROCESS structure.) This function is called whenever &CCL; detects a change in the status of the EXTERNAL-PROCESS.

external-format

  The external format (see ) for all of the streams (input, output, and error) used to communicate with the external process.

env

  New OS environment variable bindings for the external process. By default the external process inherits the environment of the running Lisp process. Env is an association list with elements (<Environment Variable Name> . <Value>). Name and value are case sensitive strings. See .

>silently-ignore-catastrophic-failures

  If NIL, signal an error if run-program is unable to start the program. If non-NIL, treat failure to start the same as failure from the program itself, by setting the status and exit-code fields. Default is *silently-ignore-catastrophic-failure-in-run-program*.

#### Description

Runs the specified program in an external (Unix) process, returning an object of type EXTERNAL-PROCESS if successful.

The implementation involves a lisp process/thread which monitors the status of this external process and arranges for the standard I/O descriptors for the external process to be connected to the specified lisp streams. Since this may require the monitoring thread to do I/O on lisp streams in some cases, streams provided as the values of the `:INPUT`, `:OUTPUT`, and `:ERROR` arguments should not be private to some other lisp thread.

### SIGNAL-EXTERNAL-PROCESS

Function

    signal-external-process
    	    proc signal-number &key; (error-if-exited t)

#### Arguments and Values

proc

  An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.

signal

  A small integer.

error-if-exited

  A boolean, by default T.

#### Description

Sends `signal` to the external process `proc`. (Typically, it would only be useful to call this function if the EXTERNAL-PROCESS was created with :WAIT NIL.)

If successful, the function returns T; otherwise, an error is signaled.

However, if `error-if-exited` is nil, and the attempt to signal the external process fails because the external process has already exited, the function will return nil rather than signaling an error.

### EXTERNAL-PROCESS-ID

Returns the "process ID" of an OS subprocess, a positive integer which identifies it.
Function

    external-process-id
    	    proc

#### Arguments and Values

proc

  An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.

#### Description

Returns the process id assigned to the external process by the operating system. This is typically a positive, 16-bit number.

### EXTERNAL-PROCESS-INPUT-STREAM

Returns the lisp stream which is used to write input to a given OS subprocess, if it has one.
Function

    external-process-input-stream
    	    proc

#### Arguments and Values

proc

  An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.

#### Description

Returns the stream created when the input argument to run-program is specified as :STREAM.

### EXTERNAL-PROCESS-OUTPUT-STREAM

Returns the lisp stream which is used to read output from an OS subprocess, if there is one.
Function

    external-process-output-stream
    	    proc

#### Arguments and Values

proc

  An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.

#### Description

Returns the stream created when the output argument to run-program is specified as :STREAM.

### EXTERNAL-PROCESS-ERROR-STREAM

Returns the stream which is used to read "error" output from a given OS subprocess, if it has one.
Function

    external-process-error-stream
    	    proc

#### Arguments and Values

proc

  An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.

#### Description

Returns the stream created when the error argument to run-program is specified as :STREAM.

### EXTERNAL-PROCESS-STATUS

Returns information about whether an OS subprocess is running; or, if not, why not; and what its result code was if it completed.
Function

    external-process-status
    	    proc

#### Arguments and Values

proc

  An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.

#### Description

Returns, as multiple values, a keyword denoting the status of the external process (one of :running, :stopped, :signaled, or :exited), and the exit code or terminating signal if the first value is other than :running.