Merge branch 'makefile' into haiku
[grub2/phcoder.git] / normal / menu.c
blob07d465f65db0dbca783d8c8d722100b1f5b35785
1 /* menu.c - General supporting functionality for menus. */
2 /*
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>
23 #include <grub/mm.h>
24 #include <grub/time.h>
25 #include <grub/env.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. */
31 grub_menu_entry_t
32 grub_menu_get_entry (grub_menu_t menu, int no)
34 grub_menu_entry_t e;
36 for (e = menu->entry_list; e && no > 0; e = e->next, no--)
39 return e;
42 /* Return the current timeout. If the variable "timeout" is not set or
43 invalid, return -1. */
44 int
45 grub_menu_get_timeout (void)
47 char *val;
48 int timeout;
50 val = grub_env_get ("timeout");
51 if (! val)
52 return -1;
54 grub_error_push ();
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;
63 timeout = -1;
66 grub_error_pop ();
68 return timeout;
71 /* Set current timeout in the variable "timeout". */
72 void
73 grub_menu_set_timeout (int timeout)
75 /* Ignore TIMEOUT if it is zero, because it will be unset really soon. */
76 if (timeout > 0)
78 char buf[16];
80 grub_sprintf (buf, "%d", timeout);
81 grub_env_set ("timeout", buf);
85 /* Get the entry number from the environment variable NAME. */
86 static int
87 get_entry_number (const char *name)
89 char *val;
90 int entry;
92 val = grub_env_get (name);
93 if (! val)
94 return -1;
96 grub_error_push ();
98 entry = (int) grub_strtoul (val, 0, 0);
100 if (grub_errno != GRUB_ERR_NONE)
102 grub_errno = GRUB_ERR_NONE;
103 entry = -1;
106 grub_error_pop ();
108 return entry;
111 /* Get the default menu entry index. */
113 grub_menu_get_default_entry_index (grub_menu_t menu)
115 int i;
117 i = get_entry_number ("default");
119 /* If DEFAULT_ENTRY is not within the menu entries, fall back to
120 the first entry. */
121 if (i < 0 || i >= menu->size)
122 i = 0;
124 return i;
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. */
131 static int
132 get_and_remove_first_entry_number (const char *name)
134 char *val;
135 char *tail;
136 int entry;
138 val = grub_env_get (name);
139 if (! val)
140 return -1;
142 grub_error_push ();
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))
150 tail++;
151 grub_env_set (name, tail);
153 else
155 grub_env_unset (name);
156 grub_errno = GRUB_ERR_NONE;
157 entry = -1;
160 grub_error_pop ();
162 return entry;
165 /* Run a menu entry. */
166 void
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. */
180 void
181 grub_menu_execute_with_fallback (grub_menu_t menu,
182 grub_menu_entry_t entry,
183 grub_menu_execute_callback_t callback,
184 void *callback_data)
186 int fallback_entry;
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"))
194 >= 0)
196 grub_print_error ();
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);