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 first entry number from the value of the environment variable NAME,
86 which is a space-separated list of non-negative integers. The entry number
87 which is returned is stripped from the value of NAME. If no entry number
88 can be found, -1 is returned. */
90 get_and_remove_first_entry_number (const char *name
)
96 val
= grub_env_get (name
);
102 entry
= (int) grub_strtoul (val
, &tail
, 0);
104 if (grub_errno
== GRUB_ERR_NONE
)
106 /* Skip whitespace to find the next digit. */
107 while (*tail
&& grub_isspace (*tail
))
109 grub_env_set (name
, tail
);
113 grub_env_unset (name
);
114 grub_errno
= GRUB_ERR_NONE
;
123 /* Run a menu entry. */
125 grub_menu_execute_entry(grub_menu_entry_t entry
)
127 grub_parser_execute ((char *) entry
->sourcecode
);
129 if (grub_errno
== GRUB_ERR_NONE
&& grub_loader_is_loaded ())
130 /* Implicit execution of boot, only if something is loaded. */
131 grub_command_execute ("boot", 0, 0);
134 /* Execute ENTRY from the menu MENU, falling back to entries specified
135 in the environment variable "fallback" if it fails. CALLBACK is a
136 pointer to a struct of function pointers which are used to allow the
137 caller provide feedback to the user. */
139 grub_menu_execute_with_fallback (grub_menu_t menu
,
140 grub_menu_entry_t entry
,
141 grub_menu_execute_callback_t callback
,
146 callback
->notify_booting (entry
, callback_data
);
148 grub_menu_execute_entry (entry
);
150 /* Deal with fallback entries. */
151 while ((fallback_entry
= get_and_remove_first_entry_number ("fallback"))
155 grub_errno
= GRUB_ERR_NONE
;
157 entry
= grub_menu_get_entry (menu
, fallback_entry
);
158 callback
->notify_fallback (entry
, callback_data
);
159 grub_menu_execute_entry (entry
);
160 /* If the function call to execute the entry returns at all, then this is
161 taken to indicate a boot failure. For menu entries that do something
162 other than actually boot an operating system, this could assume
163 incorrectly that something failed. */
166 callback
->notify_failure (callback_data
);