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;