1 /* main.c - the normal mode main routine */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2000,2001,2002,2003,2005,2006,2007,2008 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/rescue.h>
24 #include <grub/misc.h>
25 #include <grub/file.h>
27 #include <grub/term.h>
29 #include <grub/parser.h>
30 #include <grub/script.h>
32 grub_jmp_buf grub_exit_env
;
34 static grub_fs_module_list_t fs_module_list
= 0;
36 #define GRUB_DEFAULT_HISTORY_SIZE 50
38 /* Read a line from the file FILE. */
40 get_line (grub_file_t file
)
49 /* Initially locate some space. */
50 cmdline
= grub_malloc (max_len
);
56 if (grub_file_read (file
, &c
, 1) != 1)
59 /* Skip all carriage returns. */
63 /* Replace tabs with spaces. */
67 /* The previous is a backslash, then... */
70 /* If it is a newline, replace it with a space and continue. */
75 /* Go back to overwrite the backslash. */
95 else if (! grub_isspace (c
))
102 char *old_cmdline
= cmdline
;
103 max_len
= max_len
* 2;
104 cmdline
= grub_realloc (cmdline
, max_len
);
107 grub_free (old_cmdline
);
121 /* If the buffer is empty, don't return anything at all. */
132 free_menu (grub_menu_t menu
)
134 grub_menu_entry_t entry
= menu
->entry_list
;
138 grub_menu_entry_t next_entry
= entry
->next
;
140 grub_script_free (entry
->commands
);
141 grub_free ((void *) entry
->title
);
142 grub_free ((void *) entry
->sourcecode
);
147 grub_env_unset_data_slot ("menu");
151 grub_normal_menu_addentry (const char *title
, struct grub_script
*script
,
152 const char *sourcecode
)
154 const char *menutitle
;
155 const char *menusourcecode
;
157 grub_menu_entry_t
*last
;
159 menu
= grub_env_get_data_slot("menu");
161 return grub_error (GRUB_ERR_MENU
, "no menu context");
163 last
= &menu
->entry_list
;
165 menusourcecode
= grub_strdup (sourcecode
);
166 if (! menusourcecode
)
169 menutitle
= grub_strdup (title
);
172 grub_free ((void *) menusourcecode
);
176 /* Add the menu entry at the end of the list. */
178 last
= &(*last
)->next
;
180 *last
= grub_malloc (sizeof (**last
));
183 grub_free ((void *) menutitle
);
184 grub_free ((void *) menusourcecode
);
188 (*last
)->commands
= script
;
189 (*last
)->title
= menutitle
;
191 (*last
)->sourcecode
= menusourcecode
;
195 return GRUB_ERR_NONE
;
199 read_config_file (const char *config
, int nested
)
202 auto grub_err_t
getline (char **line
);
206 grub_err_t
getline (char **line
)
210 *line
= get_line (file
);
214 return GRUB_ERR_NONE
;
219 newmenu
= grub_env_get_data_slot ("menu");
221 if (nested
|| ! newmenu
)
223 newmenu
= grub_malloc (sizeof (*newmenu
));
227 newmenu
->entry_list
= 0;
230 /* Try to open the config file. */
231 file
= grub_file_open (config
);
235 grub_env_set_data_slot ("menu", newmenu
);
239 struct grub_script
*parsed_script
;
243 cmdline
= get_line (file
);
247 startline
= ++currline
;
249 /* Execute the script, line for line. */
250 parsed_script
= grub_script_parse (cmdline
, getline
);
256 grub_printf ("(line %d-%d)\n", startline
, currline
);
261 /* Execute the command(s). */
262 grub_script_execute (parsed_script
);
265 grub_errno
= GRUB_ERR_NONE
;
267 /* The parsed script was executed, throw it away. */
268 grub_script_free (parsed_script
);
271 grub_file_close (file
);
274 grub_wait_after_message ();
279 /* This starts the normal mode. */
281 grub_enter_normal_mode (const char *config
)
283 if (grub_setjmp (grub_exit_env
) == 0)
284 grub_normal_execute (config
, 0);
287 /* Initialize the screen. */
289 grub_normal_init_page (void)
293 GNU GRUB version %s\n\n",
297 /* Read the file command.lst for auto-loading. */
299 read_command_list (void)
303 prefix
= grub_env_get ("prefix");
308 filename
= grub_malloc (grub_strlen (prefix
) + sizeof ("/command.lst"));
313 grub_sprintf (filename
, "%s/command.lst", prefix
);
314 file
= grub_file_open (filename
);
321 char *buf
= get_line (file
);
326 if (! grub_isgraph (buf
[0]))
329 p
= grub_strchr (buf
, ':');
337 if (! grub_isgraph (*p
))
340 cmd
= grub_register_command (buf
, 0,
341 GRUB_COMMAND_FLAG_NOT_LOADED
,
349 cmd
->module_name
= grub_strdup (p
);
350 if (! cmd
->module_name
)
351 grub_unregister_command (buf
);
355 grub_file_close (file
);
358 grub_free (filename
);
363 grub_errno
= GRUB_ERR_NONE
;
366 /* The auto-loading hook for filesystems. */
368 autoload_fs_module (void)
370 grub_fs_module_list_t p
;
372 while ((p
= fs_module_list
) != 0)
374 if (! grub_dl_get (p
->name
) && grub_dl_load (p
->name
))
377 fs_module_list
= p
->next
;
385 /* Read the file fs.lst for auto-loading. */
391 prefix
= grub_env_get ("prefix");
396 filename
= grub_malloc (grub_strlen (prefix
) + sizeof ("/fs.lst"));
401 grub_sprintf (filename
, "%s/fs.lst", prefix
);
402 file
= grub_file_open (filename
);
410 grub_fs_module_list_t fs_mod
;
412 buf
= get_line (file
);
417 q
= buf
+ grub_strlen (buf
) - 1;
420 while (grub_isspace (*p
))
423 while (p
< q
&& grub_isspace (*q
))
426 /* If the line is empty, skip it. */
430 fs_mod
= grub_malloc (sizeof (*fs_mod
));
434 fs_mod
->name
= grub_strdup (p
);
441 fs_mod
->next
= fs_module_list
;
442 fs_module_list
= fs_mod
;
445 grub_file_close (file
);
448 grub_free (filename
);
453 grub_errno
= GRUB_ERR_NONE
;
456 grub_fs_autoload_hook
= autoload_fs_module
;
459 /* Read the config file CONFIG and execute the menu interface or
460 the command-line interface. */
462 grub_normal_execute (const char *config
, int nested
)
464 grub_menu_t menu
= 0;
466 read_command_list ();
471 menu
= read_config_file (config
, nested
);
473 /* Ignore any error. */
474 grub_errno
= GRUB_ERR_NONE
;
477 if (menu
&& menu
->size
)
479 grub_menu_run (menu
, nested
);
484 grub_cmdline_run (nested
);
487 /* Enter normal mode from rescue mode. */
489 grub_rescue_cmd_normal (int argc
, char *argv
[])
493 /* Guess the config filename. It is necessary to make CONFIG static,
494 so that it won't get broken by longjmp. */
498 prefix
= grub_env_get ("prefix");
501 config
= grub_malloc (grub_strlen (prefix
) + sizeof ("/grub.cfg"));
505 grub_sprintf (config
, "%s/grub.cfg", prefix
);
506 grub_enter_normal_mode (config
);
510 grub_enter_normal_mode (0);
513 grub_enter_normal_mode (argv
[0]);
516 GRUB_MOD_INIT(normal
)
518 /* Normal mode shouldn't be unloaded. */
522 grub_set_history (GRUB_DEFAULT_HISTORY_SIZE
);
524 /* Register a command "normal" for the rescue mode. */
525 grub_rescue_register_command ("normal", grub_rescue_cmd_normal
,
526 "enter normal mode");
528 /* Reload terminal colors when these variables are written to. */
529 grub_register_variable_hook ("color_normal", NULL
, grub_env_write_color_normal
);
530 grub_register_variable_hook ("color_highlight", NULL
, grub_env_write_color_highlight
);
532 /* Preserve hooks after context changes. */
533 grub_env_export ("color_normal");
534 grub_env_export ("color_highlight");
536 /* This registers some built-in commands. */
537 grub_command_init ();
540 GRUB_MOD_FINI(normal
)
542 grub_set_history (0);
543 grub_rescue_unregister_command ("normal");