iPXE
Data Structures | Functions | Variables
exec.c File Reference

Command execution. More...

#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
#include <assert.h>
#include <ipxe/tables.h>
#include <ipxe/command.h>
#include <ipxe/parseopt.h>
#include <ipxe/settings.h>
#include <ipxe/shell.h>

Go to the source code of this file.

Data Structures

struct  echo_options
 "echo" options More...
struct  exit_options
 "exit" options More...
struct  isset_options
 "isset" options More...
struct  iseq_options
 "iseq" options More...
struct  sleep_options
 "sleep" options More...

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
int execv (const char *command, char *const argv[])
 Execute command.
static int split_command (char *command, char **tokens)
 Split command line into tokens.
static int process_on_success (int rc)
 Process next command only if previous command succeeded.
static int process_on_failure (int rc)
 Process next command only if previous command failed.
static int process_always (int rc __unused)
 Process next command regardless of status from previous command.
static int command_terminator (char **tokens, int(**process_next)(int rc))
 Find command terminator.
void shell_stop (int stop)
 Set shell stop state.
int shell_stopped (int stop)
 Test and consume shell stop state.
static int expand_tokens (int argc, char **tokens, char **argv)
 Expand settings within a token list.
static void free_tokens (char **argv)
 Free an expanded token list.
int system (const char *command)
 Execute command line.
char * concat_args (char **args)
 Concatenate arguments.
static int echo_exec (int argc, char **argv)
 "echo" command
static int exit_exec (int argc, char **argv)
 "exit" command
static int isset_exec (int argc, char **argv)
 "isset" command
static int iseq_exec (int argc, char **argv)
 "iseq" command
static int sleep_exec (int argc, char **argv)
 "sleep" command

Variables

static int stop_state
 Shell stop state.
static struct option_descriptor echo_opts []
 "echo" option list
static struct command_descriptor echo_cmd
 "echo" command descriptor
struct command echo_command __command
 "echo" command
static struct option_descriptor exit_opts [] = {}
 "exit" option list
static struct command_descriptor exit_cmd
 "exit" command descriptor
static struct option_descriptor isset_opts [] = {}
 "isset" option list
static struct command_descriptor isset_cmd
 "isset" command descriptor
static struct option_descriptor iseq_opts [] = {}
 "iseq" option list
static struct command_descriptor iseq_cmd
 "iseq" command descriptor
static struct option_descriptor sleep_opts [] = {}
 "sleep" option list
static struct command_descriptor sleep_cmd
 "sleep" command descriptor

Detailed Description

Command execution.

Definition in file exec.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
int execv ( const char *  command,
char *const  argv[] 
)

Execute command.

Parameters:
commandCommand name
argvArgument list
Return values:
rcReturn status code

Execute the named command. Unlike a traditional POSIX execv(), this function returns the exit status of the command.

Definition at line 60 of file exec.c.

References cmd, COMMANDS, DBG, done, EINVAL, ENOEXEC, errno, command::exec, for_each_table_entry, command::name, NULL, printf(), rc, reset_getopt(), and strcmp().

Referenced by system(), and time_exec().

                                                       {
        struct command *cmd;
        int argc;
        int rc;

        /* Count number of arguments */
        for ( argc = 0 ; argv[argc] ; argc++ ) {}

        /* An empty command is deemed to do nothing, successfully */
        if ( command == NULL ) {
                rc = 0;
                goto done;
        }

        /* Sanity checks */
        if ( argc == 0 ) {
                DBG ( "%s: empty argument list\n", command );
                rc = -EINVAL;
                goto done;
        }

        /* Reset getopt() library ready for use by the command.  This
         * is an artefact of the POSIX getopt() API within the context
         * of Etherboot; see the documentation for reset_getopt() for
         * details.
         */
        reset_getopt();

        /* Hand off to command implementation */
        for_each_table_entry ( cmd, COMMANDS ) {
                if ( strcmp ( command, cmd->name ) == 0 ) {
                        rc = cmd->exec ( argc, ( char ** ) argv );
                        goto done;
                }
        }

        printf ( "%s: command not found\n", command );
        rc = -ENOEXEC;

 done:
        /* Store error number, if an error occurred */
        if ( rc ) {
                errno = rc;
                if ( errno < 0 )
                        errno = -errno;
        }

        return rc;
}
static int split_command ( char *  command,
char **  tokens 
) [static]

Split command line into tokens.

Parameters:
commandCommand line
tokensToken list to populate, or NULL
Return values:
countNumber of tokens

