1 /* execute.c -- Execute a GRUB script. */
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>
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>
30 #include <grub/verify.h>
32 /* Max digits for a char is 3 (0xFF is 255), similarly for an int it
33 is sizeof (int) * 3, and one extra for a possible -ve sign. */
34 #define ERRNO_DIGITS_MAX (sizeof (int) * 3 + 1)
36 static unsigned long is_continue
;
37 static unsigned long active_loops
;
38 static unsigned long active_breaks
;
39 static unsigned long function_return
;
41 #define GRUB_SCRIPT_SCOPE_MALLOCED 1
42 #define GRUB_SCRIPT_SCOPE_ARGS_MALLOCED 2
44 /* Scope for grub script functions. */
45 struct grub_script_scope
49 struct grub_script_argv argv
;
51 static struct grub_script_scope
*scope
= 0;
53 /* Wildcard translator for GRUB script. */
54 struct grub_script_wildcard_translator
*grub_wildcard_translator
;
57 wildcard_escape (const char *s
)
64 len
= grub_strlen (s
);
65 p
= grub_malloc (len
* 2 + 1);
72 if (ch
== '*' || ch
== '\\' || ch
== '?')
81 wildcard_unescape (const char *s
)
88 len
= grub_strlen (s
);
89 p
= grub_malloc (len
+ 1);
106 replace_scope (struct grub_script_scope
*new_scope
)
110 scope
->argv
.argc
+= scope
->shifts
;
111 scope
->argv
.args
-= scope
->shifts
;
113 if (scope
->flags
& GRUB_SCRIPT_SCOPE_ARGS_MALLOCED
)
114 grub_script_argv_free (&scope
->argv
);
116 if (scope
->flags
& GRUB_SCRIPT_SCOPE_MALLOCED
)
123 grub_script_break (grub_command_t cmd
, int argc
, char *argv
[])
125 const char *p
= NULL
;
131 return grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("one argument expected"));
134 count
= grub_strtoul (argv
[0], &p
, 10);
138 return grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("unrecognized number"));
140 /* TRANSLATORS: 0 is a quantifier. "break" (similar to bash)
141 can be used e.g. to break 3 loops at once.
142 But asking it to break 0 loops makes no sense. */
143 return grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("can't break 0 loops"));
146 is_continue
= grub_strcmp (cmd
->name
, "break") ? 1 : 0;
147 active_breaks
= count
;
148 if (active_breaks
> active_loops
)
149 active_breaks
= active_loops
;
150 return GRUB_ERR_NONE
;
154 grub_script_shift (grub_command_t cmd
__attribute__((unused
)),
155 int argc
, char *argv
[])
157 const char *p
= NULL
;
161 return GRUB_ERR_NONE
;
167 return GRUB_ERR_BAD_ARGUMENT
;
171 n
= grub_strtoul (argv
[0], &p
, 10);
173 return GRUB_ERR_BAD_ARGUMENT
;
176 if (n
> scope
->argv
.argc
)
177 return GRUB_ERR_BAD_ARGUMENT
;
180 scope
->argv
.argc
-= n
;
181 scope
->argv
.args
+= n
;
182 return GRUB_ERR_NONE
;
186 grub_script_setparams (grub_command_t cmd
__attribute__((unused
)),
187 int argc
, char **args
)
189 struct grub_script_scope
*new_scope
;
190 struct grub_script_argv argv
= { 0, 0, 0 };
193 return GRUB_ERR_INVALID_COMMAND
;
195 new_scope
= grub_malloc (sizeof (*new_scope
));
199 if (grub_script_argv_make (&argv
, argc
, args
))
201 grub_free (new_scope
);
205 new_scope
->shifts
= 0;
206 new_scope
->argv
= argv
;
207 new_scope
->flags
= GRUB_SCRIPT_SCOPE_MALLOCED
|
208 GRUB_SCRIPT_SCOPE_ARGS_MALLOCED
;
210 replace_scope (new_scope
);
211 return GRUB_ERR_NONE
;
215 grub_script_return (grub_command_t cmd
__attribute__((unused
)),
216 int argc
, char *argv
[])
218 const char *p
= NULL
;
221 if (! scope
|| argc
> 1)
222 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
223 /* TRANSLATORS: It's about not being
224 inside a function. "return" can be used only
225 in a function and this error occurs if it's used
227 N_("not in function body"));
233 t
= grub_env_get ("?");
235 return GRUB_ERR_NONE
;
236 return grub_strtoul (t
, NULL
, 10);
239 n
= grub_strtoul (argv
[0], &p
, 10);
243 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
244 N_("unrecognized number"));
247 return n
? grub_error (n
, N_("false")) : GRUB_ERR_NONE
;
251 grub_env_special (const char *name
)
253 if (grub_isdigit (name
[0]) ||
254 grub_strcmp (name
, "#") == 0 ||
255 grub_strcmp (name
, "*") == 0 ||
256 grub_strcmp (name
, "@") == 0)
262 grub_script_env_get (const char *name
, grub_script_arg_type_t type
)
265 struct grub_script_argv result
= { 0, 0, 0 };
267 if (grub_script_argv_next (&result
))
270 if (! grub_env_special (name
))
272 const char *v
= grub_env_get (name
);
275 if (type
== GRUB_SCRIPT_ARG_TYPE_VAR
)
277 if (grub_script_argv_split_append (&result
, v
))
281 if (grub_script_argv_append (&result
, v
, grub_strlen (v
)))
287 if (grub_script_argv_append (&result
, 0, 0))
290 else if (grub_strcmp (name
, "#") == 0)
292 char buffer
[ERRNO_DIGITS_MAX
+ 1];
293 grub_snprintf (buffer
, sizeof (buffer
), "%u", scope
->argv
.argc
);
294 if (grub_script_argv_append (&result
, buffer
, grub_strlen (buffer
)))
297 else if (grub_strcmp (name
, "*") == 0)
299 for (i
= 0; i
< scope
->argv
.argc
; i
++)
300 if (type
== GRUB_SCRIPT_ARG_TYPE_VAR
)
302 if (i
!= 0 && grub_script_argv_next (&result
))
305 if (grub_script_argv_split_append (&result
, scope
->argv
.args
[i
]))
310 if (i
!= 0 && grub_script_argv_append (&result
, " ", 1))
313 if (grub_script_argv_append (&result
, scope
->argv
.args
[i
],
314 grub_strlen (scope
->argv
.args
[i
])))
318 else if (grub_strcmp (name
, "@") == 0)
320 for (i
= 0; i
< scope
->argv
.argc
; i
++)
322 if (i
!= 0 && grub_script_argv_next (&result
))
325 if (type
== GRUB_SCRIPT_ARG_TYPE_VAR
)
327 if (grub_script_argv_split_append (&result
, scope
->argv
.args
[i
]))
331 if (grub_script_argv_append (&result
, scope
->argv
.args
[i
],
332 grub_strlen (scope
->argv
.args
[i
])))
338 unsigned long num
= grub_strtoul (name
, 0, 10);
340 ; /* XXX no file name, for now. */
342 else if (num
<= scope
->argv
.argc
)
344 if (type
== GRUB_SCRIPT_ARG_TYPE_VAR
)
346 if (grub_script_argv_split_append (&result
,
347 scope
->argv
.args
[num
- 1]))
351 if (grub_script_argv_append (&result
, scope
->argv
.args
[num
- 1],
352 grub_strlen (scope
->argv
.args
[num
- 1])
362 grub_script_argv_free (&result
);
367 grub_script_env_set (const char *name
, const char *val
)
369 if (grub_env_special (name
))
370 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
371 N_("invalid variable name `%s'"), name
);
373 return grub_env_set (name
, val
);
376 struct gettext_context
378 char **allowed_strings
;
379 grub_size_t nallowed_strings
;
380 grub_size_t additional_len
;
384 parse_string (const char *str
,
385 int (*hook
) (const char *var
, grub_size_t varlen
,
386 char **ptr
, struct gettext_context
*ctx
),
387 struct gettext_context
*ctx
,
394 for (ptr
= str
; ptr
&& *ptr
; )
419 ptr
= grub_strchr (optr
, '}');
422 if (hook (optr
, ptr
- optr
, &put
, ctx
))
429 while (*ptr
>= '0' && *ptr
<= '9')
431 if (hook (optr
, ptr
- optr
, &put
, ctx
))
438 while ((*ptr
>= '0' && *ptr
<= '9')
439 || (*ptr
>= 'a' && *ptr
<= 'z')
440 || (*ptr
>= 'A' && *ptr
<= 'Z')
443 if (hook (optr
, ptr
- optr
, &put
, ctx
))
448 if (hook (ptr
, 1, &put
, ctx
))
472 gettext_putvar (const char *str
, grub_size_t len
,
473 char **ptr
, struct gettext_context
*ctx
)
478 for (i
= 0; i
< ctx
->nallowed_strings
; i
++)
479 if (grub_strncmp (ctx
->allowed_strings
[i
], str
, len
) == 0
480 && ctx
->allowed_strings
[i
][len
] == 0)
484 if (i
== ctx
->nallowed_strings
)
487 /* Enough for any number. */
488 if (len
== 1 && str
[0] == '#' && scope
!= NULL
)
490 grub_snprintf (*ptr
, 30, "%u", scope
->argv
.argc
);
491 *ptr
+= grub_strlen (*ptr
);
494 var
= grub_env_get (ctx
->allowed_strings
[i
]);
496 *ptr
= grub_stpcpy (*ptr
, var
);
501 gettext_save_allow (const char *str
, grub_size_t len
,
502 char **ptr
__attribute__ ((unused
)),
503 struct gettext_context
*ctx
)
505 ctx
->allowed_strings
[ctx
->nallowed_strings
++] = grub_strndup (str
, len
);
506 if (!ctx
->allowed_strings
[ctx
->nallowed_strings
- 1])
512 gettext_getlen (const char *str
, grub_size_t len
,
513 char **ptr
__attribute__ ((unused
)),
514 struct gettext_context
*ctx
)
519 for (i
= 0; i
< ctx
->nallowed_strings
; i
++)
520 if (grub_strncmp (ctx
->allowed_strings
[i
], str
, len
) == 0
521 && ctx
->allowed_strings
[i
][len
] == 0)
523 if (i
== ctx
->nallowed_strings
)
526 /* Enough for any number. */
527 if (len
== 1 && str
[0] == '#')
529 ctx
->additional_len
+= 30;
532 var
= grub_env_get (ctx
->allowed_strings
[i
]);
534 ctx
->additional_len
+= grub_strlen (var
);
539 gettext_append (struct grub_script_argv
*result
, const char *orig_str
)
541 const char *template;
543 struct gettext_context ctx
= {
544 .allowed_strings
= 0,
545 .nallowed_strings
= 0,
551 grub_size_t dollar_cnt
= 0;
553 for (iptr
= orig_str
; *iptr
; iptr
++)
556 ctx
.allowed_strings
= grub_calloc (dollar_cnt
, sizeof (ctx
.allowed_strings
[0]));
558 if (parse_string (orig_str
, gettext_save_allow
, &ctx
, 0))
561 template = _(orig_str
);
563 if (parse_string (template, gettext_getlen
, &ctx
, 0))
566 res
= grub_malloc (grub_strlen (template) + ctx
.additional_len
);
570 if (parse_string (template, gettext_putvar
, &ctx
, res
))
574 escaped
= wildcard_escape (res
);
575 if (grub_script_argv_append (result
, escaped
, grub_strlen (escaped
)))
587 for (i
= 0; i
< ctx
.nallowed_strings
; i
++)
588 grub_free (ctx
.allowed_strings
[i
]);
590 grub_free (ctx
.allowed_strings
);
595 append (struct grub_script_argv
*result
,
596 const char *s
, int escape_type
)
601 if (escape_type
== 0)
602 return grub_script_argv_append (result
, s
, grub_strlen (s
));
605 p
= wildcard_escape (s
);
606 else if (escape_type
< 0)
607 p
= wildcard_unescape (s
);
612 r
= grub_script_argv_append (result
, p
, grub_strlen (p
));
617 /* Convert arguments in ARGLIST into ARGV form. */
619 grub_script_arglist_to_argv (struct grub_script_arglist
*arglist
,
620 struct grub_script_argv
*argv
)
624 struct grub_script_arg
*arg
= 0;
625 struct grub_script_argv result
= { 0, 0, 0 };
630 for (; arglist
&& arglist
->arg
; arglist
= arglist
->next
)
632 if (grub_script_argv_next (&result
))
640 case GRUB_SCRIPT_ARG_TYPE_VAR
:
641 case GRUB_SCRIPT_ARG_TYPE_DQVAR
:
643 int need_cleanup
= 0;
645 values
= grub_script_env_get (arg
->str
, arg
->type
);
646 for (i
= 0; values
&& values
[i
]; i
++)
650 if (i
!= 0 && grub_script_argv_next (&result
))
656 if (arg
->type
== GRUB_SCRIPT_ARG_TYPE_VAR
)
662 const char *s
= values
[i
];
664 len
= grub_strlen (values
[i
]);
668 p
= grub_malloc (len
* 2 + 1);
681 if (*s
== '?' || *s
== '*')
688 need_cleanup
= grub_script_argv_append (&result
, p
, op
- p
);
690 /* Fall through to cleanup */
694 need_cleanup
= append (&result
, values
[i
], 1);
695 /* Fall through to cleanup */
700 grub_free (values
[i
]);
710 case GRUB_SCRIPT_ARG_TYPE_BLOCK
:
713 if (grub_script_argv_append (&result
, "{", 1))
715 p
= wildcard_escape (arg
->str
);
718 if (grub_script_argv_append (&result
, p
,
725 if (grub_script_argv_append (&result
, "}", 1))
728 result
.script
= arg
->script
;
731 case GRUB_SCRIPT_ARG_TYPE_TEXT
:
733 grub_script_argv_append (&result
, arg
->str
,
734 grub_strlen (arg
->str
)))
738 case GRUB_SCRIPT_ARG_TYPE_GETTEXT
:
740 if (gettext_append (&result
, arg
->str
))
745 case GRUB_SCRIPT_ARG_TYPE_DQSTR
:
746 case GRUB_SCRIPT_ARG_TYPE_SQSTR
:
747 if (append (&result
, arg
->str
, 1))
755 if (! result
.args
[result
.argc
- 1])
758 /* Perform wildcard expansion. */
762 struct grub_script_argv unexpanded
= result
;
766 for (i
= 0; unexpanded
.args
[i
]; i
++)
768 char **expansions
= 0;
769 if (grub_wildcard_translator
770 && grub_wildcard_translator
->expand (unexpanded
.args
[i
],
773 grub_script_argv_free (&unexpanded
);
779 grub_script_argv_next (&result
);
780 append (&result
, unexpanded
.args
[i
], -1);
784 for (j
= 0; expansions
[j
]; j
++)
786 failed
= (failed
|| grub_script_argv_next (&result
) ||
787 append (&result
, expansions
[j
], 0));
788 grub_free (expansions
[j
]);
790 grub_free (expansions
);
794 grub_script_argv_free (&unexpanded
);
799 grub_script_argv_free (&unexpanded
);
806 grub_script_argv_free (&result
);
811 grub_script_execute_cmd (struct grub_script_cmd
*cmd
)
814 char errnobuf
[ERRNO_DIGITS_MAX
+ 1];
819 ret
= cmd
->exec (cmd
);
821 grub_snprintf (errnobuf
, sizeof (errnobuf
), "%d", ret
);
822 grub_env_set ("?", errnobuf
);
826 /* Execute a function call. */
828 grub_script_function_call (grub_script_function_t func
, int argc
, char **args
)
831 unsigned long loops
= active_loops
;
832 struct grub_script_scope
*old_scope
;
833 struct grub_script_scope new_scope
;
837 new_scope
.shifts
= 0;
838 new_scope
.argv
.argc
= argc
;
839 new_scope
.argv
.args
= args
;
845 ret
= grub_script_execute (func
->func
);
849 active_loops
= loops
;
850 replace_scope (old_scope
); /* free any scopes by setparams */
854 /* Helper for grub_script_execute_sourcecode. */
856 grub_script_execute_sourcecode_getline (char **line
,
857 int cont
__attribute__ ((unused
)),
860 const char **source
= data
;
869 p
= grub_strchr (*source
, '\n');
872 *line
= grub_strndup (*source
, p
- *source
);
874 *line
= grub_strdup (*source
);
875 *source
= p
? p
+ 1 : 0;
879 /* Execute a source script. */
881 grub_script_execute_sourcecode (const char *source
)
884 struct grub_script
*parsed_script
;
890 grub_script_execute_sourcecode_getline (&line
, 0, &source
);
891 parsed_script
= grub_script_parse
892 (line
, grub_script_execute_sourcecode_getline
, &source
);
900 ret
= grub_script_execute (parsed_script
);
901 grub_script_free (parsed_script
);
908 /* Execute a source script in new scope. */
910 grub_script_execute_new_scope (const char *source
, int argc
, char **args
)
913 struct grub_script_scope new_scope
;
914 struct grub_script_scope
*old_scope
;
916 new_scope
.argv
.argc
= argc
;
917 new_scope
.argv
.args
= args
;
923 ret
= grub_script_execute_sourcecode (source
);
929 /* Execute a single command line. */
931 grub_script_execute_cmdline (struct grub_script_cmd
*cmd
)
933 struct grub_script_cmdline
*cmdline
= (struct grub_script_cmdline
*) cmd
;
934 grub_command_t grubcmd
;
936 grub_script_function_t func
= 0;
938 char *cmdname
, *cmdstring
;
939 int argc
, offset
= 0, cmdlen
= 0;
943 struct grub_script_argv argv
= { 0, 0, 0 };
945 /* Lookup the command. */
946 if (grub_script_arglist_to_argv (cmdline
->arglist
, &argv
) || ! argv
.args
|| ! argv
.args
[0])
949 for (i
= 0; i
< argv
.argc
; i
++)
951 cmdlen
+= grub_strlen (argv
.args
[i
]) + 1;
954 cmdstring
= grub_malloc (cmdlen
);
957 return grub_error (GRUB_ERR_OUT_OF_MEMORY
,
958 N_("cannot allocate command buffer"));
961 for (i
= 0; i
< argv
.argc
; i
++)
963 offset
+= grub_snprintf (cmdstring
+ offset
, cmdlen
- offset
, "%s ",
966 cmdstring
[cmdlen
- 1] = '\0';
967 grub_verify_string (cmdstring
, GRUB_VERIFY_COMMAND
);
968 grub_free (cmdstring
);
970 argc
= argv
.argc
- 1;
971 args
= argv
.args
+ 1;
972 cmdname
= argv
.args
[0];
973 if (grub_strcmp (cmdname
, "!") == 0)
975 if (argv
.argc
< 2 || ! argv
.args
[1])
977 grub_script_argv_free (&argv
);
978 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
979 N_("no command is specified"));
983 argc
= argv
.argc
- 2;
984 args
= argv
.args
+ 2;
985 cmdname
= argv
.args
[1];
987 grubcmd
= grub_command_find (cmdname
);
990 grub_errno
= GRUB_ERR_NONE
;
992 /* It's not a GRUB command, try all functions. */
993 func
= grub_script_function_find (cmdname
);
996 /* As a last resort, try if it is an assignment. */
997 char *assign
= grub_strdup (cmdname
);
998 char *eq
= grub_strchr (assign
, '=');
1002 /* This was set because the command was not found. */
1003 grub_errno
= GRUB_ERR_NONE
;
1005 /* Create two strings and set the variable. */
1008 grub_script_env_set (assign
, eq
);
1012 grub_snprintf (errnobuf
, sizeof (errnobuf
), "%d", grub_errno
);
1013 grub_script_env_set ("?", errnobuf
);
1015 grub_script_argv_free (&argv
);
1016 grub_print_error ();
1022 /* Execute the GRUB command or function. */
1025 if (grub_extractor_level
&& !(grubcmd
->flags
1026 & GRUB_COMMAND_FLAG_EXTRACTOR
))
1027 ret
= grub_error (GRUB_ERR_EXTRACTOR
,
1028 "%s isn't allowed to execute in an extractor",
1030 else if ((grubcmd
->flags
& GRUB_COMMAND_FLAG_BLOCKS
) &&
1031 (grubcmd
->flags
& GRUB_COMMAND_FLAG_EXTCMD
))
1032 ret
= grub_extcmd_dispatcher (grubcmd
, argc
, args
, argv
.script
);
1034 ret
= (grubcmd
->func
) (grubcmd
, argc
, args
);
1037 ret
= grub_script_function_call (func
, argc
, args
);
1041 if (ret
== GRUB_ERR_TEST_FAILURE
)
1042 grub_errno
= ret
= GRUB_ERR_NONE
;
1043 else if (ret
== GRUB_ERR_NONE
)
1044 ret
= grub_error (GRUB_ERR_TEST_FAILURE
, N_("false"));
1047 grub_print_error ();
1048 ret
= GRUB_ERR_NONE
;
1052 /* Free arguments. */
1053 grub_script_argv_free (&argv
);
1055 if (grub_errno
== GRUB_ERR_TEST_FAILURE
)
1056 grub_errno
= GRUB_ERR_NONE
;
1058 grub_print_error ();
1060 grub_snprintf (errnobuf
, sizeof (errnobuf
), "%d", ret
);
1061 grub_env_set ("?", errnobuf
);
1066 /* Execute a block of one or more commands. */
1068 grub_script_execute_cmdlist (struct grub_script_cmd
*list
)
1071 struct grub_script_cmd
*cmd
;
1073 /* Loop over every command and execute it. */
1074 for (cmd
= list
->next
; cmd
; cmd
= cmd
->next
)
1079 ret
= grub_script_execute_cmd (cmd
);
1081 if (function_return
)
1088 /* Execute an if statement. */
1090 grub_script_execute_cmdif (struct grub_script_cmd
*cmd
)
1094 struct grub_script_cmdif
*cmdif
= (struct grub_script_cmdif
*) cmd
;
1096 /* Check if the commands results in a true or a false. The value is
1097 read from the env variable `?'. */
1098 ret
= grub_script_execute_cmd (cmdif
->exec_to_evaluate
);
1099 if (function_return
)
1102 result
= grub_env_get ("?");
1103 grub_errno
= GRUB_ERR_NONE
;
1105 /* Execute the `if' or the `else' part depending on the value of
1107 if (result
&& ! grub_strcmp (result
, "0"))
1108 return grub_script_execute_cmd (cmdif
->exec_on_true
);
1110 return grub_script_execute_cmd (cmdif
->exec_on_false
);
1113 /* Execute a for statement. */
1115 grub_script_execute_cmdfor (struct grub_script_cmd
*cmd
)
1119 struct grub_script_argv argv
= { 0, 0, 0 };
1120 struct grub_script_cmdfor
*cmdfor
= (struct grub_script_cmdfor
*) cmd
;
1122 if (grub_script_arglist_to_argv (cmdfor
->words
, &argv
))
1127 for (i
= 0; i
< argv
.argc
; i
++)
1129 if (is_continue
&& active_breaks
== 1)
1132 if (! active_breaks
)
1134 grub_script_env_set (cmdfor
->name
->str
, argv
.args
[i
]);
1135 result
= grub_script_execute_cmd (cmdfor
->list
);
1136 if (function_return
)
1145 grub_script_argv_free (&argv
);
1149 /* Execute a "while" or "until" command. */
1151 grub_script_execute_cmdwhile (struct grub_script_cmd
*cmd
)
1154 struct grub_script_cmdwhile
*cmdwhile
= (struct grub_script_cmdwhile
*) cmd
;
1158 result
= grub_script_execute_cmd (cmdwhile
->cond
);
1159 if (function_return
)
1162 if (cmdwhile
->until
? !result
: result
)
1165 result
= grub_script_execute_cmd (cmdwhile
->list
);
1166 if (function_return
)
1169 if (active_breaks
== 1 && is_continue
)
1175 } while (1); /* XXX Put a check for ^C here */
1184 /* Execute any GRUB pre-parsed command or script. */
1186 grub_script_execute (struct grub_script
*script
)
1191 return grub_script_execute_cmd (script
->cmd
);