X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=ui%2Fncurses%2Fnc-cui.c;h=a6537cb46b2b9e46a353d383e6c7ec8c5fad4c39;hp=09b63b053f25638176b1837332b88dab387be110;hb=211d7eb1de2d3a9cd97846deb9a85a934dae2981;hpb=86c9d34380b0074dab1ba89a569a94280d6999c4 diff --git a/ui/ncurses/nc-cui.c b/ui/ncurses/nc-cui.c index 09b63b0..a6537cb 100644 --- a/ui/ncurses/nc-cui.c +++ b/ui/ncurses/nc-cui.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "log/log.h" #include "pb-protocol/pb-protocol.h" @@ -45,8 +46,18 @@ 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) +{ + bool lockdown = false; + if (access(LOCKDOWN_FILE, F_OK) != -1) + lockdown = true; + return lockdown; +} + static void cui_start(void) { initscr(); /* Initialize ncurses. */ @@ -91,9 +102,19 @@ static void cui_start(void) static void cui_atexit(void) { + if (cui_detached) + return; + clear(); refresh(); endwin(); + + bool lockdown = lockdown_active(); + + while (lockdown) { + sync(); + reboot(RB_AUTOBOOT); + } } /** @@ -673,13 +694,13 @@ 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 ? + status->type == STATUS_ERROR ? _("Error") : _("Info"), status->message); @@ -826,6 +847,7 @@ static struct pmenu *main_menu_init(struct cui *cui) struct pmenu_item *i; struct pmenu *m; int result; + bool lockdown = lockdown_active(); m = pmenu_init(cui, 7, cui_on_exit); if (!m) { @@ -869,7 +891,10 @@ static struct pmenu *main_menu_init(struct cui *cui) i->on_execute = menu_add_url_execute; pmenu_item_insert(m, i, 5); - i = pmenu_item_create(m, _("Exit to shell")); + 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); @@ -904,6 +929,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. * @@ -931,13 +981,15 @@ 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_printf(cui->current, + "Info: Connected to pb-discover!"); 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); } } @@ -1058,6 +1110,8 @@ fail_alloc: int cui_run(struct cui *cui) { + pid_t pid; + assert(main); cui->current = &cui->main->scr; @@ -1084,5 +1138,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; }