Upgraded GRUB2 to 2.00 release.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / script / execute.c
blobb5e6eb05ea092053a38fdbff8d358468e45d4442
1 /* execute.c -- Execute a GRUB script. */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2005,2007,2008,2009,2010 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/misc.h>
21 #include <grub/mm.h>
22 #include <grub/env.h>
23 #include <grub/script_sh.h>
24 #include <grub/command.h>
25 #include <grub/menu.h>
26 #include <grub/lib/arg.h>
27 #include <grub/normal.h>
28 #include <grub/extcmd.h>
29 #include <grub/i18n.h>
31 /* Max digits for a char is 3 (0xFF is 255), similarly for an int it
32 is sizeof (int) * 3, and one extra for a possible -ve sign. */
33 #define ERRNO_DIGITS_MAX (sizeof (int) * 3 + 1)
35 static unsigned long is_continue;
36 static unsigned long active_loops;
37 static unsigned long active_breaks;
38 static unsigned long function_return;
40 #define GRUB_SCRIPT_SCOPE_MALLOCED 1
41 #define GRUB_SCRIPT_SCOPE_ARGS_MALLOCED 2
43 /* Scope for grub script functions. */
44 struct grub_script_scope
46 unsigned flags;
47 unsigned shifts;
48 struct grub_script_argv argv;
50 static struct grub_script_scope *scope = 0;
52 /* Wildcard translator for GRUB script. */
53 struct grub_script_wildcard_translator *grub_wildcard_translator;
55 static char*
56 wildcard_escape (const char *s)
58 int i;
59 int len;
60 char ch;
61 char *p;
63 len = grub_strlen (s);
64 p = grub_malloc (len * 2 + 1);
65 if (! p)
66 return NULL;
68 i = 0;
69 while ((ch = *s++))
71 if (ch == '*' || ch == '\\' || ch == '?')
72 p[i++] = '\\';
73 p[i++] = ch;
75 p[i] = '\0';
76 return p;
79 static char*
80 wildcard_unescape (const char *s)
82 int i;
83 int len;
84 char ch;
85 char *p;
87 len = grub_strlen (s);
88 p = grub_malloc (len + 1);
89 if (! p)
90 return NULL;
92 i = 0;
93 while ((ch = *s++))
95 if (ch == '\\')
96 p[i++] = *s++;
97 else
98 p[i++] = ch;
100 p[i] = '\0';
101 return p;
104 static void
105 replace_scope (struct grub_script_scope *new_scope)
107 if (scope)
109 scope->argv.argc += scope->shifts;
110 scope->argv.args -= scope->shifts;
112 if (scope->flags & GRUB_SCRIPT_SCOPE_ARGS_MALLOCED)
113 grub_script_argv_free (&scope->argv);
115 if (scope->flags & GRUB_SCRIPT_SCOPE_MALLOCED)
116 grub_free (scope);
118 scope = new_scope;
121 grub_err_t
122 grub_script_break (grub_command_t cmd, int argc, char *argv[])
124 char *p = 0;
125 unsigned long count;
127 if (argc == 0)
128 count = 1;
129 else if (argc > 1)
130 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
131 else
133 count = grub_strtoul (argv[0], &p, 10);
134 if (grub_errno)
135 return grub_errno;
136 if (*p != '\0')
137 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unrecognized number"));
138 if (count == 0)
139 /* TRANSLATORS: 0 is a quantifier. "break" (similar to bash)
140 can be used e.g. to break 3 loops at once.
141 But asking it to break 0 loops makes no sense. */
142 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't break 0 loops"));
145 is_continue = grub_strcmp (cmd->name, "break") ? 1 : 0;
146 active_breaks = count;
147 if (active_breaks > active_loops)
148 active_breaks = active_loops;
149 return GRUB_ERR_NONE;
152 grub_err_t
153 grub_script_shift (grub_command_t cmd __attribute__((unused)),
154 int argc, char *argv[])
156 char *p = 0;
157 unsigned long n = 0;
159 if (! scope)
160 return GRUB_ERR_NONE;
162 if (argc == 0)
163 n = 1;
165 else if (argc > 1)
166 return GRUB_ERR_BAD_ARGUMENT;
168 else
170 n = grub_strtoul (argv[0], &p, 10);
171 if (*p != '\0')
172 return GRUB_ERR_BAD_ARGUMENT;
175 if (n > scope->argv.argc)
176 return GRUB_ERR_BAD_ARGUMENT;
178 scope->shifts += n;
179 scope->argv.argc -= n;
180 scope->argv.args += n;
181 return GRUB_ERR_NONE;
184 grub_err_t
185 grub_script_setparams (grub_command_t cmd __attribute__((unused)),
186 int argc, char **args)
188 struct grub_script_scope *new_scope;
189 struct grub_script_argv argv = { 0, 0, 0 };
191 if (! scope)
192 return GRUB_ERR_INVALID_COMMAND;
194 new_scope = grub_malloc (sizeof (*new_scope));
195 if (! new_scope)
196 return grub_errno;
198 if (grub_script_argv_make (&argv, argc, args))
200 grub_free (new_scope);
201 return grub_errno;
204 new_scope->shifts = 0;
205 new_scope->argv = argv;
206 new_scope->flags = GRUB_SCRIPT_SCOPE_MALLOCED |
207 GRUB_SCRIPT_SCOPE_ARGS_MALLOCED;
209 replace_scope (new_scope);
210 return GRUB_ERR_NONE;
213 grub_err_t
214 grub_script_return (grub_command_t cmd __attribute__((unused)),
215 int argc, char *argv[])
217 char *p;
218 unsigned long n;
220 if (! scope || argc > 1)
221 return grub_error (GRUB_ERR_BAD_ARGUMENT,
222 /* TRANSLATORS: It's about not being
223 inside a function. "return" can be used only
224 in a function and this error occurs if it's used
225 anywhere else. */
226 N_("not in function body"));
228 if (argc == 0)
230 const char *t;
231 function_return = 1;
232 t = grub_env_get ("?");
233 if (!t)
234 return GRUB_ERR_NONE;
235 return grub_strtoul (t, NULL, 10);
238 n = grub_strtoul (argv[0], &p, 10);
239 if (grub_errno)
240 return grub_errno;
241 if (*p != '\0')
242 return grub_error (GRUB_ERR_BAD_ARGUMENT,
243 N_("unrecognized number"));
245 function_return = 1;
246 return n ? grub_error (n, N_("false")) : GRUB_ERR_NONE;
249 static int
250 grub_env_special (const char *name)
252 if (grub_isdigit (name[0]) ||
253 grub_strcmp (name, "#") == 0 ||
254 grub_strcmp (name, "*") == 0 ||
255 grub_strcmp (name, "@") == 0)
256 return 1;
257 return 0;
260 static char **
261 grub_script_env_get (const char *name, grub_script_arg_type_t type)
263 unsigned i;
264 struct grub_script_argv result = { 0, 0, 0 };
266 if (grub_script_argv_next (&result))
267 goto fail;
269 if (! grub_env_special (name))
271 const char *v = grub_env_get (name);
272 if (v && v[0])
274 if (type == GRUB_SCRIPT_ARG_TYPE_VAR)
276 if (grub_script_argv_split_append (&result, v))
277 goto fail;
279 else
280 if (grub_script_argv_append (&result, v, grub_strlen (v)))
281 goto fail;
284 else if (! scope)
286 if (grub_script_argv_append (&result, 0, 0))
287 goto fail;
289 else if (grub_strcmp (name, "#") == 0)
291 char buffer[ERRNO_DIGITS_MAX + 1];
292 grub_snprintf (buffer, sizeof (buffer), "%u", scope->argv.argc);
293 if (grub_script_argv_append (&result, buffer, grub_strlen (buffer)))
294 goto fail;
296 else if (grub_strcmp (name, "*") == 0)
298 for (i = 0; i < scope->argv.argc; i++)
299 if (type == GRUB_SCRIPT_ARG_TYPE_VAR)
301 if (i != 0 && grub_script_argv_next (&result))
302 goto fail;
304 if (grub_script_argv_split_append (&result, scope->argv.args[i]))
305 goto fail;
307 else
309 if (i != 0 && grub_script_argv_append (&result, " ", 1))
310 goto fail;
312 if (grub_script_argv_append (&result, scope->argv.args[i],
313 grub_strlen (scope->argv.args[i])))
314 goto fail;
317 else if (grub_strcmp (name, "@") == 0)
319 for (i = 0; i < scope->argv.argc; i++)
321 if (i != 0 && grub_script_argv_next (&result))
322 goto fail;
324 if (type == GRUB_SCRIPT_ARG_TYPE_VAR)
326 if (grub_script_argv_split_append (&result, scope->argv.args[i]))
327 goto fail;
329 else
330 if (grub_script_argv_append (&result, scope->argv.args[i],
331 grub_strlen (scope->argv.args[i])))
332 goto fail;
335 else
337 unsigned long num = grub_strtoul (name, 0, 10);
338 if (num == 0)
339 ; /* XXX no file name, for now. */
341 else if (num <= scope->argv.argc)
343 if (type == GRUB_SCRIPT_ARG_TYPE_VAR)
345 if (grub_script_argv_split_append (&result,
346 scope->argv.args[num - 1]))
347 goto fail;
349 else
350 if (grub_script_argv_append (&result, scope->argv.args[num - 1],
351 grub_strlen (scope->argv.args[num - 1])
353 goto fail;
357 return result.args;
359 fail:
361 grub_script_argv_free (&result);
362 return 0;
365 static grub_err_t
366 grub_script_env_set (const char *name, const char *val)
368 if (grub_env_special (name))
369 return grub_error (GRUB_ERR_BAD_ARGUMENT,
370 N_("invalid variable name `%s'"), name);
372 return grub_env_set (name, val);
375 static int
376 parse_string (const char *str,
377 int (*hook) (const char *var, grub_size_t varlen),
378 char **put)
380 const char *ptr;
381 int escaped = 0;
382 const char *optr;
384 for (ptr = str; ptr && *ptr; )
385 switch (*ptr)
387 case '\\':
388 escaped = !escaped;
389 if (!escaped && put)
390 *((*put)++) = '\\';
391 ptr++;
392 break;
393 case '$':
394 if (escaped)
396 escaped = 0;
397 if (put)
398 *((*put)++) = *ptr;
399 ptr++;
400 break;
403 ptr++;
404 switch (*ptr)
406 case '{':
408 optr = ptr + 1;
409 ptr = grub_strchr (optr, '}');
410 if (!ptr)
411 break;
412 if (hook (optr, ptr - optr))
413 return 1;
414 ptr++;
415 break;
417 case '0' ... '9':
418 optr = ptr;
419 while (*ptr >= '0' && *ptr <= '9')
420 ptr++;
421 if (hook (optr, ptr - optr))
422 return 1;
423 break;
424 case 'a' ... 'z':
425 case 'A' ... 'Z':
426 case '_':
427 optr = ptr;
428 while ((*ptr >= '0' && *ptr <= '9')
429 || (*ptr >= 'a' && *ptr <= 'z')
430 || (*ptr >= 'A' && *ptr <= 'Z')
431 || *ptr == '_')
432 ptr++;
433 if (hook (optr, ptr - optr))
434 return 1;
435 break;
436 case '?':
437 case '#':
438 if (hook (ptr, 1))
439 return 1;
440 ptr++;
441 break;
442 default:
443 if (put)
444 *((*put)++) = '$';
446 break;
447 default:
448 if (escaped && put)
449 *((*put)++) = '\\';
450 escaped = 0;
451 if (put)
452 *((*put)++) = *ptr;
453 ptr++;
454 break;
456 return 0;
459 static int
460 gettext_append (struct grub_script_argv *result, const char *orig_str)
462 const char *template;
463 char *res = 0, *ptr;
464 char **allowed_strings;
465 grub_size_t nallowed_strings = 0;
466 grub_size_t additional_len = 1;
467 int rval = 1;
468 const char *iptr;
470 auto int save_allow (const char *str, grub_size_t len);
471 int save_allow (const char *str, grub_size_t len)
473 allowed_strings[nallowed_strings++] = grub_strndup (str, len);
474 if (!allowed_strings[nallowed_strings - 1])
475 return 1;
476 return 0;
479 auto int getlen (const char *str, grub_size_t len);
480 int getlen (const char *str, grub_size_t len)
482 const char *var;
483 grub_size_t i;
485 for (i = 0; i < nallowed_strings; i++)
486 if (grub_strncmp (allowed_strings[i], str, len) == 0
487 && allowed_strings[i][len] == 0)
488 break;
489 if (i == nallowed_strings)
490 return 0;
492 /* Enough for any number. */
493 if (len == 1 && str[0] == '#')
495 additional_len += 30;
496 return 0;
498 var = grub_env_get (allowed_strings[i]);
499 if (var)
500 additional_len += grub_strlen (var);
501 return 0;
504 auto int putvar (const char *str, grub_size_t len);
505 int putvar (const char *str, grub_size_t len)
507 const char *var;
508 grub_size_t i;
510 for (i = 0; i < nallowed_strings; i++)
511 if (grub_strncmp (allowed_strings[i], str, len) == 0
512 && allowed_strings[i][len] == 0)
514 break;
516 if (i == nallowed_strings)
517 return 0;
519 /* Enough for any number. */
520 if (len == 1 && str[0] == '#')
522 grub_snprintf (ptr, 30, "%u", scope->argv.argc);
523 ptr += grub_strlen (ptr);
524 return 0;
526 var = grub_env_get (allowed_strings[i]);
527 if (var)
528 ptr = grub_stpcpy (ptr, var);
529 return 0;
532 grub_size_t dollar_cnt = 0;
534 for (iptr = orig_str; *iptr; iptr++)
535 if (*iptr == '$')
536 dollar_cnt++;
537 allowed_strings = grub_malloc (sizeof (allowed_strings[0]) * dollar_cnt);
539 if (parse_string (orig_str, save_allow, 0))
540 goto fail;
542 template = _(orig_str);
544 if (parse_string (template, getlen, 0))
545 goto fail;
547 res = grub_malloc (grub_strlen (template) + additional_len);
548 if (!res)
549 goto fail;
550 ptr = res;
552 if (parse_string (template, putvar, &ptr))
553 goto fail;
555 *ptr = 0;
556 char *escaped = 0;
557 escaped = wildcard_escape (res);
558 if (grub_script_argv_append (result, escaped, grub_strlen (escaped)))
560 grub_free (escaped);
561 goto fail;
563 grub_free (escaped);
565 rval = 0;
566 fail:
567 grub_free (res);
569 grub_size_t i;
570 for (i = 0; i < nallowed_strings; i++)
571 grub_free (allowed_strings[i]);
573 grub_free (allowed_strings);
574 return rval;
577 /* Convert arguments in ARGLIST into ARGV form. */
578 static int
579 grub_script_arglist_to_argv (struct grub_script_arglist *arglist,
580 struct grub_script_argv *argv)
582 int i;
583 char **values = 0;
584 struct grub_script_arg *arg = 0;
585 struct grub_script_argv result = { 0, 0, 0 };
587 auto int append (const char *s, int escape_type);
588 int append (const char *s, int escape_type)
590 int r;
591 char *p = 0;
593 if (escape_type == 0)
594 return grub_script_argv_append (&result, s, grub_strlen (s));
596 if (escape_type > 0)
597 p = wildcard_escape (s);
598 else if (escape_type < 0)
599 p = wildcard_unescape (s);
601 if (! p)
602 return 1;
604 r = grub_script_argv_append (&result, p, grub_strlen (p));
605 grub_free (p);
606 return r;
609 for (; arglist && arglist->arg; arglist = arglist->next)
611 if (grub_script_argv_next (&result))
612 goto fail;
614 arg = arglist->arg;
615 while (arg)
617 switch (arg->type)
619 case GRUB_SCRIPT_ARG_TYPE_VAR:
620 case GRUB_SCRIPT_ARG_TYPE_DQVAR:
621 values = grub_script_env_get (arg->str, arg->type);
622 for (i = 0; values && values[i]; i++)
624 if (i != 0 && grub_script_argv_next (&result))
625 goto fail;
627 if (arg->type == GRUB_SCRIPT_ARG_TYPE_VAR)
629 if (grub_script_argv_append (&result, values[i],
630 grub_strlen (values[i])))
631 goto fail;
633 else
635 if (append (values[i], 1))
636 goto fail;
639 grub_free (values[i]);
641 grub_free (values);
642 break;
644 case GRUB_SCRIPT_ARG_TYPE_BLOCK:
646 char *p;
647 if (grub_script_argv_append (&result, "{", 1))
648 goto fail;
649 p = wildcard_escape (arg->str);
650 if (!p)
651 goto fail;
652 if (grub_script_argv_append (&result, p,
653 grub_strlen (p)))
655 grub_free (p);
656 goto fail;
658 grub_free (p);
659 if (grub_script_argv_append (&result, "}", 1))
660 goto fail;
662 result.script = arg->script;
663 break;
665 case GRUB_SCRIPT_ARG_TYPE_TEXT:
666 if (arg->str[0] &&
667 grub_script_argv_append (&result, arg->str,
668 grub_strlen (arg->str)))
669 goto fail;
670 break;
672 case GRUB_SCRIPT_ARG_TYPE_GETTEXT:
674 if (gettext_append (&result, arg->str))
675 goto fail;
677 break;
679 case GRUB_SCRIPT_ARG_TYPE_DQSTR:
680 case GRUB_SCRIPT_ARG_TYPE_SQSTR:
681 if (append (arg->str, 1))
682 goto fail;
683 break;
685 arg = arg->next;
689 if (! result.args[result.argc - 1])
690 result.argc--;
692 /* Perform wildcard expansion. */
694 int j;
695 int failed = 0;
696 struct grub_script_argv unexpanded = result;
698 result.argc = 0;
699 result.args = 0;
700 for (i = 0; unexpanded.args[i]; i++)
702 char **expansions = 0;
703 if (grub_wildcard_translator
704 && grub_wildcard_translator->expand (unexpanded.args[i],
705 &expansions))
707 grub_script_argv_free (&unexpanded);
708 goto fail;
711 if (! expansions)
713 grub_script_argv_next (&result);
714 append (unexpanded.args[i], -1);
716 else
718 for (j = 0; expansions[j]; j++)
720 failed = (failed || grub_script_argv_next (&result) ||
721 append (expansions[j], 0));
722 grub_free (expansions[j]);
724 grub_free (expansions);
726 if (failed)
728 grub_script_argv_free (&unexpanded);
729 goto fail;
733 grub_script_argv_free (&unexpanded);
735 *argv = result;
736 return 0;
738 fail:
740 grub_script_argv_free (&result);
741 return 1;
744 static grub_err_t
745 grub_script_execute_cmd (struct grub_script_cmd *cmd)
747 int ret;
748 char errnobuf[ERRNO_DIGITS_MAX + 1];
750 if (cmd == 0)
751 return 0;
753 ret = cmd->exec (cmd);
755 grub_snprintf (errnobuf, sizeof (errnobuf), "%d", ret);
756 grub_env_set ("?", errnobuf);
757 return ret;
760 /* Execute a function call. */
761 grub_err_t
762 grub_script_function_call (grub_script_function_t func, int argc, char **args)
764 grub_err_t ret = 0;
765 unsigned long loops = active_loops;
766 struct grub_script_scope *old_scope;
767 struct grub_script_scope new_scope;
769 active_loops = 0;
770 new_scope.flags = 0;
771 new_scope.shifts = 0;
772 new_scope.argv.argc = argc;
773 new_scope.argv.args = args;
775 old_scope = scope;
776 scope = &new_scope;
778 ret = grub_script_execute (func->func);
780 function_return = 0;
781 active_loops = loops;
782 replace_scope (old_scope); /* free any scopes by setparams */
783 return ret;
786 /* Execute a source script. */
787 grub_err_t
788 grub_script_execute_sourcecode (const char *source, int argc, char **args)
790 grub_err_t ret = 0;
791 struct grub_script *parsed_script;
792 struct grub_script_scope new_scope;
793 struct grub_script_scope *old_scope;
795 auto grub_err_t getline (char **line, int cont);
796 grub_err_t getline (char **line, int cont __attribute__ ((unused)))
798 const char *p;
800 if (! source)
802 *line = 0;
803 return 0;
806 p = grub_strchr (source, '\n');
808 if (p)
809 *line = grub_strndup (source, p - source);
810 else
811 *line = grub_strdup (source);
812 source = p ? p + 1 : 0;
813 return 0;
816 new_scope.argv.argc = argc;
817 new_scope.argv.args = args;
818 new_scope.flags = 0;
820 old_scope = scope;
821 scope = &new_scope;
823 while (source)
825 char *line;
827 getline (&line, 0);
828 parsed_script = grub_script_parse (line, getline);
829 if (! parsed_script)
831 ret = grub_errno;
832 break;
835 ret = grub_script_execute (parsed_script);
836 grub_free (line);
839 scope = old_scope;
840 return ret;
843 /* Execute a single command line. */
844 grub_err_t
845 grub_script_execute_cmdline (struct grub_script_cmd *cmd)
847 struct grub_script_cmdline *cmdline = (struct grub_script_cmdline *) cmd;
848 grub_command_t grubcmd;
849 grub_err_t ret = 0;
850 grub_script_function_t func = 0;
851 char errnobuf[18];
852 char *cmdname;
853 int argc;
854 char **args;
855 int invert;
856 struct grub_script_argv argv = { 0, 0, 0 };
858 /* Lookup the command. */
859 if (grub_script_arglist_to_argv (cmdline->arglist, &argv) || ! argv.args[0])
860 return grub_errno;
862 invert = 0;
863 argc = argv.argc - 1;
864 args = argv.args + 1;
865 cmdname = argv.args[0];
866 if (grub_strcmp (cmdname, "!") == 0)
868 if (argv.argc < 2 || ! argv.args[1])
870 grub_script_argv_free (&argv);
871 return grub_error (GRUB_ERR_BAD_ARGUMENT,
872 N_("no command is specified"));
875 invert = 1;
876 argc = argv.argc - 2;
877 args = argv.args + 2;
878 cmdname = argv.args[1];
880 grubcmd = grub_command_find (cmdname);
881 if (! grubcmd)
883 grub_errno = GRUB_ERR_NONE;
885 /* It's not a GRUB command, try all functions. */
886 func = grub_script_function_find (cmdname);
887 if (! func)
889 /* As a last resort, try if it is an assignment. */
890 char *assign = grub_strdup (cmdname);
891 char *eq = grub_strchr (assign, '=');
893 if (eq)
895 /* This was set because the command was not found. */
896 grub_errno = GRUB_ERR_NONE;
898 /* Create two strings and set the variable. */
899 *eq = '\0';
900 eq++;
901 grub_script_env_set (assign, eq);
903 grub_free (assign);
905 grub_snprintf (errnobuf, sizeof (errnobuf), "%d", grub_errno);
906 grub_script_env_set ("?", errnobuf);
908 grub_script_argv_free (&argv);
909 grub_print_error ();
911 return 0;
915 /* Execute the GRUB command or function. */
916 if (grubcmd)
918 if (grub_extractor_level && !(grubcmd->flags
919 & GRUB_COMMAND_FLAG_EXTRACTOR))
920 ret = grub_error (GRUB_ERR_EXTRACTOR,
921 "%s isn't allowed to execute in an extractor",
922 cmdname);
923 else if ((grubcmd->flags & GRUB_COMMAND_FLAG_BLOCKS) &&
924 (grubcmd->flags & GRUB_COMMAND_FLAG_EXTCMD))
925 ret = grub_extcmd_dispatcher (grubcmd, argc, args, argv.script);
926 else
927 ret = (grubcmd->func) (grubcmd, argc, args);
929 else
930 ret = grub_script_function_call (func, argc, args);
932 if (invert)
934 if (ret == GRUB_ERR_TEST_FAILURE)
935 grub_errno = ret = GRUB_ERR_NONE;
936 else if (ret == GRUB_ERR_NONE)
937 ret = grub_error (GRUB_ERR_TEST_FAILURE, N_("false"));
938 else
940 grub_print_error ();
941 ret = GRUB_ERR_NONE;
945 /* Free arguments. */
946 grub_script_argv_free (&argv);
948 if (grub_errno == GRUB_ERR_TEST_FAILURE)
949 grub_errno = GRUB_ERR_NONE;
951 grub_print_error ();
953 grub_snprintf (errnobuf, sizeof (errnobuf), "%d", ret);
954 grub_env_set ("?", errnobuf);
956 return ret;
959 /* Execute a block of one or more commands. */
960 grub_err_t
961 grub_script_execute_cmdlist (struct grub_script_cmd *list)
963 int ret = 0;
964 struct grub_script_cmd *cmd;
966 /* Loop over every command and execute it. */
967 for (cmd = list->next; cmd; cmd = cmd->next)
969 if (active_breaks)
970 break;
972 ret = grub_script_execute_cmd (cmd);
974 if (function_return)
975 break;
978 return ret;
981 /* Execute an if statement. */
982 grub_err_t
983 grub_script_execute_cmdif (struct grub_script_cmd *cmd)
985 int ret;
986 const char *result;
987 struct grub_script_cmdif *cmdif = (struct grub_script_cmdif *) cmd;
989 /* Check if the commands results in a true or a false. The value is
990 read from the env variable `?'. */
991 ret = grub_script_execute_cmd (cmdif->exec_to_evaluate);
992 if (function_return)
993 return ret;
995 result = grub_env_get ("?");
996 grub_errno = GRUB_ERR_NONE;
998 /* Execute the `if' or the `else' part depending on the value of
999 `?'. */
1000 if (result && ! grub_strcmp (result, "0"))
1001 return grub_script_execute_cmd (cmdif->exec_on_true);
1002 else
1003 return grub_script_execute_cmd (cmdif->exec_on_false);
1006 /* Execute a for statement. */
1007 grub_err_t
1008 grub_script_execute_cmdfor (struct grub_script_cmd *cmd)
1010 unsigned i;
1011 grub_err_t result;
1012 struct grub_script_argv argv = { 0, 0, 0 };
1013 struct grub_script_cmdfor *cmdfor = (struct grub_script_cmdfor *) cmd;
1015 if (grub_script_arglist_to_argv (cmdfor->words, &argv))
1016 return grub_errno;
1018 active_loops++;
1019 result = 0;
1020 for (i = 0; i < argv.argc; i++)
1022 if (is_continue && active_breaks == 1)
1023 active_breaks = 0;
1025 if (! active_breaks)
1027 grub_script_env_set (cmdfor->name->str, argv.args[i]);
1028 result = grub_script_execute_cmd (cmdfor->list);
1029 if (function_return)
1030 break;
1034 if (active_breaks)
1035 active_breaks--;
1037 active_loops--;
1038 grub_script_argv_free (&argv);
1039 return result;
1042 /* Execute a "while" or "until" command. */
1043 grub_err_t
1044 grub_script_execute_cmdwhile (struct grub_script_cmd *cmd)
1046 int result;
1047 struct grub_script_cmdwhile *cmdwhile = (struct grub_script_cmdwhile *) cmd;
1049 active_loops++;
1050 do {
1051 result = grub_script_execute_cmd (cmdwhile->cond);
1052 if (function_return)
1053 break;
1055 if (cmdwhile->until ? !result : result)
1056 break;
1058 result = grub_script_execute_cmd (cmdwhile->list);
1059 if (function_return)
1060 break;
1062 if (active_breaks == 1 && is_continue)
1063 active_breaks = 0;
1065 if (active_breaks)
1066 break;
1068 } while (1); /* XXX Put a check for ^C here */
1070 if (active_breaks)
1071 active_breaks--;
1073 active_loops--;
1074 return result;
1077 /* Execute any GRUB pre-parsed command or script. */
1078 grub_err_t
1079 grub_script_execute (struct grub_script *script)
1081 if (script == 0)
1082 return 0;
1084 return grub_script_execute_cmd (script->cmd);