Splits the command line into whitespace-delimited tokens. If tokens is non-NULL, any whitespace in the command line will be replaced with NULs.

Definition at line 121 of file exec.c.

References command, count, and isspace().

Referenced by system().

                                                          {
        int count = 0;

        while ( 1 ) {
                /* Skip over any whitespace / convert to NUL */
                while ( isspace ( *command ) ) {
                        if ( tokens )
                                *command = '\0';
                        command++;
                }
                /* Check for end of line */
                if ( ! *command )
                        break;
                /* We have found the start of the next argument */
                if ( tokens )
                        tokens[count] = command;
                count++;
                /* Skip to start of next whitespace, if any */
                while ( *command && ! isspace ( *command ) ) {
                        command++;
                }
        }
        return count;
}
static int process_on_success ( int  rc) [static]

Process next command only if previous command succeeded.

Parameters:
rcStatus of previous command
Return values:
processProcess next command

Definition at line 152 of file exec.c.

Referenced by command_terminator().

                                         {
        return ( rc == 0 );
}
static int process_on_failure ( int  rc) [static]

Process next command only if previous command failed.

Parameters:
rcStatus of previous command
Return values:
processProcess next command

Definition at line 162 of file exec.c.

Referenced by command_terminator().

                                         {
        return ( rc != 0 );
}
static int process_always ( int rc  __unused) [static]

Process next command regardless of status from previous command.

Parameters:
rcStatus of previous command
Return values:
processProcess next command

Definition at line 172 of file exec.c.

