Trait Command

Source
pub trait Command {
    // Required method
    async fn execute(&self, env: &mut Env) -> Result;
}
Expand description

Syntactic construct that can be executed.

Required Methods§

Source

async fn execute(&self, env: &mut Env) -> Result

Executes this command.

Implementations of this method is expected to update env.exit_status reflecting the result of the command execution.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl Command for Command

Executes the command.

After executing the command body, the execute function runs traps if any caught signals are pending, and updates subshell statuses.

Source§

async fn execute(&self, env: &mut Env) -> Result

Source§

impl Command for CompoundCommand

Executes the compound command.

§Grouping

A grouping is executed by running the contained list.

§Subshell

A subshell is executed by running the contained list in a separate environment (Subshell).

After the subshell has finished, Env::apply_errexit is called.

§For loop

Executing a for loop starts with expanding the name and values. If values is None, it expands to the current positional parameters. Each field resulting from the expansion is assigned to the variable name, and in turn, body is executed.

§While loop

The condition is executed first. If its exit status is zero, the body is executed. The execution is repeated while the condition exit status is zero.

§Until loop

The until loop is executed in the same manner as the while loop except that the loop condition is inverted: The execution continues until the condition exit status is zero.

§If conditional construct

The if command first executes the condition. If its exit status is zero, it runs the body, and its exit status becomes that of the if command. Otherwise, it executes the condition of each elif-then clause until finding a condition that returns an exit status of zero, after which it runs the corresponding body. If all the conditions result in a non-zero exit status, it runs the else clause, if any. In case the command has no else clause, the final exit status will be zero.

§Case conditional construct

The “case” command expands the subject word and executes the body of the first item with a pattern matching the word. Each pattern is subjected to word expansion before matching.

POSIX does not specify the order in which the shell tests multiple patterns in an item. This implementation tries them in the order of appearance.

After executing the body of the matching item, the case command may process the next item depending on the continuation.

Source§

async fn execute(&self, env: &mut Env) -> Result

Source§

impl Command for AndOrList

Executes the and-or list.

The && operator first executes the left-hand-side pipeline, and if and only if the exit status is zero, executes the right-hand-side. The || operator works similarly but runs the right-hand-side if and only if the left-hand-side exit status is non-zero. The && and || operators are left-associative and have equal precedence.

The exit status of the and-or list will be that of the last executed pipeline.

Frame::Condition is pushed to the environment’s stack while the execution of the pipelines except for the last.

Source§

async fn execute(&self, env: &mut Env) -> Result

Source§

impl Command for FullCompoundCommand

Executes the compound command.

The redirections are performed, if any, before executing the command body. Redirection errors are subject to the ErrExit option (Env::apply_errexit).

Source§

async fn execute(&self, env: &mut Env) -> Result

Source§

impl Command for FunctionDefinition

Executes the function definition command.

First, the function name is expanded. If the expansion fails, the execution ends with a non-zero exit status. Next, the environment is examined for an existing function having the same name. If there is such a function that is read-only, the execution ends with a non-zero exit status. Finally, the function definition is inserted into the environment, and the execution ends with an exit status of zero.

The ErrExit shell option is applied on error.

Source§

async fn execute(&self, env: &mut Env) -> Result

Source§

impl Command for Item

Executes the item.

§Synchronous command

If the item’s async_flag is None, this function executes the and-or list in the item.

§Asynchronous command

If the item has an async_flag set, the and-or list is executed asynchronously in a subshell, whose process ID is set to the job list in the environment.

Since this function finishes before the asynchronous execution finishes, the exit status does not reflect the results of the and-or list; the exit status is always 0.

If the Monitor option is off, the standard input of the asynchronous and-or list is implicitly redirected to /dev/null.

Source§

async fn execute(&self, env: &mut Env) -> Result

Source§

impl Command for List

Executes the list.

The list is executed by executing each item in sequence. If any item results in a Divert, the remaining items are not executed.

Source§

async fn execute(&self, env: &mut Env) -> Result

Source§

impl Command for Pipeline

Executes the pipeline.

§Executing commands

If this pipeline contains one command, it is executed in the current shell execution environment.

