Upgraded GRUB2 to 2.00 release.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / commands / menuentry.c
blob58d4dadf6ee4ec392a09d433802803520704cd7b
1 /* menuentry.c - menuentry command */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 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/types.h>
21 #include <grub/misc.h>
22 #include <grub/err.h>
23 #include <grub/dl.h>
24 #include <grub/extcmd.h>
25 #include <grub/i18n.h>
26 #include <grub/normal.h>
28 static const struct grub_arg_option options[] =
30 {"class", 1, GRUB_ARG_OPTION_REPEATABLE,
31 N_("Menu entry type."), N_("STRING"), ARG_TYPE_STRING},
32 {"users", 2, 0,
33 N_("List of users allowed to boot this entry."), N_("USERNAME[,USERNAME]"),
34 ARG_TYPE_STRING},
35 {"hotkey", 3, 0,
36 N_("Keyboard key to quickly boot this entry."), N_("KEYBOARD_KEY"), ARG_TYPE_STRING},
37 {"source", 4, 0,
38 N_("Use STRING as menu entry body."), N_("STRING"), ARG_TYPE_STRING},
39 {"id", 0, 0, N_("Menu entry identifier."), N_("STRING"), ARG_TYPE_STRING},
40 /* TRANSLATORS: menu entry can either be bootable by anyone or only by
41 handful of users. By default when security is active only superusers can
42 boot a given menu entry. With --unrestricted (this option)
43 anyone can boot it. */
44 {"unrestricted", 0, 0, N_("This entry can be booted by any user."),
45 0, ARG_TYPE_NONE},
46 {0, 0, 0, 0, 0, 0}
49 static struct
51 const char *name;
52 int key;
53 } hotkey_aliases[] =
55 {"backspace", '\b'},
56 {"tab", '\t'},
57 {"delete", GRUB_TERM_KEY_DC},
58 {"insert", GRUB_TERM_KEY_INSERT},
59 {"f1", GRUB_TERM_KEY_F1},
60 {"f2", GRUB_TERM_KEY_F2},
61 {"f3", GRUB_TERM_KEY_F3},
62 {"f4", GRUB_TERM_KEY_F4},
63 {"f5", GRUB_TERM_KEY_F5},
64 {"f6", GRUB_TERM_KEY_F6},
65 {"f7", GRUB_TERM_KEY_F7},
66 {"f8", GRUB_TERM_KEY_F8},
67 {"f9", GRUB_TERM_KEY_F9},
68 {"f10", GRUB_TERM_KEY_F10},
69 {"f11", GRUB_TERM_KEY_F11},
70 {"f12", GRUB_TERM_KEY_F12},
73 /* Add a menu entry to the current menu context (as given by the environment
74 variable data slot `menu'). As the configuration file is read, the script
75 parser calls this when a menu entry is to be created. */
76 grub_err_t
77 grub_normal_add_menu_entry (int argc, const char **args,
78 char **classes, const char *id,
79 const char *users, const char *hotkey,
80 const char *prefix, const char *sourcecode,
81 int submenu)
83 int menu_hotkey = 0;
84 char **menu_args = NULL;
85 char *menu_users = NULL;
86 char *menu_title = NULL;
87 char *menu_sourcecode = NULL;
88 char *menu_id = NULL;
89 struct grub_menu_entry_class *menu_classes = NULL;
91 grub_menu_t menu;
92 grub_menu_entry_t *last;
94 menu = grub_env_get_menu ();
95 if (! menu)
96 return grub_error (GRUB_ERR_MENU, "no menu context");
98 last = &menu->entry_list;
100 menu_sourcecode = grub_xasprintf ("%s%s", prefix ?: "", sourcecode);
101 if (! menu_sourcecode)
102 return grub_errno;
104 if (classes && classes[0])
106 int i;
107 for (i = 0; classes[i]; i++); /* count # of menuentry classes */
108 menu_classes = grub_zalloc (sizeof (struct grub_menu_entry_class)
109 * (i + 1));
110 if (! menu_classes)
111 goto fail;
113 for (i = 0; classes[i]; i++)
115 menu_classes[i].name = grub_strdup (classes[i]);
116 if (! menu_classes[i].name)
117 goto fail;
118 menu_classes[i].next = classes[i + 1] ? &menu_classes[i + 1] : NULL;
122 if (users)
124 menu_users = grub_strdup (users);
125 if (! menu_users)
126 goto fail;
129 if (hotkey)
131 unsigned i;
132 for (i = 0; i < ARRAY_SIZE (hotkey_aliases); i++)
133 if (grub_strcmp (hotkey, hotkey_aliases[i].name) == 0)
135 menu_hotkey = hotkey_aliases[i].key;
136 break;
138 if (i == ARRAY_SIZE (hotkey_aliases))
139 menu_hotkey = hotkey[0];
142 if (! argc)
144 grub_error (GRUB_ERR_MENU, "menuentry is missing title");
145 goto fail;
148 menu_title = grub_strdup (args[0]);
149 if (! menu_title)
150 goto fail;
152 menu_id = grub_strdup (id ? : menu_title);
153 if (! menu_id)
154 goto fail;
156 /* Save argc, args to pass as parameters to block arg later. */
157 menu_args = grub_malloc (sizeof (char*) * (argc + 1));
158 if (! menu_args)
159 goto fail;
162 int i;
163 for (i = 0; i < argc; i++)
165 menu_args[i] = grub_strdup (args[i]);
166 if (! menu_args[i])
167 goto fail;
169 menu_args[argc] = NULL;
172 /* Add the menu entry at the end of the list. */
173 while (*last)
174 last = &(*last)->next;
176 *last = grub_zalloc (sizeof (**last));
177 if (! *last)
178 goto fail;
180 (*last)->title = menu_title;
181 (*last)->id = menu_id;
182 (*last)->hotkey = menu_hotkey;
183 (*last)->classes = menu_classes;
184 if (menu_users)
185 (*last)->restricted = 1;
186 (*last)->users = menu_users;
187 (*last)->argc = argc;
188 (*last)->args = menu_args;
189 (*last)->sourcecode = menu_sourcecode;
190 (*last)->submenu = submenu;
192 menu->size++;
193 return GRUB_ERR_NONE;
195 fail:
197 grub_free (menu_sourcecode);
199 int i;
200 for (i = 0; menu_classes && menu_classes[i].name; i++)
201 grub_free (menu_classes[i].name);
202 grub_free (menu_classes);
206 int i;
207 for (i = 0; menu_args && menu_args[i]; i++)
208 grub_free (menu_args[i]);
209 grub_free (menu_args);
212 grub_free (menu_users);
213 grub_free (menu_title);
214 grub_free (menu_id);
215 return grub_errno;
218 static char *
219 setparams_prefix (int argc, char **args)
221 int i;
222 int j;
223 char *p;
224 char *result;
225 grub_size_t len = 10;
227 /* Count resulting string length */
228 for (i = 0; i < argc; i++)
230 len += 3; /* 3 = 1 space + 2 quotes */
231 p = args[i];
232 while (*p)
233 len += (*p++ == '\'' ? 3 : 1);
236 result = grub_malloc (len + 2);
237 if (! result)
238 return 0;
240 grub_strcpy (result, "setparams");
241 p = result + 9;
243 for (j = 0; j < argc; j++)
245 *p++ = ' ';
246 *p++ = '\'';
247 p = grub_strchrsub (p, args[j], '\'', "'\\''");
248 *p++ = '\'';
250 *p++ = '\n';
251 *p = '\0';
252 return result;
255 static grub_err_t
256 grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
258 char ch;
259 char *src;
260 char *prefix;
261 unsigned len;
262 grub_err_t r;
263 const char *users;
265 if (! argc)
266 return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing arguments");
268 if (ctxt->state[3].set && ctxt->script)
269 return grub_error (GRUB_ERR_BAD_ARGUMENT, "multiple menuentry definitions");
271 if (! ctxt->state[3].set && ! ctxt->script)
272 return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menuentry definition");
274 if (ctxt->state[1].set)
275 users = ctxt->state[1].arg;
276 else if (ctxt->state[5].set)
277 users = NULL;
278 else
279 users = "";
281 if (! ctxt->script)
282 return grub_normal_add_menu_entry (argc, (const char **) args,
283 (ctxt->state[0].set ? ctxt->state[0].args
284 : NULL),
285 ctxt->state[4].arg,
286 users,
287 ctxt->state[2].arg, 0,
288 ctxt->state[3].arg,
289 ctxt->extcmd->cmd->name[0] == 's');
291 src = args[argc - 1];
292 args[argc - 1] = NULL;
294 len = grub_strlen(src);
295 ch = src[len - 1];
296 src[len - 1] = '\0';
298 prefix = setparams_prefix (argc - 1, args);
299 if (! prefix)
300 return grub_errno;
302 r = grub_normal_add_menu_entry (argc - 1, (const char **) args,
303 ctxt->state[0].args, ctxt->state[4].arg,
304 users,
305 ctxt->state[2].arg, prefix, src + 1,
306 ctxt->extcmd->cmd->name[0] == 's');
308 src[len - 1] = ch;
309 args[argc - 1] = src;
310 grub_free (prefix);
311 return r;
314 static grub_extcmd_t cmd, cmd_sub;
316 void
317 grub_menu_init (void)
319 cmd = grub_register_extcmd ("menuentry", grub_cmd_menuentry,
320 GRUB_COMMAND_FLAG_BLOCKS
321 | GRUB_COMMAND_ACCEPT_DASH
322 | GRUB_COMMAND_FLAG_EXTRACTOR,
323 N_("BLOCK"), N_("Define a menu entry."), options);
324 cmd_sub = grub_register_extcmd ("submenu", grub_cmd_menuentry,
325 GRUB_COMMAND_FLAG_BLOCKS
326 | GRUB_COMMAND_ACCEPT_DASH
327 | GRUB_COMMAND_FLAG_EXTRACTOR,
328 N_("BLOCK"), N_("Define a submenu."),
329 options);
332 void
333 grub_menu_fini (void)
335 grub_unregister_extcmd (cmd);
336 grub_unregister_extcmd (cmd_sub);