diff --git a/ChangeLog b/ChangeLog index 4bb294fab..0ec383b3a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2010-09-14 Vladimir Serbinenko + + Fix incorrect echo options handling. + Reported by: Yves Blusseau. + + * include/grub/command.h (grub_command_flags_t): New flags + GRUB_COMMAND_ACCEPT_DASH and GRUB_COMMAND_OPTIONS_AT_START. + * grub-core/lib/arg.c (grub_arg_parse): Handle new flags. + * grub-core/commands/echo.c (GRUB_MOD_INIT): Use new flags. + 2010-09-14 Vladimir Serbinenko * include/grub/command.h (GRUB_COMMAND_FLAG_CMDLINE): Removed. All diff --git a/grub-core/commands/echo.c b/grub-core/commands/echo.c index 6d69bc3f0..13bc1c3fd 100644 --- a/grub-core/commands/echo.c +++ b/grub-core/commands/echo.c @@ -113,7 +113,9 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(echo) { - cmd = grub_register_extcmd ("echo", grub_cmd_echo, 0, + cmd = grub_register_extcmd ("echo", grub_cmd_echo, + GRUB_COMMAND_ACCEPT_DASH + | GRUB_COMMAND_OPTIONS_AT_START, N_("[-e|-n] STRING"), N_("Display a line of text."), options); } diff --git a/grub-core/lib/arg.c b/grub-core/lib/arg.c index f3352520b..f487de7ad 100644 --- a/grub-core/lib/arg.c +++ b/grub-core/lib/arg.c @@ -231,7 +231,6 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, { int curarg; int arglen; - int complete = 0; char **argl = 0; int num = 0; auto grub_err_t add_arg (char *s); @@ -258,7 +257,8 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, char *option = 0; /* No option is used. */ - if (arg[0] != '-' || grub_strlen (arg) == 1) + if ((num && GRUB_COMMAND_OPTIONS_AT_START) + || arg[0] != '-' || grub_strlen (arg) == 1) { if (add_arg (arg) != 0) goto fail; @@ -269,11 +269,28 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, /* One or more short options. */ if (arg[1] != '-') { - char *curshort = arg + 1; + char *curshort; + + if (cmd->cmd->flags & GRUB_COMMAND_ACCEPT_DASH) + { + for (curshort = arg + 1; *curshort; curshort++) + if (!find_short (cmd->options, *curshort)) + break; + + if (*curshort) + { + if (add_arg (arg) != 0) + goto fail; + continue; + } + } + + curshort = arg + 1; while (1) { opt = find_short (cmd->options, *curshort); + if (! opt) { grub_error (GRUB_ERR_BAD_ARGUMENT, @@ -330,6 +347,14 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, } opt = find_long (cmd->options, arg + 2, arglen); + + if (!opt && (cmd->cmd->flags & GRUB_COMMAND_ACCEPT_DASH)) + { + if (add_arg (arg) != 0) + goto fail; + continue; + } + if (! opt) { grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown argument `%s'", arg); @@ -398,13 +423,12 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, } } - complete = 1; - *args = argl; *argnum = num; + return 1; fail: - return complete; + return 0; } struct grub_arg_list* diff --git a/include/grub/command.h b/include/grub/command.h index 31b639548..3b7bf0a10 100644 --- a/include/grub/command.h +++ b/include/grub/command.h @@ -30,7 +30,11 @@ typedef enum grub_command_flags /* This is an dynamic command. */ GRUB_COMMAND_FLAG_DYNCMD = 0x20, /* This command accepts block arguments. */ - GRUB_COMMAND_FLAG_BLOCKS = 0x40 + GRUB_COMMAND_FLAG_BLOCKS = 0x40, + /* This command accepts unknown arguments as direct parameters. */ + GRUB_COMMAND_ACCEPT_DASH = 0x80, + /* This command accepts only options preceding direct arguments. */ + GRUB_COMMAND_OPTIONS_AT_START = 0x100, } grub_command_flags_t; struct grub_command;