1 /* execute.c -- Execute a GRUB script. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2005,2007 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>
22 #include <grub/normal.h>
25 #include <grub/script.h>
28 grub_script_execute_cmd (struct grub_script_cmd
*cmd
)
33 return cmd
->exec (cmd
);
36 /* Parse ARG and return the textual representation. Add strings are
37 concatenated and all values of the variables are filled in. */
39 grub_script_execute_argument_to_string (struct grub_script_arg
*arg
)
44 struct grub_script_arg
*argi
;
46 /* First determine the size of the argument. */
47 for (argi
= arg
; argi
; argi
= argi
->next
)
51 val
= grub_env_get (argi
->str
);
53 size
+= grub_strlen (val
);
56 size
+= grub_strlen (argi
->str
);
59 /* Create the argument. */
60 chararg
= grub_malloc (size
+ 1);
65 /* First determine the size of the argument. */
66 for (argi
= arg
; argi
; argi
= argi
->next
)
70 val
= grub_env_get (argi
->str
);
72 grub_strcat (chararg
, val
);
75 grub_strcat (chararg
, argi
->str
);
81 /* Execute a single command line. */
83 grub_script_execute_cmdline (struct grub_script_cmd
*cmd
)
85 struct grub_script_cmdline
*cmdline
= (struct grub_script_cmdline
*) cmd
;
86 struct grub_script_arglist
*arglist
;
89 grub_command_t grubcmd
;
90 struct grub_arg_list
*state
;
91 struct grub_arg_option
*parser
;
93 char **parsed_arglist
;
97 grub_script_function_t func
= 0;
100 /* Lookup the command. */
101 grubcmd
= grub_command_find (cmdline
->cmdname
);
105 grub_errno
= GRUB_ERR_NONE
;
107 /* It's not a GRUB command, try all functions. */
108 func
= grub_script_function_find (cmdline
->cmdname
);
111 /* As a last resort, try if it is an assignment. */
112 char *assign
= grub_strdup (cmdline
->cmdname
);
113 char *eq
= grub_strchr (assign
, '=');
117 /* Create two strings and set the variable. */
120 grub_env_set (assign
, eq
);
122 /* This was set because the command was not found. */
123 grub_errno
= GRUB_ERR_NONE
;
130 if (cmdline
->arglist
)
132 argcount
= cmdline
->arglist
->argcount
;
134 /* Create argv from the arguments. */
135 args
= grub_malloc (sizeof (char *) * argcount
);
136 for (arglist
= cmdline
->arglist
; arglist
; arglist
= arglist
->next
)
139 str
= grub_script_execute_argument_to_string (arglist
->arg
);
144 /* Execute the GRUB command or function. */
147 /* Count the amount of options the command has. */
148 parser
= (struct grub_arg_option
*) grubcmd
->options
;
149 while (parser
&& (parser
++)->doc
)
152 /* Set up the option state. */
153 state
= grub_malloc (sizeof (struct grub_arg_list
) * maxargs
);
154 grub_memset (state
, 0, sizeof (struct grub_arg_list
) * maxargs
);
156 /* Start the command. */
157 if (! (grubcmd
->flags
& GRUB_COMMAND_FLAG_NO_ARG_PARSE
))
159 if (grub_arg_parse (grubcmd
, argcount
, args
, state
, &parsed_arglist
, &numargs
))
160 ret
= (grubcmd
->func
) (state
, numargs
, parsed_arglist
);
163 ret
= (grubcmd
->func
) (state
, argcount
, args
);
168 ret
= grub_script_function_call (func
, argcount
, args
);
170 /* Free arguments. */
171 for (i
= 0; i
< argcount
; i
++)
175 grub_sprintf (errnobuf
, "%d", ret
);
176 grub_env_set ("?", errnobuf
);
181 /* Execute a block of one or more commands. */
183 grub_script_execute_cmdblock (struct grub_script_cmd
*cmd
)
185 struct grub_script_cmdblock
*cmdblock
= (struct grub_script_cmdblock
*) cmd
;
187 /* Loop over every command and execute it. */
188 for (cmd
= cmdblock
->cmdlist
; cmd
; cmd
= cmd
->next
)
189 grub_script_execute_cmd (cmd
);
194 /* Execute an if statement. */
196 grub_script_execute_cmdif (struct grub_script_cmd
*cmd
)
198 struct grub_script_cmdif
*cmdif
= (struct grub_script_cmdif
*) cmd
;
201 /* Check if the commands results in a true or a false. The value is
202 read from the env variable `?'. */
203 grub_script_execute_cmd (cmdif
->exec_to_evaluate
);
204 result
= grub_env_get ("?");
206 /* Execute the `if' or the `else' part depending on the value of
208 if (result
&& ! grub_strcmp (result
, "0"))
209 return grub_script_execute_cmd (cmdif
->exec_on_true
);
211 return grub_script_execute_cmd (cmdif
->exec_on_false
);
214 /* Execute the menu entry generate statement. */
216 grub_script_execute_menuentry (struct grub_script_cmd
*cmd
)
218 struct grub_script_cmd_menuentry
*cmd_menuentry
;
220 struct grub_script
*script
;
222 cmd_menuentry
= (struct grub_script_cmd_menuentry
*) cmd
;
224 /* The title can contain variables, parse them and generate a string
226 title
= grub_script_execute_argument_to_string (cmd_menuentry
->title
);
230 /* Parse the menu entry *again*. */
231 script
= grub_script_parse ((char *) cmd_menuentry
->sourcecode
, 0);
239 /* XXX: When this fails, the memory should be freed? */
240 return grub_normal_menu_addentry (title
, script
,
241 cmd_menuentry
->sourcecode
);
246 /* Execute any GRUB pre-parsed command or script. */
248 grub_script_execute (struct grub_script
*script
)
253 return grub_script_execute_cmd (script
->cmd
);