1 /* main.c - the normal mode main routine */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2000,2001,2002,2003,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/kernel.h>
21 #include <grub/normal.h>
23 #include <grub/misc.h>
24 #include <grub/file.h>
26 #include <grub/term.h>
28 #include <grub/parser.h>
29 #include <grub/reader.h>
30 #include <grub/menu_viewer.h>
31 #include <grub/auth.h>
32 #include <grub/i18n.h>
33 #include <grub/charset.h>
34 #include <grub/script_sh.h>
36 GRUB_MOD_LICENSE ("GPLv3+");
38 #define GRUB_DEFAULT_HISTORY_SIZE 50
40 static int nested_level
= 0;
41 int grub_normal_exit_level
= 0;
44 grub_normal_free_menu (grub_menu_t menu
)
46 grub_menu_entry_t entry
= menu
->entry_list
;
50 grub_menu_entry_t next_entry
= entry
->next
;
55 struct grub_menu_entry_class
*class;
56 for (class = entry
->classes
; class; class = class->next
)
57 grub_free (class->name
);
58 grub_free (entry
->classes
);
63 for (i
= 0; entry
->args
[i
]; i
++)
64 grub_free (entry
->args
[i
]);
65 grub_free (entry
->args
);
68 grub_free ((void *) entry
->id
);
69 grub_free ((void *) entry
->users
);
70 grub_free ((void *) entry
->title
);
71 grub_free ((void *) entry
->sourcecode
);
77 grub_env_unset_menu ();
80 /* Helper for read_config_file. */
82 read_config_file_getline (char **line
, int cont
__attribute__ ((unused
)),
85 grub_file_t file
= data
;
91 *line
= buf
= grub_file_getline (file
);
101 return GRUB_ERR_NONE
;
105 read_config_file (const char *config
)
108 char *old_file
= 0, *old_dir
= 0;
109 char *config_dir
, *ptr
= 0;
114 newmenu
= grub_env_get_menu ();
117 newmenu
= grub_zalloc (sizeof (*newmenu
));
121 grub_env_set_menu (newmenu
);
124 /* Try to open the config file. */
125 file
= grub_file_open (config
);
129 ctmp
= grub_env_get ("config_file");
131 old_file
= grub_strdup (ctmp
);
132 ctmp
= grub_env_get ("config_directory");
134 old_dir
= grub_strdup (ctmp
);
137 grub_env_set ("config_file", config
);
138 config_dir
= grub_strdup (config
);
142 /* $root is guranteed to be defined, otherwise open above would fail */
143 config_dir
= grub_xasprintf ("(%s)%s", grub_env_get ("root"), config
);
145 grub_env_set ("config_file", config_dir
);
149 ptr
= grub_strrchr (config_dir
, '/');
152 grub_env_set ("config_directory", config_dir
);
153 grub_free (config_dir
);
156 grub_env_export ("config_file");
157 grub_env_export ("config_directory");
163 /* Print an error, if any. */
165 grub_errno
= GRUB_ERR_NONE
;
167 if ((read_config_file_getline (&line
, 0, file
)) || (! line
))
170 grub_normal_parse_line (line
, read_config_file_getline
, file
);
175 grub_env_set ("config_file", old_file
);
177 grub_env_unset ("config_file");
179 grub_env_set ("config_directory", old_dir
);
181 grub_env_unset ("config_directory");
182 grub_free (old_file
);
185 grub_file_close (file
);
190 /* Initialize the screen. */
192 grub_normal_init_page (struct grub_term_output
*term
,
195 grub_ssize_t msg_len
;
198 grub_uint32_t
*unicode_msg
;
199 grub_uint32_t
*last_position
;
201 grub_term_cls (term
);
203 msg_formatted
= grub_xasprintf (_("GNU GRUB version %s"), PACKAGE_VERSION
);
207 msg_len
= grub_utf8_to_ucs4_alloc (msg_formatted
,
208 &unicode_msg
, &last_position
);
209 grub_free (msg_formatted
);
216 posx
= grub_getstringwidth (unicode_msg
, last_position
, term
);
217 posx
= ((int) grub_term_width (term
) - posx
) / 2;
220 grub_term_gotoxy (term
, (struct grub_term_coordinate
) { posx
, y
});
222 grub_print_ucs4 (unicode_msg
, last_position
, 0, 0, term
);
223 grub_putcode ('\n', term
);
224 grub_putcode ('\n', term
);
225 grub_free (unicode_msg
);
229 read_lists (const char *val
)
231 if (! grub_no_modules
)
233 read_command_list (val
);
235 read_crypto_list (val
);
236 read_terminal_list (val
);
238 grub_gettext_reread_prefix (val
);
242 read_lists_hook (struct grub_env_var
*var
__attribute__ ((unused
)),
246 return val
? grub_strdup (val
) : NULL
;
249 /* Read the config file CONFIG and execute the menu interface or
250 the command line interface if BATCH is false. */
252 grub_normal_execute (const char *config
, int nested
, int batch
)
254 grub_menu_t menu
= 0;
259 prefix
= grub_env_get ("prefix");
261 grub_register_variable_hook ("prefix", NULL
, read_lists_hook
);
264 grub_boot_time ("Executing config file");
268 menu
= read_config_file (config
);
270 /* Ignore any error. */
271 grub_errno
= GRUB_ERR_NONE
;
274 grub_boot_time ("Executed config file");
278 if (menu
&& menu
->size
)
281 grub_boot_time ("Entering menu");
282 grub_show_menu (menu
, nested
, 0);
284 grub_normal_free_menu (menu
);
289 /* This starts the normal mode. */
291 grub_enter_normal_mode (const char *config
)
293 grub_boot_time ("Entering normal mode");
295 grub_normal_execute (config
, 0, 0);
296 grub_boot_time ("Entering shell");
297 grub_cmdline_run (0);
299 if (grub_normal_exit_level
)
300 grub_normal_exit_level
--;
301 grub_boot_time ("Exiting normal mode");
304 /* Enter normal mode from rescue mode. */
306 grub_cmd_normal (struct grub_command
*cmd
__attribute__ ((unused
)),
307 int argc
, char *argv
[])
311 /* Guess the config filename. It is necessary to make CONFIG static,
312 so that it won't get broken by longjmp. */
316 prefix
= grub_env_get ("prefix");
319 config
= grub_xasprintf ("%s/grub.cfg", prefix
);
323 grub_enter_normal_mode (config
);
327 grub_enter_normal_mode (0);
330 grub_enter_normal_mode (argv
[0]);
336 /* Exit from normal mode to rescue mode. */
338 grub_cmd_normal_exit (struct grub_command
*cmd
__attribute__ ((unused
)),
339 int argc
__attribute__ ((unused
)),
340 char *argv
[] __attribute__ ((unused
)))
342 if (nested_level
<= grub_normal_exit_level
)
343 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "not in normal environment");
344 grub_normal_exit_level
++;
345 return GRUB_ERR_NONE
;
349 grub_normal_reader_init (int nested
)
351 struct grub_term_output
*term
;
352 const char *msg_esc
= _("ESC at any time exits.");
355 msg_formatted
= grub_xasprintf (_("Minimal BASH-like line editing is supported. For "
356 "the first word, TAB lists possible command completions. Anywhere "
357 "else TAB lists possible device or file completions. %s"),
358 nested
? msg_esc
: "");
362 FOR_ACTIVE_TERM_OUTPUTS(term
)
364 grub_normal_init_page (term
, 1);
365 grub_term_setcursor (term
, 1);
367 if (grub_term_width (term
) > 3 + STANDARD_MARGIN
+ 20)
368 grub_print_message_indented (msg_formatted
, 3, STANDARD_MARGIN
, term
);
370 grub_print_message_indented (msg_formatted
, 0, 0, term
);
371 grub_putcode ('\n', term
);
372 grub_putcode ('\n', term
);
373 grub_putcode ('\n', term
);
375 grub_free (msg_formatted
);
381 grub_normal_read_line_real (char **line
, int cont
, int nested
)
385 static int displayed_intro
;
387 if (! displayed_intro
)
389 grub_normal_reader_init (nested
);
395 /* TRANSLATORS: it's command line prompt. */
398 /* TRANSLATORS: it's command line prompt. */
406 *line
= grub_cmdline_get (prompt
);
421 grub_normal_read_line (char **line
, int cont
,
422 void *data
__attribute__ ((unused
)))
424 return grub_normal_read_line_real (line
, cont
, 0);
428 grub_cmdline_run (int nested
)
430 grub_err_t err
= GRUB_ERR_NONE
;
432 err
= grub_auth_check_authentication (NULL
);
437 grub_errno
= GRUB_ERR_NONE
;
442 grub_normal_reader_init (nested
);
449 if (grub_normal_exit_level
)
452 /* Print an error, if any. */
454 grub_errno
= GRUB_ERR_NONE
;
456 grub_normal_read_line_real (&line
, 0, nested
);
460 grub_normal_parse_line (line
, grub_normal_read_line
, NULL
);
466 grub_env_write_pager (struct grub_env_var
*var
__attribute__ ((unused
)),
469 grub_set_more ((*val
== '1'));
470 return grub_strdup (val
);
475 grub_mini_cmd_clear (struct grub_command
*cmd
__attribute__ ((unused
)),
476 int argc
__attribute__ ((unused
)),
477 char *argv
[] __attribute__ ((unused
)))
483 static grub_command_t cmd_clear
;
485 static void (*grub_xputs_saved
) (const char *str
);
486 static const char *features
[] = {
487 "feature_chainloader_bpb", "feature_ntldr", "feature_platform_search_hint",
488 "feature_default_font_path", "feature_all_video_module",
489 "feature_menuentry_id", "feature_menuentry_options", "feature_200_final",
490 "feature_nativedisk_cmd", "feature_timeout_style"
493 GRUB_MOD_INIT(normal
)
497 grub_boot_time ("Preparing normal module");
499 /* Previously many modules depended on gzio. Be nice to user and load it. */
500 grub_dl_load ("gzio");
503 grub_normal_auth_init ();
504 grub_context_init ();
508 grub_xputs_saved
= grub_xputs
;
509 grub_xputs
= grub_xputs_normal
;
511 /* Normal mode shouldn't be unloaded. */
516 grub_register_command ("clear", grub_mini_cmd_clear
,
517 0, N_("Clear the screen."));
519 grub_set_history (GRUB_DEFAULT_HISTORY_SIZE
);
521 grub_register_variable_hook ("pager", 0, grub_env_write_pager
);
522 grub_env_export ("pager");
524 /* Register a command "normal" for the rescue mode. */
525 grub_register_command ("normal", grub_cmd_normal
,
526 0, N_("Enter normal mode."));
527 grub_register_command ("normal_exit", grub_cmd_normal_exit
,
528 0, N_("Exit from normal mode."));
530 /* Reload terminal colors when these variables are written to. */
531 grub_register_variable_hook ("color_normal", NULL
, grub_env_write_color_normal
);
532 grub_register_variable_hook ("color_highlight", NULL
, grub_env_write_color_highlight
);
534 /* Preserve hooks after context changes. */
535 grub_env_export ("color_normal");
536 grub_env_export ("color_highlight");
538 /* Set default color names. */
539 grub_env_set ("color_normal", "light-gray/black");
540 grub_env_set ("color_highlight", "black/light-gray");
542 for (i
= 0; i
< ARRAY_SIZE (features
); i
++)
544 grub_env_set (features
[i
], "y");
545 grub_env_export (features
[i
]);
547 grub_env_set ("grub_cpu", GRUB_TARGET_CPU
);
548 grub_env_export ("grub_cpu");
549 grub_env_set ("grub_platform", GRUB_PLATFORM
);
550 grub_env_export ("grub_platform");
552 grub_boot_time ("Normal module prepared");
555 GRUB_MOD_FINI(normal
)
557 grub_context_fini ();
560 grub_normal_auth_fini ();
562 grub_xputs
= grub_xputs_saved
;
564 grub_set_history (0);
565 grub_register_variable_hook ("pager", 0, 0);
566 grub_fs_autoload_hook
= 0;
567 grub_unregister_command (cmd_clear
);