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
)
96 for (i
= 0; classes
[i
]; i
++); /* count # of menuentry classes */
97 menu_classes
= grub_zalloc (sizeof (struct grub_menu_entry_class
) * i
);
101 for (i
= 0; classes
[i
]; i
++)
103 menu_classes
[i
].name
= grub_strdup (classes
[i
]);
104 if (! menu_classes
[i
].name
)
106 menu_classes
[i
].next
= classes
[i
+ 1] ? &menu_classes
[i
+ 1] : NULL
;
112 menu_users
= grub_strdup (users
);
119 for (i
= 0; i
< ARRAY_SIZE (hotkey_aliases
); i
++)
120 if (grub_strcmp (hotkey
, hotkey_aliases
[i
].name
) == 0)
122 menu_hotkey
= hotkey_aliases
[i
].key
;
125 if (i
== ARRAY_SIZE (hotkey_aliases
))
126 menu_hotkey
= hotkey
[0];
131 grub_error (GRUB_ERR_MENU
, "menuentry is missing title");
135 menu_title
= grub_strdup (args
[0]);
139 /* Save argc, args to pass as parameters to block arg later. */
140 menu_args
= grub_malloc (sizeof (char*) * (argc
+ 1));
144 for (i
= 0; i
< argc
; i
++)
146 menu_args
[i
] = grub_strdup (args
[i
]);
150 menu_args
[argc
] = NULL
;
152 /* Add the menu entry at the end of the list. */
154 last
= &(*last
)->next
;
156 *last
= grub_zalloc (sizeof (**last
));
160 (*last
)->title
= menu_title
;
161 (*last
)->hotkey
= menu_hotkey
;
162 (*last
)->classes
= menu_classes
;
164 (*last
)->restricted
= 1;
165 (*last
)->users
= menu_users
;
166 (*last
)->argc
= argc
;
167 (*last
)->args
= menu_args
;
168 (*last
)->sourcecode
= menu_sourcecode
;
171 return GRUB_ERR_NONE
;
175 grub_free (menu_sourcecode
);
176 for (i
= 0; menu_classes
&& menu_classes
[i
].name
; i
++)
177 grub_free (menu_classes
[i
].name
);
178 grub_free (menu_classes
);
180 for (i
= 0; menu_args
&& menu_args
[i
]; i
++)
181 grub_free (menu_args
[i
]);
182 grub_free (menu_args
);
184 grub_free (menu_users
);
185 grub_free (menu_title
);
190 setparams_prefix (int argc
, char **args
)
196 grub_size_t len
= 10;
197 static const char *escape_characters
= "\"\\";
199 auto char *strescpy (char *, const char *, const char *);
200 char * strescpy (char *d
, const char *s
, const char *escapes
)
204 if (grub_strchr (escapes
, *s
))
212 /* Count resulting string length */
213 for (i
= 0; i
< argc
; i
++)
215 len
+= 3; /* 3 = 1 space + 2 quotes */
218 len
+= grub_strchr (escape_characters
, *p
++) ? 2 : 1;
221 result
= grub_malloc (len
+ 2);
225 grub_strcpy (result
, "setparams");
228 for (j
= 0; j
< argc
; j
++)
232 i
= strescpy (result
+ i
, args
[j
], escape_characters
) - result
;
241 grub_cmd_menuentry (grub_extcmd_context_t ctxt
, int argc
, char **args
)
250 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "missing arguments");
252 if (ctxt
->state
[3].set
&& ctxt
->script
)
253 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "multiple menuentry definitions");
255 if (! ctxt
->state
[3].set
&& ! ctxt
->script
)
256 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "no menuentry definition");
259 return grub_normal_add_menu_entry (argc
, (const char **) args
,
260 ctxt
->state
[0].args
, ctxt
->state
[1].arg
,
261 ctxt
->state
[2].arg
, 0,
264 src
= args
[argc
- 1];
265 args
[argc
- 1] = NULL
;
267 len
= grub_strlen(src
);
271 prefix
= setparams_prefix (argc
- 1, args
);
275 r
= grub_normal_add_menu_entry (argc
- 1, (const char **) args
,
276 ctxt
->state
[0].args
, ctxt
->state
[1].arg
,
277 ctxt
->state
[2].arg
, prefix
, src
+ 1);
280 args
[argc
- 1] = src
;
285 static grub_extcmd_t cmd
;
288 grub_menu_init (void)
290 cmd
= grub_register_extcmd ("menuentry", grub_cmd_menuentry
,
291 GRUB_COMMAND_FLAG_BLOCKS
,
292 N_("BLOCK"), N_("Define a menuentry."), options
);
296 grub_menu_fini (void)
298 grub_unregister_extcmd (cmd
);