Fix few bugs and put a cleaner way to handle kernel command

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-05-12 17:51:22 +02:00
parent 092fd48a25
commit 68cc4355f8

View file

@ -27,24 +27,26 @@
#include <grub/normal.h> #include <grub/normal.h>
#include <grub/script_sh.h> #include <grub/script_sh.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/term.h>
struct legacy_command struct legacy_command
{ {
const char *name; const char *name;
const char *map; const char *map;
unsigned argc; unsigned argc;
enum { enum arg_type {
TYPE_VERBATIM, TYPE_VERBATIM,
TYPE_FORCE_OPTION, TYPE_FORCE_OPTION,
TYPE_NOAPM_OPTION, TYPE_NOAPM_OPTION,
TYPE_TYPE_OPTION,
TYPE_FILE, TYPE_FILE,
TYPE_PARTITION, TYPE_PARTITION,
TYPE_BOOL, TYPE_BOOL,
TYPE_INT TYPE_INT,
TYPE_REST_VERBATIM
} argt[3]; } argt[3];
enum { enum {
FLAG_IGNORE_REST = 1, FLAG_IGNORE_REST = 1
FLAG_ALL_VERBATIM = 2
} flags; } flags;
}; };
@ -85,7 +87,8 @@ struct legacy_command legacy_commands[] =
/* install unsupported. */ /* install unsupported. */
/* ioprobe unsupported. */ /* ioprobe unsupported. */
/* FIXME: implement command. */ /* FIXME: implement command. */
{"kernel", "legacy_kernel %s\n", 0, {}, FLAG_ALL_VERBATIM}, {"kernel", "legacy_kernel %s '%s' %s\n", 3, {TYPE_TYPE_OPTION, TYPE_FILE,
TYPE_REST_VERBATIM}, 0},
/* lock is handled separately. */ /* lock is handled separately. */
{"makeactive", "parttool '%s' boot+\n", 1, {TYPE_PARTITION}, 0}, {"makeactive", "parttool '%s' boot+\n", 1, {TYPE_PARTITION}, 0},
{"map", "drivemap '%s' '%s'\n", 2, {TYPE_PARTITION, TYPE_PARTITION}, {"map", "drivemap '%s' '%s'\n", 2, {TYPE_PARTITION, TYPE_PARTITION},
@ -116,6 +119,7 @@ struct legacy_command legacy_commands[] =
/* title is handled separately. */ /* title is handled separately. */
{"unhide", "parttool '%s' hidden-\n", 1, {TYPE_PARTITION}, 0}, {"unhide", "parttool '%s' hidden-\n", 1, {TYPE_PARTITION}, 0},
/* uppermem unsupported. */ /* uppermem unsupported. */
{"uuid", "search -u '%s'\n", 1, {TYPE_VERBATIM}, 0},
/* vbeprobe unsupported. */ /* vbeprobe unsupported. */
}; };
@ -139,6 +143,7 @@ escape (const char *in)
*outptr++ = *ptr; *outptr++ = *ptr;
} }
*outptr++ = 0;
return ret; return ret;
} }
@ -188,6 +193,27 @@ adjust_file (const char *in)
return ret; return ret;
} }
static int
is_option (enum arg_type opt, const char *curarg)
{
switch (opt)
{
case TYPE_NOAPM_OPTION:
return grub_strcmp (curarg, "--no-apm") == 0;
case TYPE_FORCE_OPTION:
return grub_strcmp (curarg, "--force") == 0;
case TYPE_TYPE_OPTION:
return grub_strcmp (curarg, "--type=netbsd") == 0
|| grub_strcmp (curarg, "--type=freebsd") == 0
|| grub_strcmp (curarg, "--type=openbsd") == 0
|| grub_strcmp (curarg, "--type=linux") == 0
|| grub_strcmp (curarg, "--type=biglinux") == 0
|| grub_strcmp (curarg, "--type=multiboot") == 0;
default:
return 0;
}
}
static char * static char *
legacy_parse (char *buf, char **entryname) legacy_parse (char *buf, char **entryname)
{ {
@ -197,7 +223,11 @@ legacy_parse (char *buf, char **entryname)
for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++);
if ((!*ptr || *ptr == '#') && entryname && *entryname) if ((!*ptr || *ptr == '#') && entryname && *entryname)
return buf; {
char *ret = grub_xasprintf ("%s\n", buf);
grub_free (buf);
return ret;
}
if (!*ptr || *ptr == '#') if (!*ptr || *ptr == '#')
{ {
grub_free (buf); grub_free (buf);
@ -234,51 +264,6 @@ legacy_parse (char *buf, char **entryname)
char *args[ARRAY_SIZE (legacy_commands[0].argt)]; char *args[ARRAY_SIZE (legacy_commands[0].argt)];
memset (args, 0, sizeof (args)); memset (args, 0, sizeof (args));
if (legacy_commands[cmdnum].flags & FLAG_ALL_VERBATIM)
{
char *arg0 = ptr, *outptr;
int overhead = 3;
while (*ptr)
{
char *curarg;
for (; grub_isspace (*ptr); ptr++);
curarg = ptr;
for (; *ptr && !grub_isspace (*ptr); ptr++)
if (*ptr == '\\' || *ptr == '\'')
overhead++;
if (ptr)
ptr++;
overhead += 3;
}
args[0] = grub_malloc (overhead + (ptr - arg0));
if (!args[0])
{
grub_free (buf);
return NULL;
}
ptr = arg0;
outptr = args[0];
while (*ptr)
{
char *curarg;
for (; grub_isspace (*ptr); ptr++);
curarg = ptr;
if (outptr != args[0])
*outptr++ = ' ';
*outptr++ = '\'';
for (; *ptr && !grub_isspace (*ptr); ptr++)
{
if (*ptr == '\\' || *ptr == '\'')
*outptr++ = '\\';
*outptr++ = *ptr;
}
*outptr++ = '\'';
if (ptr)
ptr++;
overhead += 3;
}
}
{ {
unsigned j = 0; unsigned j = 0;
for (i = 0; i < legacy_commands[cmdnum].argc; i++) for (i = 0; i < legacy_commands[cmdnum].argc; i++)
@ -294,7 +279,8 @@ legacy_parse (char *buf, char **entryname)
c = *cptr; c = *cptr;
*ptr = 0; *ptr = 0;
} }
ptr++; if (*ptr)
ptr++;
switch (legacy_commands[cmdnum].argt[i]) switch (legacy_commands[cmdnum].argt[i])
{ {
case TYPE_PARTITION: case TYPE_PARTITION:
@ -302,28 +288,65 @@ legacy_parse (char *buf, char **entryname)
args[j++] = adjust_file (curarg); args[j++] = adjust_file (curarg);
break; break;
case TYPE_REST_VERBATIM:
{
char *outptr, *outptr0;
int overhead = 3;
ptr = curarg;
while (*ptr)
{
for (; grub_isspace (*ptr); ptr++);
for (; *ptr && !grub_isspace (*ptr); ptr++)
if (*ptr == '\\' || *ptr == '\'')
overhead++;
if (*ptr)
ptr++;
overhead += 3;
}
outptr0 = args[j++] = grub_malloc (overhead + (ptr - curarg));
if (!outptr0)
{
grub_free (buf);
return NULL;
}
ptr = curarg;
outptr = outptr0;
while (*ptr)
{
for (; grub_isspace (*ptr); ptr++);
if (outptr != outptr0)
*outptr++ = ' ';
*outptr++ = '\'';
for (; *ptr && !grub_isspace (*ptr); ptr++)
{
if (*ptr == '\\' || *ptr == '\'')
*outptr++ = '\\';
*outptr++ = *ptr;
}
*outptr++ = '\'';
if (*ptr)
ptr++;
overhead += 3;
}
*outptr++ = 0;
}
break;
case TYPE_VERBATIM: case TYPE_VERBATIM:
args[j++] = escape (curarg); args[j++] = escape (curarg);
break; break;
case TYPE_FORCE_OPTION: case TYPE_FORCE_OPTION:
if (grub_strcmp (curarg, "--force") == 0)
{
args[j++] = grub_strdup ("--force");
break;
}
if (cptr)
*cptr = c;
ptr = curarg;
break;
case TYPE_NOAPM_OPTION: case TYPE_NOAPM_OPTION:
if (grub_strcmp (curarg, "--no-apm") == 0) case TYPE_TYPE_OPTION:
if (is_option (legacy_commands[cmdnum].argt[i], curarg))
{ {
args[j++] = grub_strdup ("--no-apm"); args[j++] = grub_strdup (curarg);
break; break;
} }
if (cptr) if (cptr)
*cptr = c; *cptr = c;
ptr = curarg; ptr = curarg;
args[j++] = "";
break; break;
case TYPE_INT: case TYPE_INT:
{ {
@ -448,7 +471,7 @@ legacy_file (const char *filename)
grub_free (parsed); grub_free (parsed);
return grub_errno; return grub_errno;
} }
grub_memcpy (entrysrc + grub_strlen (entrysrc), buf, grub_memcpy (entrysrc + grub_strlen (entrysrc), parsed,
grub_strlen (parsed) + 1); grub_strlen (parsed) + 1);
grub_free (parsed); grub_free (parsed);
parsed = NULL; parsed = NULL;