1
/* menuentry.c - menuentry command */
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>
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."), "STRING", ARG_TYPE_STRING},
33
N_("Users allowed to boot this entry."), "USERNAME", ARG_TYPE_STRING},
35
N_("Keyboard key for this entry."), "KEY", ARG_TYPE_STRING},
37
N_("Menu entry definition as a string."), "STRING", ARG_TYPE_STRING},
49
{"delete", GRUB_TERM_KEY_DC},
50
{"insert", GRUB_TERM_KEY_INSERT},
51
{"f1", GRUB_TERM_KEY_F1},
52
{"f2", GRUB_TERM_KEY_F2},
53
{"f3", GRUB_TERM_KEY_F3},
54
{"f4", GRUB_TERM_KEY_F4},
55
{"f5", GRUB_TERM_KEY_F5},
56
{"f6", GRUB_TERM_KEY_F6},
57
{"f7", GRUB_TERM_KEY_F7},
58
{"f8", GRUB_TERM_KEY_F8},
59
{"f9", GRUB_TERM_KEY_F9},
60
{"f10", GRUB_TERM_KEY_F10},
61
{"f11", GRUB_TERM_KEY_F11},
62
{"f12", GRUB_TERM_KEY_F12},
65
/* Add a menu entry to the current menu context (as given by the environment
66
variable data slot `menu'). As the configuration file is read, the script
67
parser calls this when a menu entry is to be created. */
69
grub_normal_add_menu_entry (int argc, const char **args, char **classes,
70
const char *users, const char *hotkey,
71
const char *prefix, const char *sourcecode,
75
char **menu_args = NULL;
76
char *menu_users = NULL;
77
char *menu_title = NULL;
78
char *menu_sourcecode = NULL;
79
struct grub_menu_entry_class *menu_classes = NULL;
82
grub_menu_entry_t *last;
84
menu = grub_env_get_menu ();
86
return grub_error (GRUB_ERR_MENU, "no menu context");
88
last = &menu->entry_list;
90
menu_sourcecode = grub_xasprintf ("%s%s", prefix ?: "", sourcecode);
91
if (! menu_sourcecode)
97
for (i = 0; classes[i]; i++); /* count # of menuentry classes */
98
menu_classes = grub_zalloc (sizeof (struct grub_menu_entry_class) * i);
102
for (i = 0; classes[i]; i++)
104
menu_classes[i].name = grub_strdup (classes[i]);
105
if (! menu_classes[i].name)
107
menu_classes[i].next = classes[i + 1] ? &menu_classes[i + 1] : NULL;
113
menu_users = grub_strdup (users);
121
for (i = 0; i < ARRAY_SIZE (hotkey_aliases); i++)
122
if (grub_strcmp (hotkey, hotkey_aliases[i].name) == 0)
124
menu_hotkey = hotkey_aliases[i].key;
127
if (i == ARRAY_SIZE (hotkey_aliases))
128
menu_hotkey = hotkey[0];
133
grub_error (GRUB_ERR_MENU, "menuentry is missing title");
137
menu_title = grub_strdup (args[0]);
141
/* Save argc, args to pass as parameters to block arg later. */
142
menu_args = grub_malloc (sizeof (char*) * (argc + 1));
148
for (i = 0; i < argc; i++)
150
menu_args[i] = grub_strdup (args[i]);
154
menu_args[argc] = NULL;
157
/* Add the menu entry at the end of the list. */
159
last = &(*last)->next;
161
*last = grub_zalloc (sizeof (**last));
165
(*last)->title = menu_title;
166
(*last)->hotkey = menu_hotkey;
167
(*last)->classes = menu_classes;
169
(*last)->restricted = 1;
170
(*last)->users = menu_users;
171
(*last)->argc = argc;
172
(*last)->args = menu_args;
173
(*last)->sourcecode = menu_sourcecode;
174
(*last)->submenu = submenu;
177
return GRUB_ERR_NONE;
181
grub_free (menu_sourcecode);
184
for (i = 0; menu_classes && menu_classes[i].name; i++)
185
grub_free (menu_classes[i].name);
186
grub_free (menu_classes);
191
for (i = 0; menu_args && menu_args[i]; i++)
192
grub_free (menu_args[i]);
193
grub_free (menu_args);
196
grub_free (menu_users);
197
grub_free (menu_title);
202
setparams_prefix (int argc, char **args)
208
grub_size_t len = 10;
209
static const char *escape_characters = "\"\\";
211
auto char *strescpy (char *, const char *, const char *);
212
char * strescpy (char *d, const char *s, const char *escapes)
216
if (grub_strchr (escapes, *s))
224
/* Count resulting string length */
225
for (i = 0; i < argc; i++)
227
len += 3; /* 3 = 1 space + 2 quotes */
230
len += grub_strchr (escape_characters, *p++) ? 2 : 1;
233
result = grub_malloc (len + 2);
237
grub_strcpy (result, "setparams");
240
for (j = 0; j < argc; j++)
244
i = strescpy (result + i, args[j], escape_characters) - result;
253
grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
262
return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing arguments");
264
if (ctxt->state[3].set && ctxt->script)
265
return grub_error (GRUB_ERR_BAD_ARGUMENT, "multiple menuentry definitions");
267
if (! ctxt->state[3].set && ! ctxt->script)
268
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menuentry definition");
271
return grub_normal_add_menu_entry (argc, (const char **) args,
272
ctxt->state[0].args, ctxt->state[1].arg,
273
ctxt->state[2].arg, 0,
275
ctxt->extcmd->cmd->name[0] == 's');
277
src = args[argc - 1];
278
args[argc - 1] = NULL;
280
len = grub_strlen(src);
284
prefix = setparams_prefix (argc - 1, args);
288
r = grub_normal_add_menu_entry (argc - 1, (const char **) args,
289
ctxt->state[0].args, ctxt->state[1].arg,
290
ctxt->state[2].arg, prefix, src + 1,
291
ctxt->extcmd->cmd->name[0] == 's');
294
args[argc - 1] = src;
299
static grub_extcmd_t cmd, cmd_sub;
302
grub_menu_init (void)
304
cmd = grub_register_extcmd ("menuentry", grub_cmd_menuentry,
305
GRUB_COMMAND_FLAG_BLOCKS
306
| GRUB_COMMAND_FLAG_EXTRACTOR,
307
N_("BLOCK"), N_("Define a menuentry."), options);
308
cmd_sub = grub_register_extcmd ("submenu", grub_cmd_menuentry,
309
GRUB_COMMAND_FLAG_BLOCKS
310
| GRUB_COMMAND_FLAG_EXTRACTOR,
311
N_("BLOCK"), N_("Define a submenu."),
316
grub_menu_fini (void)
318
grub_unregister_extcmd (cmd);
319
grub_unregister_extcmd (cmd_sub);