## OS Reference

## `ext:*help-message*`

Command line help message

### Variable

Type

  A string

Initial value

  &ECL; help message

### Description

This variable contains the help message which is output when &ECL; is invoked with the `--help`.

### Example

See .

## `ext:*lisp-init-file-list*`

&ECL; initialization files.

### Constant

Type

  A list of pathname designators.

Initial value

  `'("~/.ecl" "~/.eclrc")`

### Description

This variable contains the names of initialization files that are loaded by &ECL; or embedding programs. The loading of initialization files happens automatically in &ECL; unless invoked with the option `-norc`. Whether initialization files are loaded or not is controlled by the command line options rules, as described in .

### Example

See .

## `ext:+default-command-arg-rules+`

&ECL; command line options

### Constant

Type

  A list of lists.

### Description

This constant contains a list of rules for parsing the command line arguments. This list is made of all the options which &ECL; accepts by default. It can be passed as first argument to , and you can use it as a starting point to extend &ECL;.

### Example

See .

## `ext:command-args`

Original list of command line arguments.

### Function

         ext:command-args

returns

  A list of strings.

### Description

This function returns the list of command line arguments passed to either &ECL; or the program it was embedded in. The output is a list of strings and it corresponds to the `argv` vector in a C program. Typically, the first argument is the name of the program as it was invoked. You should not count on ths filename to be resolved.

## `ext:process-command-args`

Process command line arguments.

### Function

         ext:process-command-args
         &key;
         args
         rules

args

  A list of strings. Defaults to the output of

rules

  A list of lists. Defaults to the value of

### Description

This function processes the command line arguments passed to either &ECL; or the program that embeds it. It uses the list of rules rules, which has the following syntax:

    (option-name nargs template [:stop | :noloadrc | :loadrc]*)

option-name

  A string with the option prefix as typed by the user. For instance `--help`, `-?`, `--compile`, etc.

nargs

  A nonnegative integer denoting the number of arguments taken by this option.

template

  A lisp form, not evaluated, where numbers from 0 to nargs will be replaced by the corresponding option argument.

:STOP

  If present, parsing of arguments stops after this option is found and processed. The list of remaining arguments is passed to the rule. &ECL;'s top-level uses this option with the -- command line option to set ext:*unprocessed-ecl-command-args* to the list of remaining arguments.

:NOLOADRC and :LOADRC

  Determine whether the lisp initalization file () will be loaded before processing all forms.

`EXT:PROCESS-COMMAND-ARGS` works as follows. First of all, it parses all the command line arguments, except for the first one, which is assumed to contain the program name. Each of these arguments is matched against the rules, sequentially, until one of the patterns succeeeds.

A special name `"*DEFAULT*"`, matches any unknown command line option. If there is no `"*DEFAULT*"` rule and no match is found, an error is signalled. For each rule that succeeds, the function constructs a lisp statement using the template.

After all arguments have been processed, `EXT:PROCESS-COMMAND-ARGS`, and there were no occurences of :NOLOADRC, one of the files listed in will be loaded. Finally, the list of lisp statements will be evaluated.

### Example