Referenced by command_terminator().

                                              {
        return 1;
}
static int command_terminator ( char **  tokens,
int(**)(int rc process_next 
) [static]

Find command terminator.

Parameters:
tokensToken list
Return values:
process_next"Should next command be processed?" function
argcArgument count

Definition at line 183 of file exec.c.

References NULL, process_always(), process_on_failure(), process_on_success(), and strcmp().

Referenced by system().

                                                                    {
        unsigned int i;

        /* Find first terminating token */
        for ( i = 0 ; tokens[i] ; i++ ) {
                if ( tokens[i][0] == '#' ) {
                        /* Start of a comment */
                        break;
                } else if ( strcmp ( tokens[i], "||" ) == 0 ) {
                        /* Short-circuit logical OR */
                        *process_next = process_on_failure;
                        return i;
                } else if ( strcmp ( tokens[i], "&&" ) == 0 ) {
                        /* Short-circuit logical AND */
                        *process_next = process_on_success;
                        return i;
                } else if ( strcmp ( tokens[i], ";" ) == 0 ) {
                        /* Process next command unconditionally */
                        *process_next = process_always;
                        return i;
                }
        }

        /* End of token list */
        *process_next = NULL;
        return i;
}
void shell_stop ( int  stop)

Set shell stop state.

Parameters:
stopShell stop state

Definition at line 217 of file exec.c.

References stop_state.

Referenced by exit_exec(), goto_exec(), and imgexec().

                             {
        stop_state = stop;
}
int shell_stopped ( int  stop)

Test and consume shell stop state.

Parameters:
stopShell stop state to consume
stoppedShell had been stopped

Definition at line 227 of file exec.c.

References stop_state.

Referenced by shell(), system(), and terminate_on_exit_or_failure().

                               {
        int stopped;

        /* Test to see if we need to stop */
        stopped = ( stop_state >= stop );

        /* Consume stop state */
        if ( stop_state <= stop )
                stop_state = 0;

        return stopped;
}
static int expand_tokens ( int  argc,
char **  tokens,
char **  argv 
) [static]

Expand settings within a token list.

Parameters:
argcArgument count
tokensToken list
argvArgument list to fill in
Return values:
rcReturn status code

Definition at line 248 of file exec.c.

References assert, ENOMEM, expand_settings(), free, and NULL.

Referenced by system().

                                                                  {
        int i;

        /* Expand each token in turn */
        for ( i = 0 ; i < argc ; i++ ) {
                argv[i] = expand_settings ( tokens[i] );
                if ( ! argv[i] )
                        goto err_expand_settings;
        }

        return 0;

 err_expand_settings:
        assert ( argv[i] == NULL );
        for ( ; i >= 0 ; i-- )
                free ( argv[i] );
        return -ENOMEM;
}
static void free_tokens ( char **  argv) [static]

Free an expanded token list.

Parameters:
argvArgument list

Definition at line 272 of file exec.c.

References free.

Referenced by system().

                                        {

        /* Free each expanded argument */
        while ( *argv )
                free ( *(argv++) );
}
int system ( const char *  command)

Execute command line.

Parameters:
commandCommand line
Return values:
rcReturn status code

Execute the named command and arguments.

Definition at line 287 of file exec.c.

References command_terminator(), count, ENOMEM, execv(), expand_tokens(), free, free_tokens(), NULL, rc, SHELL_STOP_COMMAND, shell_stopped(), split_command(), and strdup().

                                   {
        int count = split_command ( ( char * ) command, NULL );
        char *all_tokens[ count + 1 ];
        int ( * process_next ) ( int rc );
        char *command_copy;
        char **tokens;
        int argc;
        int process;
        int rc = 0;

        /* Create modifiable copy of command */
        command_copy = strdup ( command );
        if ( ! command_copy )
                return -ENOMEM;

        /* Split command into tokens */
        split_command ( command_copy, all_tokens );
        all_tokens[count] = NULL;

        /* Process individual commands */
        process = 1;
        for ( tokens = all_tokens ; ; tokens += ( argc + 1 ) ) {

                /* Find command terminator */
                argc = command_terminator ( tokens, &process_next );

                /* Expand tokens and execute command */
                if ( process ) {
                        char *argv[ argc + 1 ];

                        /* Expand tokens */
                        if ( ( rc = expand_tokens ( argc, tokens, argv ) ) != 0)
                                break;
                        argv[argc] = NULL;

                        /* Execute command */
                        rc = execv ( argv[0], argv );

                        /* Free tokens */
                        free_tokens ( argv );
                }

                /* Stop processing, if applicable */
                if ( shell_stopped ( SHELL_STOP_COMMAND ) )
                        break;

                /* Stop processing if we have reached the end of the
                 * command.
                 */
                if ( ! process_next )
                        break;

                /* Determine whether or not to process next command */
                process = process_next ( rc );
        }

        /* Free modified copy of command */
        free ( command_copy );

        return rc;
}
char* concat_args ( char **  args)

Concatenate arguments.

Parameters:
argsArgument list (NULL-terminated)
Return values:
stringConcatenated arguments

The returned string is allocated with malloc(). The caller is responsible for eventually free()ing this string.

Definition at line 358 of file exec.c.

References assert, len, NULL, sprintf, string, strlen(), and zalloc().

Referenced by echo_exec(), imgsingle_exec(), item_exec(), menu_exec(), param_exec(), prompt_exec(), and set_value().

                                   {
        char **arg;
        size_t len;
        char *string;
        char *ptr;

        /* Calculate total string length */
        len = 1 /* NUL */;
        for ( arg = args ; *arg ; arg++ )
                len += ( 1 /* possible space */ + strlen ( *arg ) );

        /* Allocate string */
        string = zalloc ( len );
        if ( ! string )
                return NULL;

        /* Populate string */
        ptr = string;
        for ( arg = args ; *arg ; arg++ ) {
                ptr += sprintf ( ptr, "%s%s",
                                 ( ( arg == args ) ? "" : " " ), *arg );
        }
        assert ( ptr < ( string + len ) );

        return string;
}
static int echo_exec ( int  argc,
char **  argv 
) [static]

"echo" command

Parameters:
argcArgument count
argvArgument list
Return values:
rcReturn status code

Definition at line 409 of file exec.c.

References concat_args(), ENOMEM, free, echo_options::no_newline, optind, parse_options(), printf(), and rc.

                                               {
        struct echo_options opts;
        char *text;
        int rc;

        /* Parse options */
        if ( ( rc = parse_options ( argc, argv, &echo_cmd, &opts ) ) != 0 )
                return rc;

        /* Parse text */
        text = concat_args ( &argv[optind] );
        if ( ! text )
                return -ENOMEM;

        /* Print text */
        printf ( "%s%s", text, ( opts.no_newline ? "" : "\n" ) );

        free ( text );
        return 0;
}
static int exit_exec ( int  argc,
char **  argv 
) [static]

"exit" command

Parameters:
argcArgument count
argvArgument list
Return values:
rcReturn status code

Definition at line 453 of file exec.c.

References optind, parse_integer(), parse_options(), rc, shell_stop(), and SHELL_STOP_COMMAND_SEQUENCE.

                                               {
        struct exit_options opts;
        unsigned int exit_code = 0;
        int rc;

        /* Parse options */
        if ( ( rc = parse_options ( argc, argv, &exit_cmd, &opts ) ) != 0 )
                return rc;

        /* Parse exit status, if present */
        if ( optind != argc ) {
                if ( ( rc = parse_integer ( argv[optind], &exit_code ) ) != 0 )
                        return rc;
        }

        /* Stop shell processing */
        shell_stop ( SHELL_STOP_COMMAND_SEQUENCE );

        return exit_code;
}
static int isset_exec ( int  argc,
char **  argv 
) [static]

"isset" command

Parameters:
argcArgument count
argvArgument list
Return values:
rcReturn status code

Definition at line 497 of file exec.c.

References ENOENT, optind, parse_options(), and rc.

                                                {
        struct isset_options opts;
        int rc;

        /* Parse options */
        if ( ( rc = parse_options ( argc, argv, &isset_cmd, &opts ) ) != 0 )
                return rc;

        /* Return success iff argument is non-empty */
        return ( argv[optind][0] ? 0 : -ENOENT );
}
static int iseq_exec ( int  argc,
char **  argv 
) [static]

"iseq" command

Parameters:
argcArgument count
argvArgument list
Return values:
rcReturn status code

Definition at line 533 of file exec.c.

References ERANGE, optind, parse_options(), rc, and strcmp().

                                               {
        struct iseq_options opts;
        int rc;

        /* Parse options */
        if ( ( rc = parse_options ( argc, argv, &iseq_cmd, &opts ) ) != 0 )
                return rc;

        /* Return success iff arguments are equal */
        return ( ( strcmp ( argv[optind], argv[ optind + 1 ] ) == 0 ) ?
                 0 : -ERANGE );
}
static int sleep_exec ( int  argc,
char **  argv 
) [static]

"sleep" command

Parameters:
argcArgument count
argvArgument list
Return values:
rcReturn status code

Definition at line 569 of file exec.c.

References ECANCELED, optind, parse_integer(), parse_options(), rc, seconds, and sleep().

                                                {
        struct sleep_options opts;
        unsigned int seconds;
        int rc;

        /* Parse options */
        if ( ( rc = parse_options ( argc, argv, &sleep_cmd, &opts ) ) != 0 )
                return rc;

        /* Parse number of seconds */
        if ( ( rc = parse_integer ( argv[optind], &seconds ) ) != 0 )
                return rc;

        /* Delay for specified number of seconds */
        if ( sleep ( seconds ) != 0 )
                return -ECANCELED;

        return 0;
}

Variable Documentation

int stop_state [static]

Shell stop state.

Definition at line 48 of file exec.c.

Referenced by shell_stop(), and shell_stopped().

struct option_descriptor echo_opts[] [static]
Initial value:
 {
        OPTION_DESC ( "n", 'n', no_argument,
                      struct echo_options, no_newline, parse_flag ),
}

"echo" option list

Definition at line 392 of file exec.c.

struct command_descriptor echo_cmd [static]
Initial value:

"echo" command descriptor

Definition at line 398 of file exec.c.

struct command sleep_command __command
Initial value:
 {
        .name = "echo",
        .exec = echo_exec,
}

"echo" command

"sleep" command

"iseq" command

"isset" command

"exit" command

Definition at line 431 of file exec.c.

struct option_descriptor exit_opts[] = {} [static]

"exit" option list

Definition at line 440 of file exec.c.

struct command_descriptor exit_cmd [static]
Initial value:
        COMMAND_DESC ( struct exit_options, exit_opts, 0, 1, "[<status>]" )

"exit" command descriptor

Definition at line 443 of file exec.c.

struct option_descriptor isset_opts[] = {} [static]

"isset" option list

Definition at line 484 of file exec.c.

struct command_descriptor isset_cmd [static]
Initial value:
        COMMAND_DESC ( struct isset_options, isset_opts, 1, 1, "<value>" )

"isset" command descriptor

Definition at line 487 of file exec.c.

struct option_descriptor iseq_opts[] = {} [static]

"iseq" option list

Definition at line 519 of file exec.c.

struct command_descriptor iseq_cmd [static]
Initial value:
        COMMAND_DESC ( struct iseq_options, iseq_opts, 2, 2,
                       "<value1> <value2>" )

"iseq" command descriptor

Definition at line 522 of file exec.c.

struct option_descriptor sleep_opts[] = {} [static]

"sleep" option list

Definition at line 556 of file exec.c.

struct command_descriptor sleep_cmd [static]
Initial value:
        COMMAND_DESC ( struct sleep_options, sleep_opts, 1, 1, "<seconds>" )

"sleep" command descriptor

Definition at line 559 of file exec.c.