Commands to External Environments

Issuing commands to the surrounding environment is an integral part of Rexx.

Environment

The base system for the language processor is assumed to include at least one environment for processing commands. An environment is selected by default on entry to a Rexx program. You can change the environment by using the ADDRESS instruction. You can find out the name of the current environment by using the ADDRESS built-in function. The underlying operating system defines environments external to the Rexx program. The environments selected depend on the caller. Normally the default environment is the used shell, mostly "CMD" on Windows systems and "bash" on Linux systems. If called from an editor that accepts subcommands from the language processor, the default environment can be that editor.

A Rexx program can issue commands—called subcommands—to other application programs. For example, a Rexx program written for a text editor can inspect a file being edited, issue subcommands to make changes, test return codes to check that the subcommands have been processed as expected, and display messages to the user when appropriate.

An application that uses Rexx as a macro language must register its environment with the Rexx language processor. See the Open Object Rexx: Programming Guide for a discussion of this mechanism.

Commands

To send a command to the currently addressed environment, use a clause of the form:

expression;

The expression (which must not be an expression that forms a valid message instruction—see Message Instructions) is evaluated, resulting in a character string value (which can be the null string), which is then prepared as appropriate and submitted to the environment specified by the current ADDRESS setting.

The environment then processes the command and returns control to the language processor after setting a return code. A return code is a string, typically a number, that returns some information about the command processed. A return code usually indicates if a command was successful but can also represent other information. The language processor places this return code in the Rexx special variable RC. See Special Variables.

In addition to setting a return code, the underlying system can also indicate to the language processor if an error or failure occurred. An error is a condition raised by a command to which a program that uses that command can respond. For example, a locate command to an editing system might report requested string not found as an error. A failure is a condition raised by a command to which a program that uses that command cannot respond, for example, a command that is not executable or cannot be found.

Errors and failures in commands can affect Rexx processing if a condition trap for ERROR or FAILURE is ON (see Conditions and Condition Traps). They can also cause the command to be traced if TRACE E or TRACE F is set. TRACE Normal is the same as TRACE F and is the default—see TRACE.

The .RS environment symbol can also be used to detect command failures and errors. When the command environment indicates that a command failure has occurred, the Rexx environment symbol .RS has the value -1. When a command error occurs, .RS has a value of 1. If the command did not have a FAILURE or ERROR condition, .RS is 0.

Here is an example of submitting a command. Where the default environment is Windows, the sequence:

fname = "CHESHIRE"
exten = "CAT"
"TYPE" fname"."exten

would result in passing the string TYPE CHESHIRE.CAT to the command processor, CMD.EXE. The simpler expression:

"TYPE CHESHIRE.CAT"

has the same effect.

On return, the return code placed in RC will have the value 0 if the file CHESHIRE.CAT were typed, or a nonzero value if the file could not be found in the current directory.

Note: Remember that the expression is evaluated before it is passed to the environment. Constant portions of the command should be specified as literal strings.

Windows Example:

delete "*".lst           /* not "multiplied by" */
var.003 = anyvalue
type "var.003"           /* not a compound symbol */

w = any
dir"/w"                  /* not "divided by ANY" */

Linux Example:

rm "*".lst               /* not "multiplied by" */
var.003 = anyvalue
cat "var.003"            /* not a compound symbol */

w = any
ls "/w"                  /* not "divided by ANY" */

Enclosing an entire message instruction in parentheses causes the message result to be used as a command. Any clause that is a message instruction is not treated as a command. Thus, for example, the clause

myfile~linein

causes the returned line to be assigned to the variable RESULT, not to be used as a command to an external environment, while

(myfile~linein)

would submit the return value from the linein method as a command to the external environment.