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

iPXE scripts More...

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <ipxe/command.h>
#include <ipxe/parseopt.h>
#include <ipxe/image.h>
#include <ipxe/shell.h>
#include <usr/prompt.h>
#include <ipxe/script.h>

Go to the source code of this file.

Data Structures

struct  goto_options
 "goto" options More...
struct  prompt_options
 "prompt" options More...

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static int process_script (struct image *image, int(*process_line)(struct image *image, size_t offset, const char *label, const char *command), int(*terminate)(int rc))
 Process script lines.
static int terminate_on_exit_or_failure (int rc)
 Terminate script processing on shell exit or command failure.
static int script_exec_line (struct image *image, size_t offset, const char *label __unused, const char *command)
 Execute script line.
static int script_exec (struct image *image)
 Execute script.
static int script_probe (struct image *image)
 Probe script image.
struct image_type script_image_type __image_type (PROBE_NORMAL)
 Script image type.
static int goto_find_label (struct image *image, size_t offset, const char *label, const char *command __unused)
 Check for presence of label.
static int terminate_on_label_found (int rc)
 Terminate script processing when label is found.
static int goto_exec (int argc, char **argv)
 "goto" command
static int prompt_exec (int argc, char **argv)
 "prompt" command

Variables

static size_t script_offset
 Offset within current script.
static struct option_descriptor goto_opts [] = {}
 "goto" option list
static struct command_descriptor goto_cmd
 "goto" command descriptor
static const char * goto_label
 Current "goto" label.
struct command goto_command __command
 "goto" command
static struct option_descriptor prompt_opts []
 "prompt" option list
static struct command_descriptor prompt_cmd
 "prompt" command descriptor

Detailed Description

iPXE scripts