If the pipeline has more than one command, all the commands are executed concurrently. Every command is executed in a new subshell. The standard output of a command is connected to the standard input of the next command via a pipe, except for the standard output of the last command and the standard input of the first command, which are not modified.

If the pipeline has no command, it is a no-op.

§Exit status

The exit status of the pipeline is that of the last command (or zero if no command). If the pipeline starts with an !, the exit status is inverted: zero becomes one, and non-zero becomes zero.

In POSIX, the expected exit status is unclear when an inverted pipeline performs a jump as in ! return 42. The behavior disagrees among existing shells. This implementation does not invert the exit status when the return value is Err(Divert::...).

§noexec option

If the Exec and Interactive options are Off in env.options, the entire execution of the pipeline is skipped. (The noexec option is ignored if the shell is interactive, otherwise you cannot exit the shell in any way if the ignoreeof option is set.)

§Stack

if self.negation is true, Frame::Condition is pushed to the environment’s stack while the pipeline is executed.

Source§

async fn execute(&self, env: &mut Env) -> Result

Source§

impl Command for SimpleCommand

Executes the simple command.

§Outline

The execution starts with the expansion of the command words. Next, the command search is performed to find an execution target named by the first field of the expansion results. The target type defines how the target is executed. After the execution, the ErrExit option is applied with Env::apply_errexit.

§Target types and their semantics

§Absent target

If no fields resulted from the expansion, there is no target.

If the simple command has redirections and assignments, they are performed in a new subshell and the current shell environment, respectively.

If the redirections or assignments contain command substitutions, the exit status of the simple command is taken from that of the last executed command substitution. Otherwise, the exit status will be zero.

§Built-in

If the target is a built-in, the following steps are performed in the current shell environment.

First, if there are redirections, they are performed.

Next, if there are assignments, a temporary context is created to contain the assignment results. The context, as well as the assigned variables, are discarded when the execution finishes. If the target is a regular built-in, the variables are exported.

Lastly, the built-in is executed by calling its body with the remaining fields passed as arguments.

§Function

If the target is a function, redirections are performed in the same way as a regular built-in. Then, assignments are performed in a volatile variable context and exported. Next, a regular context is pushed to allow local variable assignment during the function execution. The remaining fields not used in the command search become positional parameters in the new context. After executing the function body, the contexts are popped.

If the execution results in a Divert::Return, it is consumed, and its associated exit status, if any, is set as the exit status of the simple command.

§External utility

If the target is an external utility, a subshell is created. Redirections and assignments, if any, are performed in the subshell. The assigned variables are exported. The subshell calls the execve function to invoke the external utility with all the fields passed as arguments.

If execve fails with an ENOEXEC error, it is re-called with the current executable file so that the restarted shell executes the external utility as a shell script.

§Target not found

If the command search could not find a valid target, the execution proceeds in the same manner as an external utility except that it does not call execve and performs error handling as if it failed with ENOENT.

§Redirections

Redirections are performed in the order of appearance. The file descriptors modified by the redirections are restored after the target has finished except for external utilities executed in a subshell.

§Assignments

Assignments are performed in the order of appearance. For each assignment, the value is expanded and assigned to the variable.

§Errors

§Expansion errors

If there is an error during the expansion, the execution aborts with a non-zero exit status after printing an error message to the standard error.

Expansion errors may also occur when expanding an assignment value or a redirection operand.

§Redirection errors

Any error happening in redirections causes the execution to abort with a non-zero exit status after printing an error message to the standard error.

§Assignment errors

If an assignment tries to overwrite a read-only variable, the execution aborts with a non-zero exit status after printing an error message to the standard error.

§External utility invocation failure

If the external utility could not be called, the subshell exits after printing an error message to the standard error.

§Portability

POSIX does not define the exit status when the execve system call fails for a reason other than ENOEXEC. In this implementation, the exit status is 127 for ENOENT and ENOTDIR and 126 for others.

POSIX leaves many aspects of the simple command execution unspecified. The detail semantics may differ in other shell implementations.

Source§

async fn execute(&self, env: &mut Env) -> Result

Implementors§