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
#define GRUB_DEFAULT_HISTORY_SIZE 50
38
static int nested_level = 0;
39
int grub_normal_exit_level = 0;
41
/* Read a line from the file FILE. */
43
grub_file_getline (grub_file_t file)
51
/* Initially locate some space. */
52
cmdline = grub_malloc (max_len);
58
if (grub_file_read (file, &c, 1) != 1)
61
/* Skip all carriage returns. */
65
/* Replace tabs with spaces. */
69
/* The previous is a backslash, then... */
72
/* If it is a newline, replace it with a space and continue. */
77
/* Go back to overwrite the backslash. */
90
if (! grub_isspace (c))
97
char *old_cmdline = cmdline;
98
max_len = max_len * 2;
99
cmdline = grub_realloc (cmdline, max_len);
102
grub_free (old_cmdline);
116
/* If the buffer is empty, don't return anything at all. */
127
grub_normal_free_menu (grub_menu_t menu)
129
grub_menu_entry_t entry = menu->entry_list;
133
grub_menu_entry_t next_entry = entry->next;
135
grub_free ((void *) entry->title);
136
grub_free ((void *) entry->sourcecode);
141
grub_env_unset_menu ();
145
read_config_file (const char *config)
149
auto grub_err_t getline (char **line, int cont);
150
grub_err_t getline (char **line, int cont __attribute__ ((unused)))
156
*line = buf = grub_file_getline (file);
166
return GRUB_ERR_NONE;
171
newmenu = grub_env_get_menu ();
174
newmenu = grub_zalloc (sizeof (*newmenu));
178
grub_env_set_menu (newmenu);
181
/* Try to open the config file. */
182
file = grub_file_open (config);
190
/* Print an error, if any. */
192
grub_errno = GRUB_ERR_NONE;
194
if ((getline (&line, 0)) || (! line))
197
grub_normal_parse_line (line, getline);
201
grub_file_close (file);
206
/* Initialize the screen. */
208
grub_normal_init_page (struct grub_term_output *term)
212
const char *msg = _("GNU GRUB version %s");
214
grub_uint32_t *unicode_msg;
215
grub_uint32_t *last_position;
217
grub_term_cls (term);
219
msg_formatted = grub_xasprintf (msg, PACKAGE_VERSION);
223
msg_len = grub_utf8_to_ucs4_alloc (msg_formatted,
224
&unicode_msg, &last_position);
225
grub_free (msg_formatted);
232
posx = grub_getstringwidth (unicode_msg, last_position, term);
233
posx = (grub_term_width (term) - posx) / 2;
234
grub_term_gotoxy (term, posx, 1);
236
grub_print_ucs4 (unicode_msg, last_position, 0, 0, term);
237
grub_putcode ('\n', term);
238
grub_putcode ('\n', term);
239
grub_free (unicode_msg);
243
read_lists (const char *val)
245
if (! grub_no_autoload)
247
read_command_list (val);
249
read_crypto_list (val);
250
read_terminal_list (val);
255
read_lists_hook (struct grub_env_var *var __attribute__ ((unused)),
259
return val ? grub_strdup (val) : NULL;
262
/* Read the config file CONFIG and execute the menu interface or
263
the command line interface if BATCH is false. */
265
grub_normal_execute (const char *config, int nested, int batch)
267
grub_menu_t menu = 0;
272
prefix = grub_env_get ("prefix");
274
grub_register_variable_hook ("prefix", NULL, read_lists_hook);
275
grub_command_execute ("parser.grub", 0, 0);
280
menu = read_config_file (config);
282
/* Ignore any error. */
283
grub_errno = GRUB_ERR_NONE;
288
if (menu && menu->size)
290
grub_show_menu (menu, nested);
292
grub_normal_free_menu (menu);
297
/* This starts the normal mode. */
299
grub_enter_normal_mode (const char *config)
302
grub_normal_execute (config, 0, 0);
303
grub_cmdline_run (0);
305
if (grub_normal_exit_level)
306
grub_normal_exit_level--;
309
/* Enter normal mode from rescue mode. */
311
grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
312
int argc, char *argv[])
316
/* Guess the config filename. It is necessary to make CONFIG static,
317
so that it won't get broken by longjmp. */
321
prefix = grub_env_get ("prefix");
324
config = grub_xasprintf ("%s/grub.cfg", prefix);
328
grub_enter_normal_mode (config);
332
grub_enter_normal_mode (0);
335
grub_enter_normal_mode (argv[0]);
341
/* Exit from normal mode to rescue mode. */
343
grub_cmd_normal_exit (struct grub_command *cmd __attribute__ ((unused)),
344
int argc __attribute__ ((unused)),
345
char *argv[] __attribute__ ((unused)))
347
if (nested_level <= grub_normal_exit_level)
348
return grub_error (GRUB_ERR_BAD_ARGUMENT, "not in normal environment");
349
grub_normal_exit_level++;
350
return GRUB_ERR_NONE;
354
grub_normal_reader_init (int nested)
356
struct grub_term_output *term;
357
const char *msg = _("Minimal BASH-like line editing is supported. For "
358
"the first word, TAB lists possible command completions. Anywhere "
359
"else TAB lists possible device or file completions. %s");
360
const char *msg_esc = _("ESC at any time exits.");
363
msg_formatted = grub_xasprintf (msg, nested ? msg_esc : "");
367
FOR_ACTIVE_TERM_OUTPUTS(term)
369
grub_normal_init_page (term);
370
grub_term_setcursor (term, 1);
372
grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN, term);
373
grub_putcode ('\n', term);
374
grub_putcode ('\n', term);
376
grub_free (msg_formatted);
382
grub_normal_read_line_real (char **line, int cont, int nested)
396
*line = grub_cmdline_get (prompt);
412
grub_normal_read_line (char **line, int cont)
414
return grub_normal_read_line_real (line, cont, 0);
418
grub_cmdline_run (int nested)
420
grub_err_t err = GRUB_ERR_NONE;
422
err = grub_auth_check_authentication (NULL);
427
grub_errno = GRUB_ERR_NONE;
431
grub_normal_reader_init (nested);
437
if (grub_normal_exit_level)
440
/* Print an error, if any. */
442
grub_errno = GRUB_ERR_NONE;
444
grub_normal_read_line_real (&line, 0, nested);
448
grub_normal_parse_line (line, grub_normal_read_line);
454
grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)),
457
grub_set_more ((*val == '1'));
458
return grub_strdup (val);
463
grub_mini_cmd_clear (struct grub_command *cmd __attribute__ ((unused)),
464
int argc __attribute__ ((unused)),
465
char *argv[] __attribute__ ((unused)))
471
static grub_command_t cmd_clear;
473
static void (*grub_xputs_saved) (const char *str);
475
GRUB_MOD_INIT(normal)
477
/* Previously many modules depended on gzio. Be nice to user and load it. */
478
grub_dl_load ("gzio");
480
grub_normal_auth_init ();
481
grub_context_init ();
485
grub_xputs_saved = grub_xputs;
486
grub_xputs = grub_xputs_normal;
488
/* Normal mode shouldn't be unloaded. */
493
grub_register_command ("clear", grub_mini_cmd_clear,
494
0, N_("Clear the screen."));
496
grub_set_history (GRUB_DEFAULT_HISTORY_SIZE);
498
grub_register_variable_hook ("pager", 0, grub_env_write_pager);
500
/* Register a command "normal" for the rescue mode. */
501
grub_register_command ("normal", grub_cmd_normal,
502
0, N_("Enter normal mode."));
503
grub_register_command ("normal_exit", grub_cmd_normal_exit,
504
0, N_("Exit from normal mode."));
506
/* Reload terminal colors when these variables are written to. */
507
grub_register_variable_hook ("color_normal", NULL, grub_env_write_color_normal);
508
grub_register_variable_hook ("color_highlight", NULL, grub_env_write_color_highlight);
510
/* Preserve hooks after context changes. */
511
grub_env_export ("color_normal");
512
grub_env_export ("color_highlight");
514
/* Set default color names. */
515
grub_env_set ("color_normal", "white/black");
516
grub_env_set ("color_highlight", "black/white");
519
GRUB_MOD_FINI(normal)
521
grub_context_fini ();
524
grub_normal_auth_fini ();
526
grub_xputs = grub_xputs_saved;
528
grub_set_history (0);
529
grub_register_variable_hook ("pager", 0, 0);
530
grub_fs_autoload_hook = 0;
531
grub_unregister_command (cmd_clear);