1 /* main.c - the normal mode main routine */
3 * PUPA -- Preliminary Universal Programming Architecture for GRUB
4 * Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
5 * Copyright (C) 2002,2003 Yoshinori K. Okuji <okuji@enbug.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <pupa/kernel.h>
23 #include <pupa/normal.h>
25 #include <pupa/rescue.h>
26 #include <pupa/misc.h>
27 #include <pupa/file.h>
29 #include <pupa/term.h>
31 pupa_jmp_buf pupa_exit_env
;
33 /* Read a line from the file FILE. */
35 get_line (pupa_file_t file
, char cmdline
[], int max_len
)
44 if (pupa_file_read (file
, &c
, 1) != 1)
47 /* Skip all carriage returns. */
51 /* Replace tabs with spaces. */
55 /* The previous is a backslash, then... */
58 /* If it is a newline, replace it with a space and continue. */
63 /* Go back to overwrite the backslash. */
83 else if (! pupa_isspace (c
))
102 free_menu (pupa_menu_t menu
)
104 pupa_menu_entry_t entry
= menu
->entry_list
;
108 pupa_menu_entry_t next_entry
= entry
->next
;
109 pupa_command_list_t cmd
= entry
->command_list
;
113 pupa_command_list_t next_cmd
= cmd
->next
;
115 pupa_free ((void *) cmd
->command
);
119 pupa_free ((void *) entry
->title
);
126 /* Read the config file CONFIG and return a menu. If no entry is present,
129 read_config_file (const char *config
)
132 static char cmdline
[PUPA_MAX_CMDLINE
];
134 pupa_menu_entry_t
*next_entry
, cur_entry
= 0;
135 pupa_command_list_t
*next_cmd
, cur_cmd
;
137 /* Try to open the config file. */
138 file
= pupa_file_open (config
);
142 /* Initialize the menu. */
143 menu
= (pupa_menu_t
) pupa_malloc (sizeof (*menu
));
146 pupa_file_close (file
);
149 menu
->default_entry
= 0;
150 menu
->fallback_entry
= -1;
153 menu
->entry_list
= 0;
155 next_entry
= &(menu
->entry_list
);
158 /* Read each line. */
159 while (get_line (file
, cmdline
, sizeof (cmdline
)))
163 cmd
= pupa_command_find (cmdline
);
164 pupa_errno
= PUPA_ERR_NONE
;
167 pupa_printf ("Unknown command `%s' is ignored.\n", cmdline
);
171 if (cmd
->flags
& PUPA_COMMAND_FLAG_TITLE
)
175 cur_entry
= (pupa_menu_entry_t
) pupa_malloc (sizeof (*cur_entry
));
179 p
= pupa_strchr (cmdline
, ' ');
181 cur_entry
->title
= pupa_strdup (p
);
183 cur_entry
->title
= pupa_strdup ("");
185 if (! cur_entry
->title
)
187 pupa_free (cur_entry
);
192 cur_entry
->command_list
= 0;
195 *next_entry
= cur_entry
;
196 next_entry
= &(cur_entry
->next
);
198 next_cmd
= &(cur_entry
->command_list
);
202 else if (! cur_entry
)
204 /* Run the command if possible. */
205 if (cmd
->flags
& PUPA_COMMAND_FLAG_MENU
)
207 pupa_command_execute (cmdline
);
209 pupa_errno
= PUPA_ERR_NONE
;
213 pupa_printf ("Invalid command `%s' is ignored.\n", cmdline
);
219 cur_cmd
= (pupa_command_list_t
) pupa_malloc (sizeof (*cur_cmd
));
223 cur_cmd
->command
= pupa_strdup (cmdline
);
224 if (! cur_cmd
->command
)
233 next_cmd
= &(cur_cmd
->next
);
241 pupa_file_close (file
);
243 /* If no entry was found or any error occurred, return NULL. */
244 if (menu
->size
== 0 || pupa_errno
!= PUPA_ERR_NONE
)
250 /* Check values of the default entry and the fallback one. */
251 if (menu
->fallback_entry
>= menu
->size
)
252 menu
->fallback_entry
= -1;
254 if (menu
->default_entry
< 0 || menu
->default_entry
>= menu
->size
)
256 if (menu
->fallback_entry
< 0)
257 menu
->default_entry
= 0;
260 menu
->default_entry
= menu
->fallback_entry
;
261 menu
->fallback_entry
= -1;
268 /* This starts the normal mode. */
270 pupa_enter_normal_mode (const char *config
)
272 if (pupa_setjmp (pupa_exit_env
) == 0)
273 pupa_normal_execute (config
, 0);
276 /* Initialize the screen. */
278 pupa_normal_init_page (void)
282 PUPA version %s\n\n",
286 /* Read the config file CONFIG and execute the menu interface or
287 the command-line interface. */
289 pupa_normal_execute (const char *config
, int nested
)
291 pupa_menu_t menu
= 0;
295 menu
= read_config_file (config
);
297 /* Ignore any error. */
298 pupa_errno
= PUPA_ERR_NONE
;
302 pupa_menu_run (menu
, nested
);
304 pupa_cmdline_run (nested
);
307 /* Enter normal mode from rescue mode. */
309 pupa_rescue_cmd_normal (int argc
, char *argv
[])
313 /* Guess the config filename. */
317 prefix
= pupa_dl_get_prefix ();
320 config
= pupa_malloc (pupa_strlen (prefix
) + sizeof ("/pupa.cfg"));
324 pupa_sprintf (config
, "%s/pupa.cfg", prefix
);
325 pupa_enter_normal_mode (config
);
329 pupa_enter_normal_mode (0);
332 pupa_enter_normal_mode (argv
[0]);
337 /* Normal mode shouldn't be unloaded. */
340 /* Register a command "normal" for the rescue mode. */
341 pupa_rescue_register_command ("normal", pupa_rescue_cmd_normal
,
342 "enter normal mode");
344 /* This registers some built-in commands. */
345 pupa_command_init ();
350 pupa_rescue_unregister_command ("normal");