X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;ds=inline;f=ui%2Fncurses%2Fnc-cui.c;h=84e4bf01cdff59b1021d8c79a9a19dfa5a2803a6;hb=d90efe9e2bbfb18ee05ec2032b5723dbfa902d82;hp=c2f1c83f1c406bcd698c9b9f782da25b431f3800;hpb=f5dab0206a3baca73895a587583ddfa402f8f569;p=petitboot diff --git a/ui/ncurses/nc-cui.c b/ui/ncurses/nc-cui.c index c2f1c83..84e4bf0 100644 --- a/ui/ncurses/nc-cui.c +++ b/ui/ncurses/nc-cui.c @@ -42,10 +42,13 @@ #include "nc-sysinfo.h" #include "nc-lang.h" #include "nc-helpscreen.h" +#include "nc-statuslog.h" #include "nc-subset.h" extern const struct help_text main_menu_help_text; +static bool cui_detached = false; + static struct pmenu *main_menu_init(struct cui *cui); static bool lockdown_active(void) @@ -100,6 +103,9 @@ static void cui_start(void) static void cui_atexit(void) { + if (cui_detached) + return; + clear(); refresh(); endwin(); @@ -149,19 +155,29 @@ void cui_on_exit(struct pmenu *menu) * cui_run_cmd - A generic cb to run the supplied command. */ -int cui_run_cmd(struct pmenu_item *item) +int cui_run_cmd(struct cui *cui, const char **cmd_argv) { + struct process *process; int result; - struct cui *cui = cui_from_item(item); - const char **cmd_argv = item->data; + + process = process_create(cui); + if (!process) + return -1; + + process->path = cmd_argv[0]; + process->argv = cmd_argv; + process->raw_stdout = true; nc_scr_status_printf(cui->current, _("Running %s..."), cmd_argv[0]); def_prog_mode(); + endwin(); - result = process_run_simple_argv(item, cmd_argv); + result = process_run_sync(process); reset_prog_mode(); + refresh(); + redrawwin(cui->current->main_ncw); if (result) { @@ -170,9 +186,19 @@ int cui_run_cmd(struct pmenu_item *item) cmd_argv[0]); } + process_release(process); + return result; } +int cui_run_cmd_from_item(struct pmenu_item *item) +{ + struct cui *cui = cui_from_item(item); + const char **cmd_argv = item->data; + + return cui_run_cmd(cui, cmd_argv); +} + /** * cui_boot - A generic cb to run kexec. */ @@ -330,6 +356,19 @@ void cui_show_lang(struct cui *cui) cui_set_current(cui, lang_screen_scr(cui->lang_screen)); } +static void cui_statuslog_exit(struct cui *cui) +{ + cui_set_current(cui, &cui->main->scr); + talloc_free(cui->statuslog_screen); + cui->statuslog_screen = NULL; +} + +void cui_show_statuslog(struct cui *cui) +{ + cui->statuslog_screen = statuslog_screen_init(cui, cui_statuslog_exit); + cui_set_current(cui, statuslog_screen_scr(cui->statuslog_screen)); +} + static void cui_add_url_exit(struct cui *cui) { cui_set_current(cui, &cui->main->scr); @@ -689,16 +728,15 @@ static void cui_device_remove(struct device *dev, void *arg) nc_scr_post(cui->current); } -static void cui_update_status(struct boot_status *status, void *arg) +static void cui_update_status(struct status *status, void *arg) { struct cui *cui = cui_from_arg(arg); - nc_scr_status_printf(cui->current, - "%s: %s", - status->type == BOOT_STATUS_ERROR ? - _("Error") : _("Info"), - status->message); + statuslog_append_steal(cui, cui->statuslog, status); + /* Ignore status messages from the backlog */ + if (!status->backlog) + nc_scr_status_printf(cui->current, "%s", status->message); } static void cui_update_mm_title(struct cui *cui) @@ -820,6 +858,12 @@ static int menu_lang_execute(struct pmenu_item *item) return 0; } +static int menu_statuslog_execute(struct pmenu_item *item) +{ + cui_show_statuslog(cui_from_item(item)); + return 0; +} + static int menu_reinit_execute(struct pmenu_item *item) { if (cui_from_item(item)->client) @@ -844,7 +888,7 @@ static struct pmenu *main_menu_init(struct cui *cui) int result; bool lockdown = lockdown_active(); - m = pmenu_init(cui, 7, cui_on_exit); + m = pmenu_init(cui, 8, cui_on_exit); if (!m) { pb_log("%s: failed\n", __func__); return NULL; @@ -856,7 +900,7 @@ static struct pmenu *main_menu_init(struct cui *cui) "Petitboot (" PACKAGE_VERSION ")"); m->scr.frame.rtitle = NULL; m->scr.frame.help = talloc_strdup(m, - _("Enter=accept, e=edit, n=new, x=exit, l=language, h=help")); + _("Enter=accept, e=edit, n=new, x=exit, l=language, g=log, h=help")); m->scr.frame.status = talloc_strdup(m, _("Welcome to Petitboot")); /* add a separator */ @@ -873,25 +917,29 @@ static struct pmenu *main_menu_init(struct cui *cui) i->on_execute = menu_config_execute; pmenu_item_insert(m, i, 2); + i = pmenu_item_create(m, _("System status log")); + i->on_execute = menu_statuslog_execute; + pmenu_item_insert(m, i, 3); + /* this label isn't translated, so we don't want a gettext() here */ i = pmenu_item_create(m, "Language"); i->on_execute = menu_lang_execute; - pmenu_item_insert(m, i, 3); + pmenu_item_insert(m, i, 4); i = pmenu_item_create(m, _("Rescan devices")); i->on_execute = menu_reinit_execute; - pmenu_item_insert(m, i, 4); + pmenu_item_insert(m, i, 5); i = pmenu_item_create(m, _("Retrieve config from URL")); i->on_execute = menu_add_url_execute; - pmenu_item_insert(m, i, 5); + pmenu_item_insert(m, i, 6); if (lockdown) i = pmenu_item_create(m, _("Reboot")); else i = pmenu_item_create(m, _("Exit to shell")); i->on_execute = pmenu_exit_cb; - pmenu_item_insert(m, i, 6); + pmenu_item_insert(m, i, 7); result = pmenu_setup(m); @@ -924,6 +972,31 @@ static struct discover_client_ops cui_client_ops = { .update_config = cui_update_config, }; +/* cui_server_wait_on_exit - On exit spin until the server is available. + * + * If the program exits before connecting to the server autoboot won't be + * cancelled even though there has been keyboard activity. This function is + * called by a child process which will spin until the server is connected and + * told to cancel autoboot. + * + * Processes exiting from this function will not carry out the cui_atexit() + * steps. + */ +static void cui_server_wait_on_exit(struct cui *cui) +{ + cui_detached = true; + + while (!cui->client) { + cui->client = discover_client_init(cui->waitset, + &cui_client_ops, cui); + if (!cui->client) + sleep(1); + } + + talloc_steal(cui, cui->client); + discover_client_cancel_default(cui->client); +} + /* cui_server_wait - Connect to the discover server. * @arg: Pointer to the cui instance. * @@ -951,13 +1024,14 @@ static int cui_server_wait(void *arg) if (!cui->client) { waiter_register_timeout(cui->waitset, 1000, cui_server_wait, cui); - nc_scr_status_printf(cui->current, "Info: Waiting for server"); + nc_scr_status_printf(cui->current, + "Info: Waiting for device discovery"); } else { - nc_scr_status_printf(cui->current, "Info: Connected to server!"); + nc_scr_status_free(cui->current); talloc_steal(cui, cui->client); if (cui->has_input) { - pb_log("Aborting default boot on server connect\n"); + pb_log("Aborting default boot on pb-discover connect\n"); discover_client_cancel_default(cui->client); } } @@ -991,6 +1065,7 @@ struct cui *cui_init(void* platform_info, cui->c_sig = pb_cui_sig; cui->platform_info = platform_info; cui->waitset = waitset_create(cui); + cui->statuslog = statuslog_init(cui); process_init(cui, cui->waitset, false); @@ -1078,6 +1153,8 @@ fail_alloc: int cui_run(struct cui *cui) { + pid_t pid; + assert(main); cui->current = &cui->main->scr; @@ -1104,5 +1181,16 @@ int cui_run(struct cui *cui) cui_atexit(); + if (!cui->client) { + /* Fork a child to tell the server to cancel autoboot */ + pid = fork(); + if (!pid) { + cui_server_wait_on_exit(cui); + exit(EXIT_SUCCESS); + } + if (pid < 0) + pb_log("Failed to fork child on exit: %m\n"); + } + return cui->abort ? 0 : -1; }