Definition in file script.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static int process_script ( struct image image,
int(*)(struct image *image, size_t offset, const char *label, const char *command process_line,
int(*)(int rc terminate 
) [static]

Process script lines.

Parameters:
imageScript
process_lineLine processor
terminateTermination check
Return values:
rcReturn status code

Definition at line 61 of file script.c.

References command, copy_from_user(), image::data, EINVAL, ENOMEM, free, isspace(), image::len, len, memchr_user(), NULL, rc, realloc(), and script_offset.

Referenced by goto_exec(), and script_exec().

                                                             {
        size_t len = 0;
        char *line = NULL;
        size_t line_offset;
        char *label;
        char *command;
        off_t eol;
        size_t frag_len;
        char *tmp;
        int rc;

        /* Initialise script and line offsets */
        script_offset = 0;
        line_offset = 0;

        do {

                /* Find length of next line, excluding any terminating '\n' */
                eol = memchr_user ( image->data, script_offset, '\n',
                                    ( image->len - script_offset ) );
                if ( eol < 0 )
                        eol = image->len;
                frag_len = ( eol - script_offset );

                /* Allocate buffer for line */
                tmp = realloc ( line, ( len + frag_len + 1 /* NUL */ ) );
                if ( ! tmp ) {
                        rc = -ENOMEM;
                        goto err_alloc;
                }
                line = tmp;

                /* Copy line */
                copy_from_user ( ( line + len ), image->data, script_offset,
                                 frag_len );
                len += frag_len;

                /* Move to next line in script */
                script_offset += ( frag_len + 1 );

                /* Strip trailing CR, if present */
                if ( len && ( line[ len - 1 ] == '\r' ) )
                        len--;

                /* Handle backslash continuations */
                if ( len && ( line[ len - 1 ] == '\\' ) ) {
                        len--;
                        rc = -EINVAL;
                        continue;
                }

                /* Terminate line */
                line[len] = '\0';

                /* Split line into (optional) label and command */
                command = line;
                while ( isspace ( *command ) )
                        command++;
                if ( *command == ':' ) {
                        label = ++command;
                        while ( *command && ! isspace ( *command ) )
                                command++;
                        if ( *command )
                                *(command++) = '\0';
                } else {
                        label = NULL;
                }

                /* Process line */
                rc = process_line ( image, line_offset, label, command );
                if ( terminate ( rc ) )
                        goto err_process;

                /* Free line */
                free ( line );
                line = NULL;
                len = 0;

                /* Update line offset */
                line_offset = script_offset;

        } while ( script_offset < image->len );

 err_process:
 err_alloc:
        free ( line );
        return rc;
}
static int terminate_on_exit_or_failure ( int  rc) [static]

Terminate script processing on shell exit or command failure.

Parameters:
rcLine processing status
Return values:
terminateTerminate script processing

Definition at line 161 of file script.c.

References SHELL_STOP_COMMAND_SEQUENCE, and shell_stopped().

Referenced by script_exec().

                                                   {

        return ( shell_stopped ( SHELL_STOP_COMMAND_SEQUENCE ) ||
                 ( rc != 0 ) );
}
static int script_exec_line ( struct image image,
size_t  offset,
const char *label  __unused,
const char *  command 
) [static]

Execute script line.

Parameters:
imageScript
offsetOffset within script
labelLabel, or NULL
commandCommand
Return values:
rcReturn status code

Definition at line 176 of file script.c.

References DBGC, rc, and system.

Referenced by script_exec().

                                                    {
        int rc;

        DBGC ( image, "[%04zx] $ %s\n", offset, command );

        /* Execute command */
        if ( ( rc = system ( command ) ) != 0 )
                return rc;

        return 0;
}
static int script_exec ( struct image image) [static]

Execute script.

Parameters:
imageScript
Return values:
rcReturn status code

Definition at line 196 of file script.c.

References process_script(), rc, register_image(), image::replacement, script_exec_line(), script_offset, terminate_on_exit_or_failure(), and unregister_image().

                                               {
        size_t saved_offset;
        int rc;

        /* Temporarily de-register image, so that a "boot" command
         * doesn't throw us into an execution loop.
         */
        unregister_image ( image );

        /* Preserve state of any currently-running script */
        saved_offset = script_offset;

        /* Process script */
        rc = process_script ( image, script_exec_line,
                              terminate_on_exit_or_failure );

        /* Restore saved state */
        script_offset = saved_offset;

        /* Re-register image (unless we have been replaced) */
        if ( ! image->replacement )
                register_image ( image );

        return rc;
}
static int script_probe ( struct image image) [static]

Probe script image.

Parameters:
imageScript
Return values:
rcReturn status code

Definition at line 228 of file script.c.

References copy_from_user(), image::data, DBGC, ENOEXEC, isspace(), image::len, linker_assert, memcmp(), and test.

                                                {
        static const char ipxe_magic[] = "#!ipxe";
        static const char gpxe_magic[] = "#!gpxe";
        linker_assert ( sizeof ( ipxe_magic ) == sizeof ( gpxe_magic ),
                        magic_size_mismatch );
        char test[ sizeof ( ipxe_magic ) - 1 /* NUL */
                   + 1 /* terminating space */];

        /* Sanity check */
        if ( image->len < sizeof ( test ) ) {
                DBGC ( image, "Too short to be a script\n" );
                return -ENOEXEC;
        }

        /* Check for magic signature */
        copy_from_user ( test, image->data, 0, sizeof ( test ) );
        if ( ! ( ( ( memcmp ( test, ipxe_magic, sizeof ( test ) - 1 ) == 0 ) ||
                   ( memcmp ( test, gpxe_magic, sizeof ( test ) - 1 ) == 0 )) &&
                 isspace ( test[ sizeof ( test ) - 1 ] ) ) ) {
                DBGC ( image, "Invalid magic signature\n" );
                return -ENOEXEC;
        }

        return 0;
}
struct image_type script_image_type __image_type ( PROBE_NORMAL  ) [read]

Script image type.

static int goto_find_label ( struct image image,
size_t  offset,
const char *  label,
const char *command  __unused 
) [static]

Check for presence of label.

Parameters:
imageScript
offsetOffset within script
labelLabel
commandCommand
Return values:
rcReturn status code

Definition at line 287 of file script.c.

References DBGC, ENOENT, offset, script_offset, and strcmp().

Referenced by goto_exec().

                                                                               {

        /* Check label exists */
        if ( ! label )
                return -ENOENT;

        /* Check label matches */
        if ( strcmp ( goto_label, label ) != 0 )
                return -ENOENT;

        /* Update script offset */
        script_offset = offset;
        DBGC ( image, "[%04zx] Gone to :%s\n", offset, label );

        return 0;
}
static int terminate_on_label_found ( int  rc) [static]

Terminate script processing when label is found.

Parameters:
rcLine processing status
Return values:
terminateTerminate script processing

Definition at line 311 of file script.c.

Referenced by goto_exec().

                                               {
        return ( rc == 0 );
}
static int goto_exec ( int  argc,
char **  argv 
) [static]

"goto" command

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

Definition at line 322 of file script.c.

References current_image, DBGC, ENOTTY, goto_find_label(), optind, parse_options(), printf(), process_script(), rc, script_offset, shell_stop(), SHELL_STOP_COMMAND, strerror(), and terminate_on_label_found().

                                               {
        struct goto_options opts;
        size_t saved_offset;
        int rc;

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

        /* Sanity check */
        if ( ! current_image ) {
                rc = -ENOTTY;
                printf ( "Not in a script: %s\n", strerror ( rc ) );
                return rc;
        }

        /* Parse label */
        goto_label = argv[optind];

        /* Find label */
        saved_offset = script_offset;
        if ( ( rc = process_script ( current_image, goto_find_label,
                                     terminate_on_label_found ) ) != 0 ) {
                script_offset = saved_offset;
                DBGC ( current_image, "[%04zx] No such label :%s\n",
                       script_offset, goto_label );
                return rc;
        }

        /* Terminate processing of current command */
        shell_stop ( SHELL_STOP_COMMAND );

        return 0;
}
static int prompt_exec ( int  argc,
char **  argv 
) [static]

"prompt" command

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

Definition at line 391 of file script.c.

References concat_args(), ENOMEM, free, prompt_options::key, optind, parse_options(), prompt(), rc, and prompt_options::timeout.

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

        /* Parse options */
        if ( ( rc = parse_options ( argc, argv, &prompt_cmd, &opts ) ) != 0 )
                goto err_parse;

        /* Parse prompt text */
        text = concat_args ( &argv[optind] );
        if ( ! text ) {
                rc = -ENOMEM;
                goto err_concat;
        }

        /* Display prompt and wait for key */
        if ( ( rc = prompt ( text, opts.timeout, opts.key ) ) != 0 )
                goto err_prompt;

        /* Free prompt text */
        free ( text );

        return 0;

 err_prompt:
        free ( text );
 err_concat:
 err_parse:
        return rc;
}

Variable Documentation

Offset within current script.

This is a global in order to allow goto_exec() to update the offset.

Definition at line 51 of file script.c.

Referenced by goto_exec(), goto_find_label(), process_script(), and script_exec().

struct option_descriptor goto_opts[] = {} [static]

"goto" option list

Definition at line 265 of file script.c.

struct command_descriptor goto_cmd [static]
Initial value:
        COMMAND_DESC ( struct goto_options, goto_opts, 1, 1, "<label>" )

"goto" command descriptor

Definition at line 268 of file script.c.

const char* goto_label [static]

Current "goto" label.

Valid only during goto_exec(). Consider this part of a closure.

Definition at line 276 of file script.c.

struct command prompt_command __command
Initial value:
 {
        .name = "goto",
        .exec = goto_exec,
}

"goto" command

"prompt" command

Definition at line 358 of file script.c.

struct option_descriptor prompt_opts[] [static]
Initial value:

"prompt" option list

Definition at line 372 of file script.c.

struct command_descriptor prompt_cmd [static]
Initial value:

"prompt" command descriptor

Definition at line 380 of file script.c.