From a8aa57628e0fe20e54b1558c76f7dee70093e70d Mon Sep 17 00:00:00 2001 From: marco_g Date: Tue, 12 Dec 2006 00:13:55 +0000 Subject: [PATCH] 2006-12-12 Marco Gerards * include/grub/err.h (grub_err_t): Add `GRUB_ERR_MENU'. * kern/env.c (grub_env_unset): Don't free the member `value' when the type is GRUB_ENV_VAR_DATA, in this case it's a user defined pointer. * normal/main.c (current_menu): Removed. (free_menu): Unset the `menu' environment variable. (grub_normal_menu_addentry): Make use of the environment variable `menu', instead of using the global `current_menu'. Allocate memory for the sourcecode of this entry. (read_config_file): New argument `nested', changed all callers. Only in the case of a new context, initialize a new menu. Set the `menu' environment variable. (grub_normal_execute): Don't set and unset the environment variable `menu' here anymore. Only free the menu when leaving the context. * util/i386/pc/biosdisk.c (linux_find_partition): Fixed a memory leak. --- ChangeLog | 23 ++++++++++++++ include/grub/err.h | 1 + kern/env.c | 3 +- normal/main.c | 66 ++++++++++++++++++++++++----------------- util/i386/pc/biosdisk.c | 5 +++- 5 files changed, 69 insertions(+), 29 deletions(-) diff --git a/ChangeLog b/ChangeLog index e74884d84..4a137d1ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2006-12-12 Marco Gerards + + * include/grub/err.h (grub_err_t): Add `GRUB_ERR_MENU'. + + * kern/env.c (grub_env_unset): Don't free the member `value' when + the type is GRUB_ENV_VAR_DATA, in this case it's a user defined + pointer. + + * normal/main.c (current_menu): Removed. + (free_menu): Unset the `menu' environment variable. + (grub_normal_menu_addentry): Make use of the environment variable + `menu', instead of using the global `current_menu'. Allocate + memory for the sourcecode of this entry. + (read_config_file): New argument `nested', changed all callers. + Only in the case of a new context, initialize a new menu. Set the + `menu' environment variable. + (grub_normal_execute): Don't set and unset the environment + variable `menu' here anymore. Only free the menu when leaving the + context. + + * util/i386/pc/biosdisk.c (linux_find_partition): Fixed a memory + leak. + 2006-12-11 Marco Gerards * normal/menu_entry.c (run): Fix off by one bug so the last line diff --git a/include/grub/err.h b/include/grub/err.h index d4013be6c..2a59309c0 100644 --- a/include/grub/err.h +++ b/include/grub/err.h @@ -52,6 +52,7 @@ typedef enum GRUB_ERR_NOT_IMPLEMENTED_YET, GRUB_ERR_SYMLINK_LOOP, GRUB_ERR_BAD_GZIP_DATA, + GRUB_ERR_MENU } grub_err_t; diff --git a/kern/env.c b/kern/env.c index b534e05f2..0e841ef5a 100644 --- a/kern/env.c +++ b/kern/env.c @@ -261,7 +261,8 @@ grub_env_unset (const char *name) grub_env_remove (var); grub_free (var->name); - grub_free (var->value); + if (var->type != GRUB_ENV_VAR_DATA) + grub_free (var->value); grub_free (var); } diff --git a/normal/main.c b/normal/main.c index 92979139d..33e1fcfe9 100644 --- a/normal/main.c +++ b/normal/main.c @@ -34,9 +34,6 @@ grub_jmp_buf grub_exit_env; static grub_fs_module_list_t fs_module_list = 0; -/* The menu to which the new entries are added by the parser. */ -static grub_menu_t current_menu = 0; - #define GRUB_DEFAULT_HISTORY_SIZE 50 /* Read a line from the file FILE. */ @@ -136,7 +133,7 @@ static void free_menu (grub_menu_t menu) { grub_menu_entry_t entry = menu->entry_list; - + while (entry) { grub_menu_entry_t next_entry = entry->next; @@ -148,6 +145,7 @@ free_menu (grub_menu_t menu) } grub_free (menu); + grub_env_unset_data_slot ("menu"); } grub_err_t @@ -155,11 +153,26 @@ grub_normal_menu_addentry (const char *title, struct grub_script *script, const char *sourcecode) { const char *menutitle; - grub_menu_entry_t *last = ¤t_menu->entry_list; + const char *menusourcecode; + grub_menu_t menu; + grub_menu_entry_t *last; + + menu = grub_env_get_data_slot("menu"); + if (! menu) + return grub_error (GRUB_ERR_MENU, "no menu context"); + + last = &menu->entry_list; + + menusourcecode = grub_strdup (sourcecode); + if (! menusourcecode) + return grub_errno; menutitle = grub_strdup (title); if (! menutitle) - return grub_errno; + { + grub_free ((void *) menusourcecode); + return grub_errno; + } /* Add the menu entry at the end of the list. */ while (*last) @@ -169,22 +182,22 @@ grub_normal_menu_addentry (const char *title, struct grub_script *script, if (! *last) { grub_free ((void *) menutitle); - grub_free ((void *) sourcecode); + grub_free ((void *) menusourcecode); return grub_errno; } (*last)->commands = script; (*last)->title = menutitle; (*last)->next = 0; - (*last)->sourcecode = sourcecode; + (*last)->sourcecode = menusourcecode; - current_menu->size++; + menu->size++; return GRUB_ERR_NONE; } static grub_menu_t -read_config_file (const char *config) +read_config_file (const char *config, int nested) { grub_file_t file; auto grub_err_t getline (char **line); @@ -204,18 +217,25 @@ read_config_file (const char *config) grub_menu_t newmenu; - newmenu = grub_malloc (sizeof (*newmenu)); - if (! newmenu) - return 0; - newmenu->size = 0; - newmenu->entry_list = 0; - current_menu = newmenu; + if (nested) + { + newmenu = grub_malloc (sizeof (*newmenu)); + if (! newmenu) + return 0; + newmenu->size = 0; + newmenu->entry_list = 0; + } /* Try to open the config file. */ file = grub_file_open (config); if (! file) return 0; + if (nested) + grub_env_set_data_slot ("menu", newmenu); + else + newmenu = grub_env_get_data_slot ("menu"); + while (1) { struct grub_script *parsed_script; @@ -257,13 +277,6 @@ read_config_file (const char *config) (void) grub_getkey (); } - /* If the menu is empty, just drop it. */ - if (current_menu->size == 0) - { - grub_free (current_menu); - return 0; - } - return newmenu; } @@ -459,7 +472,7 @@ grub_normal_execute (const char *config, int nested) if (config) { - menu = read_config_file (config); + menu = read_config_file (config, nested); /* Ignore any error. */ grub_errno = GRUB_ERR_NONE; @@ -467,10 +480,9 @@ grub_normal_execute (const char *config, int nested) if (menu) { - grub_env_set_data_slot ("menu", menu); grub_menu_run (menu, nested); - grub_env_unset_data_slot ("menu"); - free_menu (menu); + if (nested) + free_menu (menu); } else grub_cmdline_run (nested); diff --git a/util/i386/pc/biosdisk.c b/util/i386/pc/biosdisk.c index 4d8131c8e..65afa9e3d 100644 --- a/util/i386/pc/biosdisk.c +++ b/util/i386/pc/biosdisk.c @@ -235,7 +235,10 @@ linux_find_partition (char *dev, unsigned long sector) { p = strchr (real_dev + 9, 'd'); if (! p) - return 0; + { + free (real_dev); + return 0; + } p++; while (*p && isdigit (*p))