2009-02-03 Felix Zielcke <fzielcke@z-51.de>
[grub2/phcoder/solaris.git] / normal / execute.c
blob35b7a4be19307759cbd4682d9b27d2974e3b3300
1 /* execute.c -- Execute a GRUB script. */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2005,2007,2008,2009 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/normal.h>
23 #include <grub/arg.h>
24 #include <grub/env.h>
25 #include <grub/script.h>
27 static grub_err_t
28 grub_script_execute_cmd (struct grub_script_cmd *cmd)
30 if (cmd == 0)
31 return 0;
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. */
38 static char *
39 grub_script_execute_argument_to_string (struct grub_script_arg *arg)
41 int size = 0;
42 char *val;
43 char *chararg;
44 struct grub_script_arg *argi;
46 /* First determine the size of the argument. */
47 for (argi = arg; argi; argi = argi->next)
49 if (argi->type == 1)
51 val = grub_env_get (argi->str);
52 if (val)
53 size += grub_strlen (val);
55 else
56 size += grub_strlen (argi->str);
59 /* Create the argument. */
60 chararg = grub_malloc (size + 1);
61 if (! chararg)
62 return 0;
64 *chararg = '\0';
65 /* First determine the size of the argument. */
66 for (argi = arg; argi; argi = argi->next)
68 if (argi->type == 1)
70 val = grub_env_get (argi->str);
71 if (val)
72 grub_strcat (chararg, val);
74 else
75 grub_strcat (chararg, argi->str);
78 return chararg;
81 /* Execute a single command line. */
82 grub_err_t
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;
87 char **args = 0;
88 int i = 0;
89 grub_command_t grubcmd;
90 struct grub_arg_list *state;
91 struct grub_arg_option *parser;
92 int maxargs = 0;
93 char **parsed_arglist;
94 int numargs;
95 grub_err_t ret = 0;
96 int argcount = 0;
97 grub_script_function_t func = 0;
98 char errnobuf[6];
100 /* Lookup the command. */
101 grubcmd = grub_command_find (cmdline->cmdname);
102 if (! grubcmd)
104 /* Ignore errors. */
105 grub_errno = GRUB_ERR_NONE;
107 /* It's not a GRUB command, try all functions. */
108 func = grub_script_function_find (cmdline->cmdname);
109 if (! func)
111 /* As a last resort, try if it is an assignment. */
112 char *assign = grub_strdup (cmdline->cmdname);
113 char *eq = grub_strchr (assign, '=');
115 if (eq)
117 /* Create two strings and set the variable. */
118 *eq = '\0';
119 eq++;
120 grub_env_set (assign, eq);
122 /* This was set because the command was not found. */
123 grub_errno = GRUB_ERR_NONE;
125 grub_free (assign);
126 return 0;
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)
138 char *str;
139 str = grub_script_execute_argument_to_string (arglist->arg);
140 args[i++] = str;
144 /* Execute the GRUB command or function. */
145 if (grubcmd)
147 /* Count the amount of options the command has. */
148 parser = (struct grub_arg_option *) grubcmd->options;
149 while (parser && (parser++)->doc)
150 maxargs++;
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);
162 else
163 ret = (grubcmd->func) (state, argcount, args);
165 grub_free (state);
167 else
168 ret = grub_script_function_call (func, argcount, args);
170 /* Free arguments. */
171 for (i = 0; i < argcount; i++)
172 grub_free (args[i]);
173 grub_free (args);
175 grub_sprintf (errnobuf, "%d", ret);
176 grub_env_set ("?", errnobuf);
178 return ret;
181 /* Execute a block of one or more commands. */
182 grub_err_t
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);
191 return 0;
194 /* Execute an if statement. */
195 grub_err_t
196 grub_script_execute_cmdif (struct grub_script_cmd *cmd)
198 struct grub_script_cmdif *cmdif = (struct grub_script_cmdif *) cmd;
199 char *result;
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
207 `?'. */
208 if (result && ! grub_strcmp (result, "0"))
209 return grub_script_execute_cmd (cmdif->exec_on_true);
210 else
211 return grub_script_execute_cmd (cmdif->exec_on_false);
214 /* Execute the menu entry generate statement. */
215 grub_err_t
216 grub_script_execute_menuentry (struct grub_script_cmd *cmd)
218 struct grub_script_cmd_menuentry *cmd_menuentry;
219 struct grub_script_arglist *arglist;
220 struct grub_script *script;
221 char **args = 0;
222 int argcount = 0;
223 int i = 0;
225 cmd_menuentry = (struct grub_script_cmd_menuentry *) cmd;
227 if (cmd_menuentry->arglist)
229 argcount = cmd_menuentry->arglist->argcount;
231 /* Create argv from the arguments. */
232 args = grub_malloc (sizeof (char *) * argcount);
234 if (! args)
236 return grub_errno;
239 for (arglist = cmd_menuentry->arglist; arglist; arglist = arglist->next)
241 char *str;
242 str = grub_script_execute_argument_to_string (arglist->arg);
243 args[i++] = str;
247 /* Parse the menu entry *again*. */
248 script = grub_script_parse ((char *) cmd_menuentry->sourcecode, 0);
250 /* Add new menu entry. */
251 if (script)
253 grub_normal_menu_addentry (argcount, (const char **)args,
254 script, cmd_menuentry->sourcecode);
257 /* Free arguments. */
258 for (i = 0; i < argcount; i++)
259 grub_free (args[i]);
260 grub_free (args);
262 return grub_errno;
267 /* Execute any GRUB pre-parsed command or script. */
268 grub_err_t
269 grub_script_execute (struct grub_script *script)
271 if (script == 0)
272 return 0;
274 return grub_script_execute_cmd (script->cmd);