1 /* menu.c - General supporting functionality for menus. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2003,2004,2005,2006,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/normal.h>
21 #include <grub/misc.h>
22 #include <grub/loader.h>
24 #include <grub/time.h>
26 #include <grub/menu_viewer.h>
27 #include <grub/command.h>
28 #include <grub/parser.h>
30 /* Get a menu entry by its index in the entry list. */
32 grub_menu_get_entry (grub_menu_t menu
, int no
)
36 for (e
= menu
->entry_list
; e
&& no
> 0; e
= e
->next
, no
--)
42 /* Return the current timeout. If the variable "timeout" is not set or
43 invalid, return -1. */
45 grub_menu_get_timeout (void)
50 val
= grub_env_get ("timeout");
56 timeout
= (int) grub_strtoul (val
, 0, 0);
58 /* If the value is invalid, unset the variable. */
59 if (grub_errno
!= GRUB_ERR_NONE
)
61 grub_env_unset ("timeout");
62 grub_errno
= GRUB_ERR_NONE
;
71 /* Set current timeout in the variable "timeout". */
73 grub_menu_set_timeout (int timeout
)
75 /* Ignore TIMEOUT if it is zero, because it will be unset really soon. */
80 grub_sprintf (buf
, "%d", timeout
);
81 grub_env_set ("timeout", buf
);
85 /* Get the entry number from the environment variable NAME. */
87 get_entry_number (const char *name
)
92 val
= grub_env_get (name
);
98 entry
= (int) grub_strtoul (val
, 0, 0);
100 if (grub_errno
!= GRUB_ERR_NONE
)
102 grub_errno
= GRUB_ERR_NONE
;
111 /* Get the default menu entry index. */
113 grub_menu_get_default_entry_index (grub_menu_t menu
)
117 i
= get_entry_number ("default");
119 /* If DEFAULT_ENTRY is not within the menu entries, fall back to
121 if (i
< 0 || i
>= menu
->size
)
127 /* Get the first entry number from the value of the environment variable NAME,
128 which is a space-separated list of non-negative integers. The entry number
129 which is returned is stripped from the value of NAME. If no entry number
130 can be found, -1 is returned. */
132 get_and_remove_first_entry_number (const char *name
)
138 val
= grub_env_get (name
);
144 entry
= (int) grub_strtoul (val
, &tail
, 0);
146 if (grub_errno
== GRUB_ERR_NONE
)
148 /* Skip whitespace to find the next digit. */
149 while (*tail
&& grub_isspace (*tail
))
151 grub_env_set (name
, tail
);
155 grub_env_unset (name
);
156 grub_errno
= GRUB_ERR_NONE
;
165 /* Run a menu entry. */
167 grub_menu_execute_entry(grub_menu_entry_t entry
)
169 grub_parser_execute ((char *) entry
->sourcecode
);
171 if (grub_errno
== GRUB_ERR_NONE
&& grub_loader_is_loaded ())
172 /* Implicit execution of boot, only if something is loaded. */
173 grub_command_execute ("boot", 0, 0);
176 /* Execute ENTRY from the menu MENU, falling back to entries specified
177 in the environment variable "fallback" if it fails. CALLBACK is a
178 pointer to a struct of function pointers which are used to allow the
179 caller provide feedback to the user. */
181 grub_menu_execute_with_fallback (grub_menu_t menu
,
182 grub_menu_entry_t entry
,
183 grub_menu_execute_callback_t callback
,
188 callback
->notify_booting (entry
, callback_data
);
190 grub_menu_execute_entry (entry
);
192 /* Deal with fallback entries. */
193 while ((fallback_entry
= get_and_remove_first_entry_number ("fallback"))
197 grub_errno
= GRUB_ERR_NONE
;
199 entry
= grub_menu_get_entry (menu
, fallback_entry
);
200 callback
->notify_fallback (entry
, callback_data
);
201 grub_menu_execute_entry (entry
);
202 /* If the function call to execute the entry returns at all, then this is
203 taken to indicate a boot failure. For menu entries that do something
204 other than actually boot an operating system, this could assume
205 incorrectly that something failed. */
208 callback
->notify_failure (callback_data
);