]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/commands/menuentry.c
Update languages.json (Turkish) (#1077)
[Ventoy.git] / GRUB2 / MOD_SRC / grub-2.04 / grub-core / commands / menuentry.c
1 /* menuentry.c - menuentry command */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2010 Free Software Foundation, Inc.
5 *
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.
10 *
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.
15 *
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/>.
18 */
19
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>
27
28 static const struct grub_arg_option options[] =
29 {
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}
47 };
48
49 static struct
50 {
51 const char *name;
52 int key;
53 } hotkey_aliases[] =
54 {
55 {"backspace", GRUB_TERM_BACKSPACE},
56 {"tab", GRUB_TERM_TAB},
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},
71 };
72
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, int *index, struct bls_entry *bls)
82 {
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;
90
91 grub_menu_t menu;
92 grub_menu_entry_t *last;
93
94 menu = grub_env_get_menu ();
95 if (! menu)
96 return grub_error (GRUB_ERR_MENU, "no menu context");
97
98 last = &menu->entry_list;
99
100 menu_sourcecode = grub_xasprintf ("%s%s", prefix ?: "", sourcecode);
101 if (! menu_sourcecode)
102 return grub_errno;
103
104 if (classes && classes[0])
105 {
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;
112
113 for (i = 0; classes[i]; i++)
114 {
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;
119 }
120 }
121
122 if (users)
123 {
124 menu_users = grub_strdup (users);
125 if (! menu_users)
126 goto fail;
127 }
128
129 if (hotkey)
130 {
131 unsigned i;
132 for (i = 0; i < ARRAY_SIZE (hotkey_aliases); i++)
133 if (grub_strcmp (hotkey, hotkey_aliases[i].name) == 0)
134 {
135 menu_hotkey = hotkey_aliases[i].key;
136 break;
137 }
138 if (i == ARRAY_SIZE (hotkey_aliases))
139 menu_hotkey = hotkey[0];
140 }
141
142 if (! argc)
143 {
144 grub_error (GRUB_ERR_MENU, "menuentry is missing title");
145 goto fail;
146 }
147
148 menu_title = grub_strdup (args[0]);
149 if (! menu_title)
150 goto fail;
151
152 grub_dprintf ("menu", "id:\"%s\"\n", id);
153 grub_dprintf ("menu", "title:\"%s\"\n", menu_title);
154 menu_id = grub_strdup (id ? : menu_title);
155 if (! menu_id)
156 goto fail;
157 grub_dprintf ("menu", "menu_id:\"%s\"\n", menu_id);
158
159 /* Save argc, args to pass as parameters to block arg later. */
160 menu_args = grub_malloc (sizeof (char*) * (argc + 1));
161 if (! menu_args)
162 goto fail;
163
164 {
165 int i;
166 for (i = 0; i < argc; i++)
167 {
168 menu_args[i] = grub_strdup (args[i]);
169 if (! menu_args[i])
170 goto fail;
171 }
172 menu_args[argc] = NULL;
173 }
174
175 /* Add the menu entry at the end of the list. */
176 int ind=0;
177 while (*last)
178 {
179 ind++;
180 last = &(*last)->next;
181 }
182
183 *last = grub_zalloc (sizeof (**last));
184 if (! *last)
185 goto fail;
186
187 (*last)->title = menu_title;
188 (*last)->id = menu_id;
189 (*last)->hotkey = menu_hotkey;
190 (*last)->classes = menu_classes;
191 if (menu_users)
192 (*last)->restricted = 1;
193 (*last)->users = menu_users;
194 (*last)->argc = argc;
195 (*last)->args = menu_args;
196 (*last)->sourcecode = menu_sourcecode;
197 (*last)->submenu = submenu;
198 (*last)->bls = bls;
199
200 menu->size++;
201 if (index)
202 *index = ind;
203 return GRUB_ERR_NONE;
204
205 fail:
206
207 grub_free (menu_sourcecode);
208 {
209 int i;
210 for (i = 0; menu_classes && menu_classes[i].name; i++)
211 grub_free (menu_classes[i].name);
212 grub_free (menu_classes);
213 }
214
215 {
216 int i;
217 for (i = 0; menu_args && menu_args[i]; i++)
218 grub_free (menu_args[i]);
219 grub_free (menu_args);
220 }
221
222 grub_free (menu_users);
223 grub_free (menu_title);
224 grub_free (menu_id);
225 return grub_errno;
226 }
227
228 static char *
229 setparams_prefix (int argc, char **args)
230 {
231 int i;
232 int j;
233 char *p;
234 char *result;
235 grub_size_t len = 10;
236
237 /* Count resulting string length */
238 for (i = 0; i < argc; i++)
239 {
240 len += 3; /* 3 = 1 space + 2 quotes */
241 p = args[i];
242 while (*p)
243 len += (*p++ == '\'' ? 3 : 1);
244 }
245
246 result = grub_malloc (len + 2);
247 if (! result)
248 return 0;
249
250 grub_strcpy (result, "setparams");
251 p = result + 9;
252
253 for (j = 0; j < argc; j++)
254 {
255 *p++ = ' ';
256 *p++ = '\'';
257 p = grub_strchrsub (p, args[j], '\'', "'\\''");
258 *p++ = '\'';
259 }
260 *p++ = '\n';
261 *p = '\0';
262 return result;
263 }
264
265 static grub_err_t
266 grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
267 {
268 char ch;
269 char *src;
270 char *prefix;
271 unsigned len;
272 grub_err_t r;
273 const char *users;
274
275 if (! argc)
276 return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing arguments");
277
278 if (ctxt->state[3].set && ctxt->script)
279 return grub_error (GRUB_ERR_BAD_ARGUMENT, "multiple menuentry definitions");
280
281 if (! ctxt->state[3].set && ! ctxt->script)
282 return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menuentry definition");
283
284 if (ctxt->state[1].set)
285 users = ctxt->state[1].arg;
286 else if (ctxt->state[5].set)
287 users = NULL;
288 else
289 users = "";
290
291 if (! ctxt->script)
292 return grub_normal_add_menu_entry (argc, (const char **) args,
293 (ctxt->state[0].set ? ctxt->state[0].args
294 : NULL),
295 ctxt->state[4].arg,
296 users,
297 ctxt->state[2].arg, 0,
298 ctxt->state[3].arg,
299 ctxt->extcmd->cmd->name[0] == 's',
300 NULL, NULL);
301
302 src = args[argc - 1];
303 args[argc - 1] = NULL;
304
305 len = grub_strlen(src);
306 ch = src[len - 1];
307 src[len - 1] = '\0';
308
309 prefix = setparams_prefix (argc - 1, args);
310 if (! prefix)
311 return grub_errno;
312
313 r = grub_normal_add_menu_entry (argc - 1, (const char **) args,
314 ctxt->state[0].args, ctxt->state[4].arg,
315 users,
316 ctxt->state[2].arg, prefix, src + 1,
317 ctxt->extcmd->cmd->name[0] == 's', NULL,
318 NULL);
319
320 src[len - 1] = ch;
321 args[argc - 1] = src;
322 grub_free (prefix);
323 return r;
324 }
325
326 static grub_extcmd_t cmd, cmd_sub;
327
328 void
329 grub_menu_init (void)
330 {
331 cmd = grub_register_extcmd ("menuentry", grub_cmd_menuentry,
332 GRUB_COMMAND_FLAG_BLOCKS
333 | GRUB_COMMAND_ACCEPT_DASH
334 | GRUB_COMMAND_FLAG_EXTRACTOR,
335 N_("BLOCK"), N_("Define a menu entry."), options);
336 cmd_sub = grub_register_extcmd ("submenu", grub_cmd_menuentry,
337 GRUB_COMMAND_FLAG_BLOCKS
338 | GRUB_COMMAND_ACCEPT_DASH
339 | GRUB_COMMAND_FLAG_EXTRACTOR,
340 N_("BLOCK"), N_("Define a submenu."),
341 options);
342 }
343
344 void
345 grub_menu_fini (void)
346 {
347 grub_unregister_extcmd (cmd);
348 grub_unregister_extcmd (cmd_sub);
349 }