diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h index d79fc048a..1564799f6 100644 --- a/include/grub/script_sh.h +++ b/include/grub/script_sh.h @@ -70,6 +70,15 @@ struct grub_script_argv char **args; }; +/* Pluggable wildcard translator. */ +struct grub_script_wildcard_translator +{ + char *(*escape) (const char *str); + char *(*unescape) (const char *str); + grub_err_t (*expand) (const char *str, char ***expansions); +}; +extern struct grub_script_wildcard_translator *wildcard_translator; + /* A complete argument. It consists of a list of one or more `struct grub_script_arg's. */ struct grub_script_arglist @@ -225,12 +234,7 @@ struct grub_parser_param void grub_script_argv_free (struct grub_script_argv *argv); int grub_script_argv_next (struct grub_script_argv *argv); int grub_script_argv_append (struct grub_script_argv *argv, const char *s); -int grub_script_argv_append_escaped (struct grub_script_argv *argv, - const char *s); -int grub_script_argv_append_unescaped (struct grub_script_argv *argv, - const char *s); int grub_script_argv_split_append (struct grub_script_argv *argv, char *s); -int grub_script_argv_expand (struct grub_script_argv *argv); struct grub_script_arglist * grub_script_create_arglist (struct grub_parser_param *state); diff --git a/include/grub/wildcard.h b/include/grub/wildcard.h deleted file mode 100644 index 8157b9db6..000000000 --- a/include/grub/wildcard.h +++ /dev/null @@ -1,34 +0,0 @@ -/* wildcard.h */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2010 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#ifndef GRUB_WILDCARD_HEADER -#define GRUB_WILDCARD_HEADER - -/* Pluggable wildcard expansion engine. */ -struct grub_wildcard_translator -{ - char *(*escape) (const char *str); - char *(*unescape) (const char *str); - - grub_err_t (*expand) (const char *str, char ***expansions); - - struct grub_wildcard_translator *next; -}; - -#endif /* GRUB_WILDCARD_HEADER */ diff --git a/script/argv.c b/script/argv.c index 10e180457..3294a90ad 100644 --- a/script/argv.c +++ b/script/argv.c @@ -23,7 +23,6 @@ #include #include #include -#include #include @@ -63,12 +62,12 @@ static char* wildcard_escape (const char *s); static char* wildcard_unescape (const char *s); static grub_err_t wildcard_expand (const char *s, char ***strs); -static struct grub_wildcard_translator foo = { +static struct grub_script_wildcard_translator translator = { .expand = wildcard_expand, .escape = wildcard_escape, .unescape = wildcard_unescape }; - +struct grub_script_wildcard_translator *wildcard_translator = &translator; void grub_script_argv_free (struct grub_script_argv *argv) @@ -109,14 +108,9 @@ grub_script_argv_next (struct grub_script_argv *argv) return 0; } -enum append_type { - APPEND_RAW, - APPEND_ESCAPED, - APPEND_UNESCAPED -}; - -static int -append (struct grub_script_argv *argv, const char *s) +/* Append `s' to the last argument. */ +int +grub_script_argv_append (struct grub_script_argv *argv, const char *s) { int a; int b; @@ -139,44 +133,6 @@ append (struct grub_script_argv *argv, const char *s) return 0; } - -/* Append `s' to the last argument. */ -int -grub_script_argv_append (struct grub_script_argv *argv, const char *s) -{ - return append (argv, s); -} - -/* Append `s' to the last argument, but escape any shell regex ops. */ -int -grub_script_argv_append_escaped (struct grub_script_argv *argv, const char *s) -{ - int r; - char *p = wildcard_escape (s); - - if (! p) - return 1; - - r = append (argv, p); - grub_free (p); - return r; -} - -/* Append `s' to the last argument, but unescape any escaped shell regex ops. */ -int -grub_script_argv_append_unescaped (struct grub_script_argv *argv, const char *s) -{ - int r; - char *p = wildcard_unescape (s); - - if (! p) - return 1; - - r = append (argv, p); - grub_free (p); - return r; -} - /* Split `s' and append words as multiple arguments. */ int grub_script_argv_split_append (struct grub_script_argv *argv, char *s) @@ -208,49 +164,6 @@ grub_script_argv_split_append (struct grub_script_argv *argv, char *s) return errors; } -/* Expand `argv' as per shell expansion rules. */ -int -grub_script_argv_expand (struct grub_script_argv *argv) -{ - int i; - int j; - char *p; - char **expansions; - struct grub_script_argv result = { 0, 0 }; - - for (i = 0; argv->args[i]; i++) - { - expansions = 0; - if (wildcard_expand (argv->args[i], &expansions)) - goto fail; - - if (! expansions) - { - grub_script_argv_next (&result); - grub_script_argv_append_unescaped (&result, argv->args[i]); - } - else - { - for (j = 0; expansions[j]; j++) - { - grub_script_argv_next (&result); - grub_script_argv_append (&result, expansions[j]); - grub_free (expansions[j]); - } - grub_free (expansions); - } - } - - grub_script_argv_free (argv); - *argv = result; - return 0; - - fail: - - grub_script_argv_free (&result); - return 1; -} - static char ** merge (char **dest, char **ps) { diff --git a/script/execute.c b/script/execute.c index 47e47b6eb..a41719091 100644 --- a/script/execute.c +++ b/script/execute.c @@ -161,7 +161,7 @@ grub_script_env_set (const char *name, const char *val) return grub_env_set (name, val); } -/* Expand arguments in ARGLIST into multiple arguments. */ +/* Convert arguments in ARGLIST into ARGV form. */ static int grub_script_arglist_to_argv (struct grub_script_arglist *arglist, struct grub_script_argv *argv) @@ -171,6 +171,28 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist, struct grub_script_arg *arg = 0; struct grub_script_argv result = { 0, 0 }; + auto int append (char *s, int escape_type); + int append (char *s, int escape_type) + { + int r; + char *p = 0; + + if (! wildcard_translator || escape_type == 0) + return grub_script_argv_append (&result, s); + + if (escape_type > 0) + p = wildcard_translator->escape (s); + else if (escape_type < 0) + p = wildcard_translator->unescape (s); + + if (! p) + return 1; + + r = grub_script_argv_append (&result, p); + grub_free (p); + return r; + } + for (; arglist && arglist->arg; arglist = arglist->next) { if (grub_script_argv_next (&result)) @@ -196,7 +218,7 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist, } else { - if (grub_script_argv_append_escaped (&result, values[i])) + if (append (values[i], 1)) goto fail; } @@ -224,8 +246,49 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist, if (! result.args[result.argc - 1]) result.argc--; - if (grub_script_argv_expand (&result)) - goto fail; + /* Perform wildcard expansion. */ + + if (wildcard_translator) + { + int j; + int failed = 0; + char **expansions = 0; + struct grub_script_argv unexpanded = result; + + result.argc = 0; + result.args = 0; + for (i = 0; unexpanded.args[i]; i++) + { + if (wildcard_translator->expand (unexpanded.args[i], &expansions)) + { + grub_script_argv_free (&unexpanded); + goto fail; + } + + if (! expansions) + { + grub_script_argv_next (&result); + append (unexpanded.args[i], -1); + } + else + { + for (j = 0; expansions[j]; j++) + { + failed = (failed || grub_script_argv_next (&result) || + append (expansions[j], -1)); + grub_free (expansions[j]); + } + grub_free (expansions); + + if (failed) + { + grub_script_argv_free (&unexpanded); + goto fail; + } + } + } + grub_script_argv_free (&unexpanded); + } *argv = result; return 0;