From 651940467773d2e679f9210e02f4654fb05cd449 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Thu, 17 Oct 2013 13:52:42 +0800 Subject: [PATCH 1/1] ui/ncurses: Add sysinfo screen Add a simple screen for displaying the struct system_info. We add this to the main menu as a selectable option, and separate it from the boot option list with an unselectable blank entry. Signed-off-by: Jeremy Kerr --- ui/ncurses/Makefile.am | 4 +- ui/ncurses/generic-main.c | 14 ++- ui/ncurses/nc-cui.c | 21 ++++ ui/ncurses/nc-cui.h | 2 + ui/ncurses/nc-menu.c | 5 + ui/ncurses/nc-scr.h | 11 +- ui/ncurses/nc-sysinfo.c | 249 ++++++++++++++++++++++++++++++++++++++ ui/ncurses/nc-sysinfo.h | 34 ++++++ 8 files changed, 332 insertions(+), 8 deletions(-) create mode 100644 ui/ncurses/nc-sysinfo.c create mode 100644 ui/ncurses/nc-sysinfo.h diff --git a/ui/ncurses/Makefile.am b/ui/ncurses/Makefile.am index 64b6eb1..ac4ca46 100644 --- a/ui/ncurses/Makefile.am +++ b/ui/ncurses/Makefile.am @@ -36,7 +36,9 @@ libpbnc_la_SOURCES = \ nc-menu.c \ nc-menu.h \ nc-scr.c \ - nc-scr.h + nc-scr.h \ + nc-sysinfo.c \ + nc-sysinfo.h sbin_PROGRAMS = petitboot-nc diff --git a/ui/ncurses/generic-main.c b/ui/ncurses/generic-main.c index 49a96cb..9d8ebb9 100644 --- a/ui/ncurses/generic-main.c +++ b/ui/ncurses/generic-main.c @@ -126,6 +126,12 @@ struct pb_cui { struct cui *cui; }; +static int pmenu_sysinfo(struct pmenu_item *item) +{ + cui_show_sysinfo(cui_from_item(item)); + return 0; +} + /** * pb_mm_init - Setup the main menu instance. */ @@ -136,7 +142,7 @@ static struct pmenu *pb_mm_init(struct pb_cui *pb_cui) struct pmenu *m; struct pmenu_item *i; - m = pmenu_init(pb_cui->cui, 1, cui_on_exit); + m = pmenu_init(pb_cui->cui, 3, cui_on_exit); if (!m) { pb_log("%s: failed\n", __func__); @@ -152,7 +158,11 @@ static struct pmenu *pb_mm_init(struct pb_cui *pb_cui) "Enter=accept, e=edit, n=new, x=exit"); m->scr.frame.status = talloc_strdup(m, "Welcome to Petitboot"); - i = pmenu_item_init(m, 0, "Exit to Shell"); + i = pmenu_item_init(m, 0, " "); + item_opts_off(i->nci, O_SELECTABLE); + i = pmenu_item_init(m, 1, "System information"); + i->on_execute = pmenu_sysinfo; + i = pmenu_item_init(m, 2, "Exit to shell"); i->on_execute = pmenu_exit_cb; result = pmenu_setup(m); diff --git a/ui/ncurses/nc-cui.c b/ui/ncurses/nc-cui.c index b734cdc..5f41196 100644 --- a/ui/ncurses/nc-cui.c +++ b/ui/ncurses/nc-cui.c @@ -34,6 +34,7 @@ #include "process/process.h" #include "ui/common/discover-client.h" #include "nc-cui.h" +#include "nc-sysinfo.h" static struct cui_opt_data *cod_from_item(struct pmenu_item *item) { @@ -236,6 +237,20 @@ void cui_item_new(struct pmenu *menu) cui_set_current(cui, &boot_editor->scr); } +static void cui_sysinfo_exit(struct cui *cui) +{ + cui_set_current(cui, &cui->main->scr); + talloc_free(cui->sysinfo_screen); + cui->sysinfo_screen = NULL; +} + +void cui_show_sysinfo(struct cui *cui) +{ + cui->sysinfo_screen = sysinfo_screen_init(cui, cui->sysinfo, + cui_sysinfo_exit); + cui_set_current(cui, sysinfo_screen_scr(cui->sysinfo_screen)); +} + /** * cui_set_current - Set the currently active screen and redraw it. */ @@ -506,6 +521,12 @@ static void cui_update_sysinfo(struct system_info *sysinfo, void *arg) { struct cui *cui = cui_from_arg(arg); cui->sysinfo = talloc_steal(cui, sysinfo); + + /* if we're currently displaying the system info screen, inform it + * of the updated information. */ + if (cui->sysinfo_screen) + sysinfo_screen_update(cui->sysinfo_screen, sysinfo); + cui_update_mm_title(cui); } diff --git a/ui/ncurses/nc-cui.h b/ui/ncurses/nc-cui.h index 730e721..d1edd79 100644 --- a/ui/ncurses/nc-cui.h +++ b/ui/ncurses/nc-cui.h @@ -56,6 +56,7 @@ struct cui { struct waitset *waitset; struct discover_client *client; struct system_info *sysinfo; + struct sysinfo_screen *sysinfo_screen; struct pjs *pjs; void *platform_info; unsigned int default_item; @@ -69,6 +70,7 @@ struct nc_scr *cui_set_current(struct cui *cui, struct nc_scr *scr); int cui_run(struct cui *cui, struct pmenu *main, unsigned int default_item); void cui_item_edit(struct pmenu_item *item); void cui_item_new(struct pmenu *menu); +void cui_show_sysinfo(struct cui *cui); /* convenience routines */ diff --git a/ui/ncurses/nc-menu.c b/ui/ncurses/nc-menu.c index 4dba0ad..dc46807 100644 --- a/ui/ncurses/nc-menu.c +++ b/ui/ncurses/nc-menu.c @@ -27,6 +27,7 @@ #include "log/log.h" #include "talloc/talloc.h" #include "ui/common/ui-system.h" +#include "nc-cui.h" #include "nc-menu.h" /** @@ -242,6 +243,8 @@ static void pmenu_process_key(struct nc_scr *scr, int key) if (item->on_execute) item->on_execute(item); break; + case 'i': + cui_show_sysinfo(cui_from_arg(scr->ui_ctx)); default: menu_driver(menu->ncm, key); break; @@ -378,6 +381,8 @@ int pmenu_setup(struct pmenu *menu) /* Makes menu scrollable. */ set_menu_format(menu->ncm, LINES - nc_scr_frame_lines, 1); + set_menu_grey(menu->ncm, A_NORMAL); + return 0; } diff --git a/ui/ncurses/nc-scr.h b/ui/ncurses/nc-scr.h index 4f9de59..e3ed20a 100644 --- a/ui/ncurses/nc-scr.h +++ b/ui/ncurses/nc-scr.h @@ -40,11 +40,12 @@ enum pb_nc_sig { - pb_cui_sig = 111, - pb_pmenu_sig = 222, - pb_item_sig = 333, - pb_boot_editor_sig = 444, - pb_removed_sig = -555, + pb_cui_sig = 111, + pb_pmenu_sig = 222, + pb_item_sig = 333, + pb_boot_editor_sig = 444, + pb_sysinfo_screen_sig = 555, + pb_removed_sig = -666, }; static inline void nc_flush_keys(void) diff --git a/ui/ncurses/nc-sysinfo.c b/ui/ncurses/nc-sysinfo.c new file mode 100644 index 0000000..4cba9a9 --- /dev/null +++ b/ui/ncurses/nc-sysinfo.c @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2013 IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define _GNU_SOURCE + + +#include + +#include +#include +#include +#include + +#include "config.h" +#include "nc-cui.h" +#include "nc-sysinfo.h" + +struct sysinfo_screen { + struct nc_scr scr; + struct cui *cui; + char **lines; + int n_lines; + int n_alloc_lines; + int scroll_y; + void (*on_exit)(struct cui *); +}; + +static struct sysinfo_screen *sysinfo_screen_from_scr(struct nc_scr *scr) +{ + struct sysinfo_screen *sysinfo_screen; + + assert(scr->sig == pb_sysinfo_screen_sig); + sysinfo_screen = (struct sysinfo_screen *) + ((char *)scr - (size_t)&((struct sysinfo_screen *)0)->scr); + assert(sysinfo_screen->scr.sig == pb_sysinfo_screen_sig); + return sysinfo_screen; +} + +static void sysinfo_screen_draw(struct sysinfo_screen *screen) +{ + int max_y, i; + + max_y = getmaxy(screen->scr.sub_ncw); + + max_y = min(max_y, screen->scroll_y + screen->n_lines); + + for (i = screen->scroll_y; i < max_y; i++) + mvwaddstr(screen->scr.sub_ncw, i, 1, screen->lines[i]); + + wrefresh(screen->scr.sub_ncw); +} + +static void sysinfo_screen_scroll(struct sysinfo_screen *screen, int key) +{ + int win_lines = getmaxy(screen->scr.sub_ncw); + int delta; + + if (key == KEY_UP) + delta = -1; + else if (key == KEY_DOWN) + delta = 1; + else + return; + + if (screen->scroll_y + delta < 0) + return; + if (screen->scroll_y + delta + win_lines > screen->n_lines - 1) + return; + + screen->scroll_y += delta; + wscrl(screen->scr.sub_ncw, delta); + + if (delta > 0) { + mvwaddstr(screen->scr.sub_ncw, win_lines - 1, 1, + screen->lines[screen->scroll_y+win_lines-1]); + } else if (delta < 0) { + mvwaddstr(screen->scr.sub_ncw, 0, 1, + screen->lines[screen->scroll_y]); + } + + wrefresh(screen->scr.sub_ncw); +} + +static void sysinfo_clear(struct sysinfo_screen *screen) +{ + talloc_free(screen->lines); + screen->n_lines = 0; + screen->n_alloc_lines = 16; + screen->lines = talloc_array(screen, char *, screen->n_alloc_lines); +} + +static __attribute__((format(printf, 2, 3))) void sysinfo_screen_append_line( + struct sysinfo_screen *screen, const char *fmt, ...) +{ + char *line; + va_list ap; + + if (fmt) { + va_start(ap, fmt); + line = talloc_vasprintf(screen->lines, fmt, ap); + va_end(ap); + } else { + line = ""; + } + + if (screen->n_lines == screen->n_alloc_lines) { + screen->n_alloc_lines *= 2; + screen->lines = talloc_realloc(screen, screen->lines, + char *, screen->n_alloc_lines); + } + + screen->lines[screen->n_lines] = line; + screen->n_lines++; +} + +static void mac_str(struct interface_info *info, char *buf, unsigned int buflen) +{ + unsigned int i; + char *pos; + + assert(buflen > sizeof("unknown")); + + if (!info->hwaddr_size || info->hwaddr_size * 3 + 1 > buflen) { + strcpy(buf, "unknown"); + return; + } + + pos = buf; + + for (i = 0; i < info->hwaddr_size; i++) { + snprintf(pos, 4, "%02x:", info->hwaddr[i]); + pos += 3; + } + + *(pos - 1) = '\0'; + + return; +} + +static void sysinfo_screen_populate(struct sysinfo_screen *screen, + const struct system_info *sysinfo) +{ + unsigned int i; + + sysinfo_clear(screen); + +#define line(...) sysinfo_screen_append_line(screen, __VA_ARGS__) + if (!sysinfo) { + line("Waiting for system information..."); + return; + } + + line("%-12s %s", "System type:", sysinfo->type ?: ""); + line("%-12s %s", "System id:", sysinfo->identifier ?: ""); + + line(NULL); + if (sysinfo->n_interfaces) + line("Network interfaces"); + + for (i = 0; i < sysinfo->n_interfaces; i++) { + struct interface_info *info = sysinfo->interfaces[i]; + char macbuf[32]; + + mac_str(info, macbuf, sizeof(macbuf)); + + line("%s:", info->name); + line(" MAC: %s", macbuf); + line(NULL); + } + +#undef line +} + +static void sysinfo_screen_process_key(struct nc_scr *scr, int key) +{ + struct sysinfo_screen *screen = sysinfo_screen_from_scr(scr); + + switch (key) { + case 'x': + screen->on_exit(screen->cui); + break; + case KEY_DOWN: + case KEY_UP: + sysinfo_screen_scroll(screen, key); + break; + default: + break; + } +} + +static void sysinfo_screen_resize(struct nc_scr *scr) +{ + struct sysinfo_screen *screen = sysinfo_screen_from_scr(scr); + sysinfo_screen_draw(screen); +} + +struct nc_scr *sysinfo_screen_scr(struct sysinfo_screen *screen) +{ + return &screen->scr; +} + +void sysinfo_screen_update(struct sysinfo_screen *screen, + const struct system_info *sysinfo) +{ + sysinfo_screen_populate(screen, sysinfo); + sysinfo_screen_draw(screen); +} + +struct sysinfo_screen *sysinfo_screen_init(struct cui *cui, + const struct system_info *sysinfo, + void (*on_exit)(struct cui *)) +{ + struct sysinfo_screen *screen; + + screen = talloc_zero(cui, struct sysinfo_screen); + nc_scr_init(&screen->scr, pb_sysinfo_screen_sig, 0, + cui, sysinfo_screen_process_key, + NULL, NULL, sysinfo_screen_resize); + + screen->cui = cui; + screen->on_exit = on_exit; + + screen->scr.frame.ltitle = talloc_strdup(screen, + "Petitboot System Information"); + screen->scr.frame.rtitle = NULL; + screen->scr.frame.help = talloc_strdup(screen, "x=exit"); + nc_scr_frame_draw(&screen->scr); + + sysinfo_screen_populate(screen, sysinfo); + wrefresh(screen->scr.main_ncw); + scrollok(screen->scr.sub_ncw, true); + sysinfo_screen_draw(screen); + + return screen; +} diff --git a/ui/ncurses/nc-sysinfo.h b/ui/ncurses/nc-sysinfo.h new file mode 100644 index 0000000..5407bf8 --- /dev/null +++ b/ui/ncurses/nc-sysinfo.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2013 IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _NC_SYSINFO_H +#define _NC_SYSINFO_H + +#include "types/types.h" +#include "nc-cui.h" + +struct sysinfo_screen; + +struct sysinfo_screen *sysinfo_screen_init(struct cui *cui, + const struct system_info *sysinfo, + void (*on_exit)(struct cui *)); + +struct nc_scr *sysinfo_screen_scr(struct sysinfo_screen *screen); +void sysinfo_screen_update(struct sysinfo_screen *screen, + const struct system_info *sysinfo); + +#endif /* defined _NC_SYSINFO_H */ -- 2.39.2