--- /dev/null
+ AutoGen definitions Makefile.tpl;
+
+ library = {
+ name = libgrub.a;
+ cflags = '$(CFLAGS_GCRY)';
+ cppflags = '$(CPPFLAGS_GCRY)';
+
+ common_nodist = grub_script.tab.c;
+ common_nodist = grub_script.yy.c;
+ common_nodist = libgrub_a_init.c;
+ common_nodist = grub_script.yy.h;
+ common_nodist = grub_script.tab.h;
+
+ common = grub-core/gnulib/error.c;
+ common = grub-core/gnulib/fnmatch.c;
+ common = grub-core/gnulib/getdelim.c;
+ common = grub-core/gnulib/getline.c;
+ common = grub-core/gnulib/getopt1.c;
+ common = grub-core/gnulib/getopt.c;
+ common = grub-core/gnulib/progname.c;
+
+ common = util/misc.c;
+ common = grub-core/kern/misc.c;
+ common = grub-core/kern/emu/mm.c;
+ common = grub-core/kern/emu/misc.c;
+ common = grub-core/kern/emu/hostfs.c;
+ common = grub-core/kern/emu/getroot.c;
+ common = grub-core/kern/emu/hostdisk.c;
+
+ common = grub-core/commands/blocklist.c;
+ common = grub-core/commands/extcmd.c;
+ common = grub-core/commands/ls.c;
+ common = grub-core/disk/dmraid_nvidia.c;
+ common = grub-core/disk/host.c;
+ common = grub-core/disk/loopback.c;
+ common = grub-core/disk/lvm.c;
+ common = grub-core/disk/mdraid_linux.c;
+ common = grub-core/disk/raid5_recover.c;
+ common = grub-core/disk/raid6_recover.c;
+ common = grub-core/disk/raid.c;
+ common = grub-core/fs/affs.c;
+ common = grub-core/fs/afs_be.c;
+ common = grub-core/fs/afs.c;
+ common = grub-core/fs/befs_be.c;
+ common = grub-core/fs/befs.c;
+ common = grub-core/fs/cpio.c;
+ common = grub-core/fs/ext2.c;
+ common = grub-core/fs/fat.c;
+ common = grub-core/fs/fshelp.c;
+ common = grub-core/fs/hfs.c;
+ common = grub-core/fs/hfsplus.c;
+ common = grub-core/fs/iso9660.c;
+ common = grub-core/fs/jfs.c;
+ common = grub-core/fs/minix.c;
+ common = grub-core/fs/nilfs2.c;
+ common = grub-core/fs/ntfs.c;
+ common = grub-core/fs/ntfscomp.c;
+ common = grub-core/fs/reiserfs.c;
+ common = grub-core/fs/sfs.c;
+ common = grub-core/fs/tar.c;
+ common = grub-core/fs/udf.c;
+ common = grub-core/fs/ufs2.c;
+ common = grub-core/fs/ufs.c;
+ common = grub-core/fs/xfs.c;
+ common = grub-core/kern/command.c;
+ common = grub-core/kern/device.c;
+ common = grub-core/kern/disk.c;
+ common = grub-core/kern/env.c;
+ common = grub-core/kern/err.c;
+ common = grub-core/kern/file.c;
+ common = grub-core/kern/fs.c;
+ common = grub-core/kern/list.c;
+ common = grub-core/kern/partition.c;
+ common = grub-core/lib/arg.c;
+ common = grub-core/lib/crc.c;
+ common = grub-core/lib/crypto.c;
+ common = grub-core/lib/envblk.c;
+ common = grub-core/lib/hexdump.c;
+ common = grub-core/lib/libgcrypt-grub/cipher/sha512.c;
+ common = grub-core/lib/LzFind.c;
+ common = grub-core/lib/LzmaEnc.c;
+ common = grub-core/lib/pbkdf2.c;
+ common = grub-core/normal/datetime.c;
+ common = grub-core/normal/misc.c;
+ common = grub-core/partmap/acorn.c;
+ common = grub-core/partmap/amiga.c;
+ common = grub-core/partmap/apple.c;
+ common = grub-core/partmap/gpt.c;
+ common = grub-core/partmap/msdos.c;
+ common = grub-core/partmap/sun.c;
+ common = grub-core/script/function.c;
+ common = grub-core/script/lexer.c;
+ common = grub-core/script/main.c;
+ common = grub-core/script/script.c;
+ common = grub-core/script/argv.c;
+ };
+
+ program = {
+ name = grub-bin2h;
+ common = util/bin2h.c;
+ ldadd = libgrub.a;
+ ldflags = '$(LIBINTL) $(LIBDEVMAPPER)';
+ mansection = 1;
+ };
+
+ program = {
+ name = grub-mkimage;
+ mansection = 1;
+
+ common = util/grub-mkimage.c;
+ common = util/resolve.c;
+ extra_dist = util/grub-mkimagexx.c;
+
+ ldadd = libgrub.a;
+ ldflags = '$(LIBINTL) $(LIBDEVMAPPER)';
+ cppflags = '-DGRUB_PKGLIBROOTDIR=\"$(pkglibrootdir)\"';
+ };
+
+ program = {
+ name = grub-mkrelpath;
+ mansection = 1;
+
+ common = util/grub-mkrelpath.c;
+
+ ldadd = libgrub.a;
+ ldflags = '$(LIBINTL) $(LIBDEVMAPPER)';
+ };
+
+ program = {
+ name = grub-script-check;
+ mansection = 1;
+
+ common = util/grub-script-check.c;
+
+ ldadd = libgrub.a;
+ ldflags = '$(LIBINTL) $(LIBDEVMAPPER)';
+ };
+
+ program = {
+ name = grub-editenv;
+ mansection = 1;
+
+ common = util/grub-editenv.c;
+
+ ldadd = libgrub.a;
+ ldflags = '$(LIBINTL) $(LIBDEVMAPPER)';
+ };
+
+ program = {
+ name = grub-mkpasswd-pbkdf2;
+ mansection = 1;
+
+ common = util/grub-mkpasswd-pbkdf2.c;
+
+ ldadd = libgrub.a;
+ ldflags = '$(LIBINTL) $(LIBDEVMAPPER)';
+ cflags = '$(CFLAGS_GCRY)';
+ cppflags = '$(CPPFLAGS_GCRY)';
+ };
+
+ program = {
+ name = grub-macho2img;
+ mansection = 1;
+ common = util/grub-macho2img.c;
+ condition = COND_APPLE_CC;
+ };
+
+ program = {
+ name = grub-pe2elf;
+ mansection = 1;
+ common = util/grub-pe2elf.c;
+
+ ldadd = libgrub.a;
+ ldflags = '$(LIBINTL)';
+ condition = COND_GRUB_PE2ELF;
+ };
+
+ program = {
+ name = grub-fstest;
+ mansection = 1;
+ common = util/grub-fstest.c;
+
+ ldadd = libgrub.a;
+ ldflags = '$(LIBINTL) $(LIBDEVMAPPER)';
+ condition = COND_GRUB_FSTEST;
+ };
+
+ program = {
+ name = grub-mkfont;
+ mansection = 1;
+ common = util/grub-mkfont.c;
+ common = grub-core/unidata.c;
+
+ cflags = '$(freetype_cflags)';
+
+ ldadd = libgrub.a;
+ ldflags = '$(LIBINTL) $(LIBDEVMAPPER)';
+ ldflags = '$(freetype_libs)';
+ condition = COND_GRUB_MKFONT;
+ };
+
+ program = {
+ name = grub-mkdevicemap;
+ installdir = sbin;
+ mansection = 8;
+
+ common = util/grub-mkdevicemap.c;
+ common = util/deviceiter.c;
+ nosparc64 = util/devicemap.c;
+
+ sparc64_ieee1275 = util/ieee1275/ofpath.c;
+ sparc64_ieee1275 = util/ieee1275/devicemap.c;
+
+ ldadd = libgrub.a;
+ ldflags = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL)';
+ };
+
+ program = {
+ name = grub-probe;
+ installdir = sbin;
+ mansection = 8;
+ common = util/grub-probe.c;
+
+ ldadd = libgrub.a;
+ ldflags = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL)';
+ };
+
+ program = {
+ name = grub-setup;
+ installdir = sbin;
+ mansection = 8;
+ i386_pc = util/i386/pc/grub-setup.c;
+ i386_pc = util/raid.c;
+ i386_pc = util/lvm.c;
+
+ sparc64_ieee1275 = util/ieee1275/ofpath.c;
+ sparc64_ieee1275 = util/sparc64/ieee1275/grub-setup.c;
+ sparc64_ieee1275 = util/raid.c;
+ sparc64_ieee1275 = util/lvm.c;
+
+ ldadd = libgrub.a;
+ ldflags = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL)';
+
+ enable = i386_pc;
+ enable = sparc64_ieee1275;
+ };
+
+ program = {
+ name = grub-ofpathname;
+ installdir = sbin;
+ ieee1275 = util/ieee1275/grub-ofpathname.c;
+ ieee1275 = util/ieee1275/ofpath.c;
+
+ ldadd = libgrub.a;
+ enable = sparc64_ieee1275;
+ };
+
+ data = {
+ common = util/grub.d/README;
+ installdir = grubconf;
+ };
+
+ script = {
+ name = '00_header';
+ common = util/grub.d/00_header.in;
+ installdir = grubconf;
+ };
+
+ script = {
+ name = '10_windows';
+ common = util/grub.d/10_windows.in;
+ installdir = grubconf;
+ condition = COND_HOST_WINDOWS;
+ };
+
+ script = {
+ name = '10_hurd';
+ common = util/grub.d/10_hurd.in;
+ installdir = grubconf;
+ condition = COND_HOST_HURD;
+ };
+
+ script = {
+ name = '10_kfreebsd';
+ common = util/grub.d/10_kfreebsd.in;
+ installdir = grubconf;
+ condition = COND_HOST_KFREEBSD;
+ };
+
+ script = {
+ name = '10_netbsd';
+ common = util/grub.d/10_netbsd.in;
+ installdir = grubconf;
+ condition = COND_HOST_NETBSD;
+ };
+
+ script = {
+ name = '10_linux';
+ common = util/grub.d/10_linux.in;
+ installdir = grubconf;
+ condition = COND_HOST_LINUX;
+ };
+
+ script = {
+ name = '20_linux_xen';
+ common = util/grub.d/20_linux_xen.in;
+ installdir = grubconf;
+ condition = COND_HOST_LINUX;
+ };
+
+ script = {
+ name = '30_os-prober';
+ common = util/grub.d/30_os-prober.in;
+ installdir = grubconf;
+ };
+
+ script = {
+ name = '40_custom';
+ common = util/grub.d/40_custom.in;
+ installdir = grubconf;
+ };
+
+ script = {
+ name = '41_custom';
+ common = util/grub.d/41_custom.in;
+ installdir = grubconf;
+ };
+
+ script = {
+ mansection = 1;
+ name = grub-mkrescue;
+ x86_noieee1275 = util/grub-mkrescue.in;
+ powerpc_ieee1275 = util/powerpc/ieee1275/grub-mkrescue.in;
+ enable = i386_pc;
+ enable = x86_efi;
+ enable = i386_qemu;
+ enable = i386_coreboot;
+ enable = powerpc_ieee1275;
+ };
+
+ script = {
+ mansection = 8;
+ installdir = sbin;
+ name = grub-install;
+
+ mips = util/grub-install.in;
+ i386_noefi_noieee1275 = util/grub-install.in;
+
+ x86_efi = util/i386/efi/grub-install.in;
+ i386_ieee1275 = util/ieee1275/grub-install.in;
+ powerpc_ieee1275 = util/ieee1275/grub-install.in;
+
+ enable = x86;
+ enable = mips;
+ enable = powerpc_ieee1275;
+ };
+
+ script = {
+ name = grub-mkconfig;
+ common = util/grub-mkconfig.in;
+ mansection = 8;
+ installdir = sbin;
+ };
+
+ script = {
+ name = grub-set-default;
+ common = util/grub-set-default.in;
+ mansection = 8;
+ installdir = sbin;
+ };
+
+ script = {
+ name = grub-reboot;
+ common = util/grub-reboot.in;
+ mansection = 8;
+ installdir = sbin;
+ };
+
+ script = {
+ name = grub-mkconfig_lib;
+ common = util/grub-mkconfig_lib.in;
+ installdir = noinst;
+ };
+
+ script = {
+ name = update-grub_lib;
+ common = util/update-grub_lib.in;
+ installdir = noinst;
+ };
+
+ script = {
+ name = grub-shell;
+ common = tests/util/grub-shell.in;
+ installdir = noinst;
+ };
+
+ script = {
+ name = grub-shell-tester;
+ common = tests/util/grub-shell-tester.in;
+ installdir = noinst;
+ };
+
+ script = {
+ testcase;
+ name = example_scripted_test;
+ common = tests/example_scripted_test.in;
+ };
+
+ script = {
+ testcase;
+ name = example_grub_script_test;
+ common = tests/example_grub_script_test.in;
+ };
+
+ script = {
+ testcase;
+ name = grub_script_echo1;
+ common = tests/grub_script_echo1.in;
+ };
+
+ script = {
+ testcase;
+ name = grub_script_echo_keywords;
+ common = tests/grub_script_echo_keywords.in;
+ };
+
+ script = {
+ testcase;
+ name = grub_script_vars1;
+ common = tests/grub_script_vars1.in;
+ };
+
+ script = {
+ testcase;
+ name = grub_script_for1;
+ common = tests/grub_script_for1.in;
+ };
+
+ script = {
+ testcase;
+ name = grub_script_while1;
+ common = tests/grub_script_while1.in;
+ };
+
+ script = {
+ testcase;
+ name = grub_script_if;
+ common = tests/grub_script_if.in;
+ };
+
+ script = {
+ testcase;
+ name = grub_script_blanklines;
+ common = tests/grub_script_blanklines.in;
+ };
+
+ script = {
+ testcase;
+ name = grub_script_final_semicolon;
+ common = tests/grub_script_final_semicolon.in;
+ };
+
+ script = {
+ testcase;
+ name = grub_script_dollar;
+ common = tests/grub_script_dollar.in;
+ };
+
+ script = {
+ testcase;
+ name = grub_script_comments;
+ common = tests/grub_script_comments.in;
+ };
+
+ script = {
+ testcase;
+ name = grub_script_functions;
+ common = tests/grub_script_functions.in;
+ };
+
+ script = {
+ testcase;
+ name = grub_script_break;
+ common = tests/grub_script_break.in;
+ };
+
+ script = {
+ testcase;
+ name = grub_script_continue;
+ common = tests/grub_script_continue.in;
+ };
+
+ script = {
+ testcase;
+ name = grub_script_shift;
+ common = tests/grub_script_shift.in;
+ };
+
++script = {
++ testcase;
++ name = grub_script_setparams;
++ common = tests/grub_script_setparams.in;
++};
++
+ program = {
+ testcase;
+ name = example_unit_test;
+ common = tests/example_unit_test.c;
+ common = tests/lib/unit_test.c;
+ common = grub-core/kern/list.c;
+ common = grub-core/kern/misc.c;
+ common = grub-core/tests/lib/test.c;
+ cflags = -Wno-format;
+ ldadd = libgrub.a;
+ ldflags = '$(LIBDEVMAPPER)';
+ };
--- /dev/null
+ /* argv.c - methods for constructing argument vector */
+ /*
+ * 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/>.
+ */
+
+ #include <grub/mm.h>
+ #include <grub/script_sh.h>
+
+ /* Return nearest power of two that is >= v. */
+ static unsigned
+ round_up_exp (unsigned v)
+ {
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+
+ if (sizeof (v) > 4)
+ v |= v >> 32;
+
+ v++;
+ v += (v == 0);
+
+ return v;
+ }
+
+ void
+ grub_script_argv_free (struct grub_script_argv *argv)
+ {
+ unsigned i;
+
+ if (argv->args)
+ {
+ for (i = 0; i < argv->argc; i++)
+ grub_free (argv->args[i]);
+
+ grub_free (argv->args);
+ }
+
+ argv->argc = 0;
+ argv->args = 0;
+ }
+
++/* Make argv from argc, args pair. */
++int
++grub_script_argv_make (struct grub_script_argv *argv, int argc, char **args)
++{
++ int i;
++ struct grub_script_argv r = { 0, 0};
++
++ for (i = 0; i < argc; i++)
++ if (grub_script_argv_next (&r) || grub_script_argv_append (&r, args[i]))
++ {
++ grub_script_argv_free (&r);
++ return 1;
++ }
++ *argv = r;
++ return 0;
++}
++
+ /* Prepare for next argc. */
+ int
+ grub_script_argv_next (struct grub_script_argv *argv)
+ {
+ char **p = argv->args;
+
+ if (argv->args && argv->args[argv->argc - 1] == 0)
+ return 0;
+
+ p = grub_realloc (p, round_up_exp ((argv->argc + 2) * sizeof (char *)));
+ if (! p)
+ return 1;
+
+ argv->argc++;
+ argv->args = p;
+
+ if (argv->argc == 1)
+ argv->args[0] = 0;
+ argv->args[argv->argc] = 0;
+ return 0;
+ }
+
+ /* Append `s' to the last argument. */
+ int
+ grub_script_argv_append (struct grub_script_argv *argv, const char *s)
+ {
+ int a, b;
+ char *p = argv->args[argv->argc - 1];
+
+ if (! s)
+ return 0;
+
+ a = p ? grub_strlen (p) : 0;
+ b = grub_strlen (s);
+
+ p = grub_realloc (p, round_up_exp ((a + b + 1) * sizeof (char)));
+ if (! p)
+ return 1;
+
+ grub_strcpy (p + a, s);
+ argv->args[argv->argc - 1] = p;
+ return 0;
+ }
+
+ /* Split `s' and append words as multiple arguments. */
+ int
+ grub_script_argv_split_append (struct grub_script_argv *argv, char *s)
+ {
+ char ch;
+ char *p;
+ int errors = 0;
+
+ if (! s)
+ return 0;
+
+ while (! errors && *s)
+ {
+ p = s;
+ while (*s && ! grub_isspace (*s))
+ s++;
+
+ ch = *s;
+ *s = '\0';
+ errors += grub_script_argv_append (argv, p);
+ *s = ch;
+
+ while (*s && grub_isspace (*s))
+ s++;
+
+ if (*s)
+ errors += grub_script_argv_next (argv);
+ }
+ return errors;
+ }
--- /dev/null
- unsigned i;
-
+ /* execute.c -- Execute a GRUB script. */
+ /*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005,2007,2008,2009,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/>.
+ */
+
+ #include <grub/misc.h>
+ #include <grub/mm.h>
+ #include <grub/env.h>
+ #include <grub/script_sh.h>
+ #include <grub/command.h>
+ #include <grub/menu.h>
+ #include <grub/lib/arg.h>
+ #include <grub/normal.h>
+
+ /* Max digits for a char is 3 (0xFF is 255), similarly for an int it
+ is sizeof (int) * 3, and one extra for a possible -ve sign. */
+ #define ERRNO_DIGITS_MAX (sizeof (int) * 3 + 1)
+
+ static unsigned long is_continue;
+ static unsigned long active_loops;
+ static unsigned long active_breaks;
+
++#define GRUB_SCRIPT_SCOPE_MALLOCED 1
++#define GRUB_SCRIPT_SCOPE_ARGS_MALLOCED 2
++
+ /* Scope for grub script functions. */
+ struct grub_script_scope
+ {
++ unsigned flags;
++ unsigned shifts;
+ struct grub_script_argv argv;
+ };
+ static struct grub_script_scope *scope = 0;
+
++static void
++replace_scope (struct grub_script_scope *new_scope)
++{
++ if (scope)
++ {
++ scope->argv.argc += scope->shifts;
++ scope->argv.args -= scope->shifts;
++
++ if (scope->flags & GRUB_SCRIPT_SCOPE_ARGS_MALLOCED)
++ grub_script_argv_free (&scope->argv);
++
++ if (scope->flags & GRUB_SCRIPT_SCOPE_MALLOCED)
++ grub_free (scope);
++ }
++ scope = new_scope;
++}
++
+ grub_err_t
+ grub_script_break (grub_command_t cmd, int argc, char *argv[])
+ {
+ char *p = 0;
+ unsigned long count;
+
+ if (argc == 0)
+ count = 1;
+
+ else if ((argc > 1) || (count = grub_strtoul (argv[0], &p, 10)) == 0 ||
+ (*p != '\0'))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad break");
+
+ is_continue = grub_strcmp (cmd->name, "break") ? 1 : 0;
+ active_breaks = grub_min (active_loops, count);
+ return GRUB_ERR_NONE;
+ }
+
+ grub_err_t
+ grub_script_shift (grub_command_t cmd __attribute__((unused)),
+ int argc, char *argv[])
+ {
+ char *p = 0;
+ unsigned long n = 0;
+
+ if (! scope)
+ return GRUB_ERR_NONE;
+
+ if (argc == 0)
+ n = 1;
+
+ else if (argc > 1)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ else
+ {
+ n = grub_strtoul (argv[0], &p, 10);
+ if (*p != '\0')
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ if (n > scope->argv.argc)
+ return GRUB_ERR_BAD_ARGUMENT;
+
++ scope->shifts += n;
+ scope->argv.argc -= n;
+ scope->argv.args += n;
+ return GRUB_ERR_NONE;
+ }
+
++grub_err_t
++grub_script_setparams (grub_command_t cmd __attribute__((unused)),
++ int argc, char **args)
++{
++ struct grub_script_scope *new_scope;
++ struct grub_script_argv argv = { 0, 0 };
++
++ if (! scope)
++ return GRUB_ERR_INVALID_COMMAND;
++
++ new_scope = grub_malloc (sizeof (*new_scope));
++ if (! new_scope)
++ return grub_errno;
++
++ if (grub_script_argv_make (&argv, argc, args))
++ {
++ grub_free (new_scope);
++ return grub_errno;
++ }
++
++ new_scope->shifts = 0;
++ new_scope->argv = argv;
++ new_scope->flags = GRUB_SCRIPT_SCOPE_MALLOCED |
++ GRUB_SCRIPT_SCOPE_ARGS_MALLOCED;
++
++ replace_scope (new_scope);
++ return GRUB_ERR_NONE;
++}
++
+ static int
+ grub_env_special (const char *name)
+ {
+ if (grub_isdigit (name[0]) ||
+ grub_strcmp (name, "#") == 0 ||
+ grub_strcmp (name, "*") == 0 ||
+ grub_strcmp (name, "@") == 0)
+ return 1;
+ return 0;
+ }
+
+ static char **
+ grub_script_env_get (const char *name, grub_script_arg_type_t type)
+ {
++ unsigned i;
+ struct grub_script_argv result = { 0, 0 };
+
+ if (grub_script_argv_next (&result))
+ goto fail;
+
+ if (! grub_env_special (name))
+ {
+ char *v = grub_env_get (name);
+ if (v && v[0])
+ {
+ if (type == GRUB_SCRIPT_ARG_TYPE_VAR)
+ {
+ if (grub_script_argv_split_append (&result, v))
+ goto fail;
+ }
+ else
+ if (grub_script_argv_append (&result, v))
+ goto fail;
+ }
+ }
+ else if (! scope)
+ {
+ if (grub_script_argv_append (&result, 0))
+ goto fail;
+ }
+ else if (grub_strcmp (name, "#") == 0)
+ {
+ char buffer[ERRNO_DIGITS_MAX + 1];
+ grub_snprintf (buffer, sizeof (buffer), "%u", scope->argv.argc);
+ if (grub_script_argv_append (&result, buffer))
+ goto fail;
+ }
+ else if (grub_strcmp (name, "*") == 0)
+ {
- unsigned i;
-
+ for (i = 0; i < scope->argv.argc; i++)
+ if (type == GRUB_SCRIPT_ARG_TYPE_VAR)
+ {
+ if (i != 0 && grub_script_argv_next (&result))
+ goto fail;
+
+ if (grub_script_argv_split_append (&result, scope->argv.args[i]))
+ goto fail;
+ }
+ else
+ {
+ if (i != 0 && grub_script_argv_append (&result, " "))
+ goto fail;
+
+ if (grub_script_argv_append (&result, scope->argv.args[i]))
+ goto fail;
+ }
+ }
+ else if (grub_strcmp (name, "@") == 0)
+ {
- scope = old_scope;
+ for (i = 0; i < scope->argv.argc; i++)
+ {
+ if (i != 0 && grub_script_argv_next (&result))
+ goto fail;
+
+ if (type == GRUB_SCRIPT_ARG_TYPE_VAR)
+ {
+ if (grub_script_argv_split_append (&result, scope->argv.args[i]))
+ goto fail;
+ }
+ else
+ if (grub_script_argv_append (&result, scope->argv.args[i]))
+ goto fail;
+ }
+ }
+ else
+ {
+ unsigned long num = grub_strtoul (name, 0, 10);
+ if (num == 0)
+ ; /* XXX no file name, for now. */
+
+ else if (num <= scope->argv.argc)
+ {
+ if (type == GRUB_SCRIPT_ARG_TYPE_VAR)
+ {
+ if (grub_script_argv_split_append (&result,
+ scope->argv.args[num - 1]))
+ goto fail;
+ }
+ else
+ if (grub_script_argv_append (&result, scope->argv.args[num - 1]))
+ goto fail;
+ }
+ }
+
+ return result.args;
+
+ fail:
+
+ grub_script_argv_free (&result);
+ return 0;
+ }
+
+ static grub_err_t
+ grub_script_env_set (const char *name, const char *val)
+ {
+ if (grub_env_special (name))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad variable name");
+
+ return grub_env_set (name, val);
+ }
+
+ /* Expand arguments in ARGLIST into multiple arguments. */
+ static int
+ grub_script_arglist_to_argv (struct grub_script_arglist *arglist,
+ struct grub_script_argv *argv)
+ {
+ int i;
+ char **values = 0;
+ struct grub_script_arg *arg = 0;
+ struct grub_script_argv result = { 0, 0 };
+
+ for (; arglist && arglist->arg; arglist = arglist->next)
+ {
+ if (grub_script_argv_next (&result))
+ goto fail;
+
+ arg = arglist->arg;
+ while (arg)
+ {
+ switch (arg->type)
+ {
+ case GRUB_SCRIPT_ARG_TYPE_VAR:
+ case GRUB_SCRIPT_ARG_TYPE_DQVAR:
+ values = grub_script_env_get (arg->str, arg->type);
+ for (i = 0; values && values[i]; i++)
+ {
+ if (i != 0 && grub_script_argv_next (&result))
+ goto fail;
+
+ if (grub_script_argv_append (&result, values[i]))
+ goto fail;
+ }
+ grub_free (values);
+ break;
+
+ case GRUB_SCRIPT_ARG_TYPE_TEXT:
+ if (grub_strlen (arg->str) &&
+ grub_script_argv_append (&result, arg->str))
+ goto fail;
+ break;
+
+ case GRUB_SCRIPT_ARG_TYPE_DQSTR:
+ case GRUB_SCRIPT_ARG_TYPE_SQSTR:
+ if (grub_script_argv_append (&result, arg->str))
+ goto fail;
+ break;
+ }
+ arg = arg->next;
+ }
+ }
+
+ if (! result.args[result.argc - 1])
+ result.argc--;
+
+ *argv = result;
+ return 0;
+
+ fail:
+
+ grub_script_argv_free (&result);
+ return 1;
+ }
+
+ static grub_err_t
+ grub_script_execute_cmd (struct grub_script_cmd *cmd)
+ {
+ int ret;
+ char errnobuf[ERRNO_DIGITS_MAX + 1];
+
+ if (cmd == 0)
+ return 0;
+
+ ret = cmd->exec (cmd);
+
+ grub_snprintf (errnobuf, sizeof (errnobuf), "%d", ret);
+ grub_env_set ("?", errnobuf);
+ return ret;
+ }
+
+ /* Execute a function call. */
+ grub_err_t
+ grub_script_function_call (grub_script_function_t func, int argc, char **args)
+ {
+ grub_err_t ret = 0;
+ unsigned long loops = active_loops;
+ struct grub_script_scope *old_scope;
+ struct grub_script_scope new_scope;
+
+ active_loops = 0;
++ new_scope.flags = 0;
++ new_scope.shifts = 0;
+ new_scope.argv.argc = argc;
+ new_scope.argv.args = args;
+
+ old_scope = scope;
+ scope = &new_scope;
+
+ ret = grub_script_execute (func->func);
+
+ active_loops = loops;
++ replace_scope (old_scope); /* free any scopes by setparams */
+ return ret;
+ }
+
+ /* Execute a single command line. */
+ grub_err_t
+ grub_script_execute_cmdline (struct grub_script_cmd *cmd)
+ {
+ struct grub_script_cmdline *cmdline = (struct grub_script_cmdline *) cmd;
+ grub_command_t grubcmd;
+ grub_err_t ret = 0;
+ grub_script_function_t func = 0;
+ char errnobuf[18];
+ char *cmdname;
+ struct grub_script_argv argv = { 0, 0 };
+
+ /* Lookup the command. */
+ if (grub_script_arglist_to_argv (cmdline->arglist, &argv) || ! argv.args[0])
+ return grub_errno;
+
+ cmdname = argv.args[0];
+ grubcmd = grub_command_find (cmdname);
+ if (! grubcmd)
+ {
+ grub_errno = GRUB_ERR_NONE;
+
+ /* It's not a GRUB command, try all functions. */
+ func = grub_script_function_find (cmdname);
+ if (! func)
+ {
+ /* As a last resort, try if it is an assignment. */
+ char *assign = grub_strdup (cmdname);
+ char *eq = grub_strchr (assign, '=');
+
+ if (eq)
+ {
+ /* This was set because the command was not found. */
+ grub_errno = GRUB_ERR_NONE;
+
+ /* Create two strings and set the variable. */
+ *eq = '\0';
+ eq++;
+ grub_script_env_set (assign, eq);
+ }
+ grub_free (assign);
+
+ grub_snprintf (errnobuf, sizeof (errnobuf), "%d", grub_errno);
+ grub_script_env_set ("?", errnobuf);
+
+ grub_script_argv_free (&argv);
+ grub_print_error ();
+
+ return 0;
+ }
+ }
+
+ /* Execute the GRUB command or function. */
+ if (grubcmd)
+ ret = (grubcmd->func) (grubcmd, argv.argc - 1, argv.args + 1);
+ else
+ ret = grub_script_function_call (func, argv.argc - 1, argv.args + 1);
+
+ /* Free arguments. */
+ grub_script_argv_free (&argv);
+
+ if (grub_errno == GRUB_ERR_TEST_FAILURE)
+ grub_errno = GRUB_ERR_NONE;
+
+ grub_print_error ();
+
+ grub_snprintf (errnobuf, sizeof (errnobuf), "%d", ret);
+ grub_env_set ("?", errnobuf);
+
+ return ret;
+ }
+
+ /* Execute a block of one or more commands. */
+ grub_err_t
+ grub_script_execute_cmdlist (struct grub_script_cmd *list)
+ {
+ int ret = 0;
+ struct grub_script_cmd *cmd;
+
+ /* Loop over every command and execute it. */
+ for (cmd = list->next; cmd && ! active_breaks; cmd = cmd->next)
+ ret = grub_script_execute_cmd (cmd);
+
+ return ret;
+ }
+
+ /* Execute an if statement. */
+ grub_err_t
+ grub_script_execute_cmdif (struct grub_script_cmd *cmd)
+ {
+ struct grub_script_cmdif *cmdif = (struct grub_script_cmdif *) cmd;
+ char *result;
+
+ /* Check if the commands results in a true or a false. The value is
+ read from the env variable `?'. */
+ grub_script_execute_cmd (cmdif->exec_to_evaluate);
+ result = grub_env_get ("?");
+
+ grub_errno = GRUB_ERR_NONE;
+
+ /* Execute the `if' or the `else' part depending on the value of
+ `?'. */
+ if (result && ! grub_strcmp (result, "0"))
+ return grub_script_execute_cmd (cmdif->exec_on_true);
+ else
+ return grub_script_execute_cmd (cmdif->exec_on_false);
+ }
+
+ /* Execute a for statement. */
+ grub_err_t
+ grub_script_execute_cmdfor (struct grub_script_cmd *cmd)
+ {
+ unsigned i;
+ grub_err_t result;
+ struct grub_script_argv argv = { 0, 0 };
+
+ struct grub_script_cmdfor *cmdfor = (struct grub_script_cmdfor *) cmd;
+
+ if (grub_script_arglist_to_argv (cmdfor->words, &argv))
+ return grub_errno;
+
+ active_loops++;
+ result = 0;
+ for (i = 0; i < argv.argc; i++)
+ {
+ if (is_continue && active_breaks == 1)
+ active_breaks = 0;
+
+ if (! active_breaks)
+ {
+ grub_script_env_set (cmdfor->name->str, argv.args[i]);
+ result = grub_script_execute_cmd (cmdfor->list);
+ }
+ }
+
+ if (active_breaks)
+ active_breaks--;
+
+ active_loops--;
+ grub_script_argv_free (&argv);
+ return result;
+ }
+
+ /* Execute a "while" or "until" command. */
+ grub_err_t
+ grub_script_execute_cmdwhile (struct grub_script_cmd *cmd)
+ {
+ int cond;
+ int result;
+ struct grub_script_cmdwhile *cmdwhile = (struct grub_script_cmdwhile *) cmd;
+
+ active_loops++;
+ result = 0;
+ do {
+ cond = grub_script_execute_cmd (cmdwhile->cond);
+ if (cmdwhile->until ? !cond : cond)
+ break;
+
+ result = grub_script_execute_cmd (cmdwhile->list);
+
+ if (active_breaks == 1 && is_continue)
+ active_breaks = 0;
+
+ if (active_breaks)
+ break;
+
+ } while (1); /* XXX Put a check for ^C here */
+
+ if (active_breaks)
+ active_breaks--;
+
+ active_loops--;
+ return result;
+ }
+
+ /* Execute the menu entry generate statement. */
+ grub_err_t
+ grub_script_execute_menuentry (struct grub_script_cmd *cmd)
+ {
+ struct grub_script_cmd_menuentry *cmd_menuentry;
+ struct grub_script_argv argv = { 0, 0 };
+
+ cmd_menuentry = (struct grub_script_cmd_menuentry *) cmd;
+
+ if (cmd_menuentry->arglist)
+ {
+ if (grub_script_arglist_to_argv (cmd_menuentry->arglist, &argv))
+ return grub_errno;
+ }
+
+ grub_normal_add_menu_entry (argv.argc, (const char **) argv.args,
+ cmd_menuentry->sourcecode);
+
+ grub_script_argv_free (&argv);
+
+ return grub_errno;
+ }
+
+
+
+ /* Execute any GRUB pre-parsed command or script. */
+ grub_err_t
+ grub_script_execute (struct grub_script *script)
+ {
+ if (script == 0)
+ return 0;
+
+ return grub_script_execute_cmd (script->cmd);
+ }
+
--- /dev/null
+ /*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 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/>.
+ */
+
+ #include <grub/dl.h>
+ #include <grub/i18n.h>
+ #include <grub/parser.h>
+ #include <grub/script_sh.h>
+
+ grub_err_t
+ grub_normal_parse_line (char *line, grub_reader_getline_t getline)
+ {
+ struct grub_script *parsed_script;
+
+ /* Parse the script. */
+ parsed_script = grub_script_parse (line, getline);
+
+ if (parsed_script)
+ {
+ /* Execute the command(s). */
+ grub_script_execute (parsed_script);
+
+ /* The parsed script was executed, throw it away. */
+ grub_script_free (parsed_script);
+ }
+
+ return grub_errno;
+ }
+
+ static grub_command_t cmd_break;
+ static grub_command_t cmd_continue;
+ static grub_command_t cmd_shift;
++static grub_command_t cmd_setparams;
+
+ void
+ grub_script_init (void)
+ {
+ cmd_break = grub_register_command ("break", grub_script_break,
+ N_("[n]"), N_("Exit from loops"));
+ cmd_continue = grub_register_command ("continue", grub_script_break,
+ N_("[n]"), N_("Continue loops"));
+ cmd_shift = grub_register_command ("shift", grub_script_shift,
+ N_("[n]"), N_("Shift positional parameters."));
++ cmd_setparams = grub_register_command ("setparams", grub_script_setparams,
++ N_("[VALUE]..."),
++ N_("Set positional parameters."));
+ }
+
+ void
+ grub_script_fini (void)
+ {
+ if (cmd_break)
+ grub_unregister_command (cmd_break);
+ cmd_break = 0;
+
+ if (cmd_continue)
+ grub_unregister_command (cmd_continue);
+ cmd_continue = 0;
+
+ if (cmd_shift)
+ grub_unregister_command (cmd_shift);
+ cmd_shift = 0;
++
++ if (cmd_setparams)
++ grub_unregister_command (cmd_setparams);
++ cmd_setparams = 0;
+ }