## 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 ref.process-command-args.

`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 ref.process-command-args.

#### Example

See ref.process-command-args.

`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 ref.process-command-args, and you can use it as a starting point to extend &ECL;.

#### Example

See ref.process-command-args.

`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 ref.command-args

`rules`

- A list of lists. Defaults to the value of ref._default-command-arg-rules_

#### 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 (ref._lisp-init-file-list_) 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 ref._lisp-init-file-list_ 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 ref.run-program.

`ext:external-process-status`

Check status of ref.external-process.

### 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

- ref.external-process 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 ref.external-process 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))))