diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/menu.c | 108 |
1 files changed, 100 insertions, 8 deletions
diff --git a/common/menu.c b/common/menu.c index 6e6637addf..7620d9e545 100644 --- a/common/menu.c +++ b/common/menu.c @@ -29,6 +29,7 @@ #include <xfuncs.h> #include <errno.h> #include <readkey.h> +#include <linux/err.h> static LIST_HEAD(menus); @@ -143,8 +144,7 @@ void menu_entry_free(struct menu_entry *me) if (!me) return; - free(me->display); - free(me); + me->free(me); } static void print_menu_entry(struct menu *m, struct menu_entry *me, int reverse) @@ -273,14 +273,74 @@ int menu_show(struct menu *m) void menu_action_exit(struct menu *m, struct menu_entry *me) {} -void menu_action_run(struct menu *m, struct menu_entry *me) +struct submenu { + char *submenu; + struct menu_entry entry; +}; + +static void menu_action_show(struct menu *m, struct menu_entry *me) { + struct submenu *s = container_of(me, struct submenu, entry); + struct menu *sm; + + sm = menu_get_by_name(s->submenu); + if (sm) + menu_show(sm); + else + eprintf("no such menu: %s\n", s->submenu); +} + +static void submenu_free(struct menu_entry *me) +{ + struct submenu *s = container_of(me, struct submenu, entry); + + free(s->entry.display); + free(s->submenu); + free(s); +} + +struct menu_entry *menu_add_submenu(struct menu *parent, char *submenu, char *display) +{ + struct submenu *s = calloc(1, sizeof(*s)); int ret; - const char *s = getenv((const char*)me->priv); + + if (!s) + return ERR_PTR(-ENOMEM); + + s->submenu = strdup(submenu); + s->entry.action = menu_action_show; + s->entry.free = submenu_free; + s->entry.display = strdup(display); + if (!s->entry.display || !s->submenu) { + ret = -ENOMEM; + goto err_free; + } + + ret = menu_add_entry(parent, &s->entry); + if (ret) + goto err_free; + + return &s->entry; + +err_free: + submenu_free(&s->entry); + return ERR_PTR(ret); +} + +struct action_entry { + char *command; + struct menu_entry entry; +}; + +static void menu_action_command(struct menu *m, struct menu_entry *me) +{ + struct action_entry *e = container_of(me, struct action_entry, entry); + int ret; + const char *s = getenv(e->command); /* can be a command as boot */ if (!s) - s = me->priv; + s = e->command; ret = run_command (s, 0); @@ -288,9 +348,41 @@ void menu_action_run(struct menu *m, struct menu_entry *me) udelay(1000000); } -void menu_action_show(struct menu *m, struct menu_entry *me) +static void menu_command_free(struct menu_entry *me) +{ + struct action_entry *e = container_of(me, struct action_entry, entry); + + free(e->entry.display); + free(e->command); + + free(e); +} + +struct menu_entry *menu_add_command_entry(struct menu *m, char *display, char *command) { - struct menu *sm = me->priv; + struct action_entry *e = calloc(1, sizeof(*e)); + int ret; + + if (!e) + return ERR_PTR(-ENOMEM); + + e->command = strdup(command); + e->entry.action = menu_action_command; + e->entry.free = menu_command_free; + e->entry.display = strdup(display); - menu_show(sm); + if (!e->entry.display || !e->command) { + ret = -ENOMEM; + goto err_free; + } + + ret = menu_add_entry(m, &e->entry); + if (ret) + goto err_free; + + return &e->entry; +err_free: + menu_command_free(&e->entry); + return ERR_PTR(ret); } + |