This commit is contained in:
BVK Chaitanya 2010-07-29 22:52:09 +05:30
parent 8c184ffa19
commit 9e3e24e47f
4 changed files with 81 additions and 135 deletions

View file

@ -70,6 +70,15 @@ struct grub_script_argv
char **args; 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 /* A complete argument. It consists of a list of one or more `struct
grub_script_arg's. */ grub_script_arg's. */
struct grub_script_arglist struct grub_script_arglist
@ -225,12 +234,7 @@ struct grub_parser_param
void grub_script_argv_free (struct grub_script_argv *argv); void grub_script_argv_free (struct grub_script_argv *argv);
int grub_script_argv_next (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 (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_split_append (struct grub_script_argv *argv, char *s);
int grub_script_argv_expand (struct grub_script_argv *argv);
struct grub_script_arglist * struct grub_script_arglist *
grub_script_create_arglist (struct grub_parser_param *state); grub_script_create_arglist (struct grub_parser_param *state);

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 */

View file

@ -23,7 +23,6 @@
#include <grub/file.h> #include <grub/file.h>
#include <grub/device.h> #include <grub/device.h>
#include <grub/script_sh.h> #include <grub/script_sh.h>
#include <grub/wildcard.h>
#include <regex.h> #include <regex.h>
@ -63,12 +62,12 @@ static char* wildcard_escape (const char *s);
static char* wildcard_unescape (const char *s); static char* wildcard_unescape (const char *s);
static grub_err_t wildcard_expand (const char *s, char ***strs); 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, .expand = wildcard_expand,
.escape = wildcard_escape, .escape = wildcard_escape,
.unescape = wildcard_unescape .unescape = wildcard_unescape
}; };
struct grub_script_wildcard_translator *wildcard_translator = &translator;
void void
grub_script_argv_free (struct grub_script_argv *argv) grub_script_argv_free (struct grub_script_argv *argv)
@ -109,14 +108,9 @@ grub_script_argv_next (struct grub_script_argv *argv)
return 0; return 0;
} }
enum append_type { /* Append `s' to the last argument. */
APPEND_RAW, int
APPEND_ESCAPED, grub_script_argv_append (struct grub_script_argv *argv, const char *s)
APPEND_UNESCAPED
};
static int
append (struct grub_script_argv *argv, const char *s)
{ {
int a; int a;
int b; int b;
@ -139,44 +133,6 @@ append (struct grub_script_argv *argv, const char *s)
return 0; 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. */ /* Split `s' and append words as multiple arguments. */
int int
grub_script_argv_split_append (struct grub_script_argv *argv, char *s) 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; 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 ** static char **
merge (char **dest, char **ps) merge (char **dest, char **ps)
{ {

View file

@ -161,7 +161,7 @@ grub_script_env_set (const char *name, const char *val)
return grub_env_set (name, val); return grub_env_set (name, val);
} }
/* Expand arguments in ARGLIST into multiple arguments. */ /* Convert arguments in ARGLIST into ARGV form. */
static int static int
grub_script_arglist_to_argv (struct grub_script_arglist *arglist, grub_script_arglist_to_argv (struct grub_script_arglist *arglist,
struct grub_script_argv *argv) 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_arg *arg = 0;
struct grub_script_argv result = { 0, 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) for (; arglist && arglist->arg; arglist = arglist->next)
{ {
if (grub_script_argv_next (&result)) if (grub_script_argv_next (&result))
@ -196,7 +218,7 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist,
} }
else else
{ {
if (grub_script_argv_append_escaped (&result, values[i])) if (append (values[i], 1))
goto fail; goto fail;
} }
@ -224,8 +246,49 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist,
if (! result.args[result.argc - 1]) if (! result.args[result.argc - 1])
result.argc--; result.argc--;
if (grub_script_argv_expand (&result)) /* 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; 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; *argv = result;
return 0; return 0;