The following piece of code implements the `ls` command using lisp. Instructions for building this program are found under `ecl/examples/cmdline/ls.lsp`

    (setq ext:*help-message* "
    ls [--help | -?] filename*
         Lists the file that match the given patterns.
    ")

    (defun print-directory (pathnames)
     (format t "~{~A~%~}"
      (mapcar #'(lambda (x) (enough-namestring x (si::getcwd)))
              (mapcan #'directory (or pathnames '("*.*" "*/"))))))

    (defconstant +ls-rules+
    '(("--help" 0 (progn (princ ext:*help-message* *standard-output*) (ext:quit 0)))
      ("-?" 0 (progn (princ ext:*help-message* *standard-output*) (ext:quit 0)))
      ("*DEFAULT*" 1 (print-directory 1) :stop)))

    (let ((ext:*lisp-init-file-list* NIL)) ; No initialization files
      (handler-case (ext:process-command-args :rules +ls-rules+)
        (error (c)
           (princ ext:*help-message* *error-output*)
           (ext:quit 1))))
    (ext:quit 0)

## `ext:quit`

Exit &ECL;.

### Function

         ext:quit
         &optional;
         exit-code

exit-code

  An integer between 0 and 255

### Description

This function abruptly stops the execution of the program in which &ECL; is embedded. Depending on the platform, several other functions will be invoked to free resources, close loaded modules, etc.

The exit code is the code seen by the parent process that invoked this program. Normally a code other than zero denotes an error.

## `ext:external-process`

Holds process state.

### Structure

    ext:external-process

PID

  process pid

INPUT

  process input stream

OUTPUT

  process output stream

ERROR-STREAM

  process error stream

%STATUS

  either :RUNNING, :STOPPED, :SIGNALED, :EXITED

, :ERROR or :ABORT
%CODE

  exit code or nil (if still running)

### Description

This structure is responsible for holding external process state - process id, communication streams, runtime status and exit code. It is returned as third value of .

## `ext:external-process-status`

Check status of .

### Function

         ext:external-process-status
         external-process

### Description

Checks status of external-process. Returns it's current status, and if exited - EXIT-CODE as second value.

## `ext:run-program`

Start and communicate with a child process.

### Function

         ext:run-program
         command
         argv
         &key;
         input
         output
         error
         wait
         environ
         if-input-does-exist
         if-output-exists
         if-error-exists
         external-format

input

  One of :STREAM, T, NIL, string or pathname - defaults to :STREAM

output

  One of :STREAM, T, NIL, string or pathname - defaults to :STREAM

error

  One of :OUTPUT, :STREAM, T, NIL, string or pathname - defaults to :OUTPUT

wait

  Boolean indicating if process should run synchronously, defaults to T

environ

  List of strings containing environment bindings. Defaults to NIL (inheritance of lisp process environment).

if-input-does-not-exist

  If :INPUT is pathname this symbol value is provided as :IF-DOES-NOT-EXIST for CL_OPEN. Defaults to NIL

if-output-exists

  If :OUTPUT is pathname this symbol value is provided as :IF-EXISTS for CL_OPEN. Defaults to :ERROR

if-error-exists

  If :ERROR is pathname this symbol value is provided as :IF-EXISTS for CL_OPEN. Defaults to :ERROR

external-format

  External format used for both streams and pathnames. Defaults to :DEFAULT

returns

  Two-way stream responsible for input/output with created process (created of :OUTPUT and :INPUT),

  Return code of spawned process. If process still runs then NIL

  structure holding process state.

### Description

This function creates a external process by launching the program command with the arguments from the list argv.

The arguments input, output and error are used to intercept the standard input, output and error streams of the program. A value of :STREAM means a lisp stream will be created to communicate with the child process. A value of NIL means that the data from this pipe will be discarded. The value of T means that the child process will use the parent's standard input, output or error channels. If value is pathname, then corresponding file will be used (strings are coerced to pathnames).

For instance, if &ECL; writes to the console and you pass a value of output equal to T, the child process will also output to the console. Finally, the error messages of the child process are redirected to the same pipe as its standard output when error takes the value :OUTPUT.

If the child process was succesfully launched, this function outputs a lisp stream to which we one may write, read or do both things, depending on the arguments input and output. If an error happened during the preparation of the child process (for instance the program was not found), this function returns NIL.

Function returns three values - two-way stream for communication, return-code or nil depending if process is called asynchronously, and structure holding process state.

The design of this function is inspired by the function of same name in &CMUCL; and &SBCL;.

### Example

List all users in a Unix system. We use the `sed` command to parse the file with the list of users, removing comments and information other than the user names:

    (defun all-users (&optional (file "/etc/passwd"))
      (let ((s (ext:run-program "sed"
                  (list "-e" "/^#.*$/d;/^[^:]*$/d;s,^\\([^:]*\\).*$,\\1,g"
                    file)
                  :input NIL :output :STREAM :error NIL)))
        (unless s
          (error "Unable to parse password file"))
        (loop for x = (read s NIL NIL)
              while x
              collect x)))

Make a directory. Redirect standard error output to the same as the output:

    (ext:run-program "mkdir" '("./tmp") :output :STREAM :error :OUTPUT)

Same as before, but now both the output and the standard error are discarded

    (ext:run-program "mkdir" '("./tmp") :output NIL :error :OUTPUT)

### Limitations

All streams passed to `ext:run-program` has to have underlying file handler. That means, that if gray streams are passed to function - it might signal an error. Such situation occurs, when for instance :OUTPUT value is T and *standard-output* is bound to gray stream (default if using slime and emacs).

## `ext:system`

Invoke a command using the shell.

### Function

         ext:system
         command

command

  A string

returns

  An integer (0-255) with the exit code of the program

### Description

This function executes a command in the shell. In Unix systems, typically the environment variable SHELL determines which program will be invoked, while in Windows `CMD.EXE` is used. The string may thus be any valid command that the shell accepts and in can contain higher level elements such as input/output redirection. Output isn't printed.

As an example, the following function uses an external editor to modify a lisp file and, if successful, loads the changed sources:

    (defun edit (filename)
      (let* ((editor #+windows "notepad.exe"
                     #-windows "/usr/bin/emacs")
        (command (concatenate 'string editor " " filename)))
        (when (zerop (ext:system command))
        (load filename))))