]> git.ozlabs.org Git - petitboot/blobdiff - ui/ncurses/nc-cui.c
ui/ncurses: Safely handle lost terminal control commands
[petitboot] / ui / ncurses / nc-cui.c
index 8fba7d5119e50c4a2f8308eed1169db5ecf6903a..8060510da0cd29010b33af506cc3da399dab3a40 100644 (file)
@@ -21,6 +21,7 @@
 #endif
 
 #include <assert.h>
+#include <ctype.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
@@ -45,6 +46,7 @@
 #include "nc-statuslog.h"
 #include "nc-subset.h"
 #include "nc-plugin.h"
+#include "console-codes.h"
 
 extern const struct help_text main_menu_help_text;
 extern const struct help_text plugin_menu_help_text;
@@ -151,7 +153,30 @@ void cui_resize(struct cui *cui)
 
 void cui_on_exit(struct pmenu *menu)
 {
-       cui_abort(cui_from_pmenu(menu));
+       struct cui *cui = cui_from_pmenu(menu);
+       char *sh_cmd;
+
+       sh_cmd = talloc_asprintf(cui,
+               "echo \"Exiting petitboot. Type 'exit' to return.\";\
+                echo \"You may run 'pb-sos' to gather diagnostic data\";\
+                %s", pb_system_apps.sh);
+
+       if (!sh_cmd) {
+               pb_log("Failed to allocate shell arguments\n");
+               return;
+       }
+
+       const char *argv[] = {
+               pb_system_apps.sh,
+               "-c",
+               sh_cmd,
+               NULL
+       };
+
+       cui_run_cmd(cui, argv);
+
+       nc_scr_status_printf(cui->current, _("Returned from shell"));
+       talloc_free(sh_cmd);
 }
 
 /**
@@ -173,6 +198,10 @@ int cui_run_cmd(struct cui *cui, const char **cmd_argv)
 
        nc_scr_status_printf(cui->current, _("Running %s..."), cmd_argv[0]);
 
+       nc_scr_unpost(cui->current);
+       clear();
+       refresh();
+
        def_prog_mode();
        endwin();
 
@@ -182,6 +211,7 @@ int cui_run_cmd(struct cui *cui, const char **cmd_argv)
        refresh();
 
        redrawwin(cui->current->main_ncw);
+       nc_scr_post(cui->current);
 
        if (result) {
                pb_log("%s: failed: '%s'\n", __func__, cmd_argv[0]);
@@ -496,6 +526,9 @@ static bool process_global_keys(struct cui *cui, int key)
 static int cui_process_key(void *arg)
 {
        struct cui *cui = cui_from_arg(arg);
+       unsigned int i;
+       char *sequence;
+       int grab;
 
        assert(cui->current);
 
@@ -507,6 +540,29 @@ static int cui_process_key(void *arg)
                if (c == ERR)
                        break;
 
+               if (c == 27) {
+                       /*
+                        * If this is a console code sequence try to parse it
+                        * and don't treat this as a key press.
+                        */
+                       grab = getch();
+                       if (grab != ERR && grab != 27) {
+                               ungetch(grab);
+                               pb_debug("%s: Caught unhandled command sequence\n",
+                                               __func__);
+                               sequence = handle_control_sequence(cui, c);
+                               pb_debug("Caught sequence ");
+                               if (sequence) {
+                                       pb_debug("(%zu): ", strlen(sequence));
+                                       for (i = 0; i < strlen(sequence); i++)
+                                               pb_debug("0%o ", sequence[i]);
+                                       pb_debug("\n");
+                               } else
+                                       pb_debug("(0): (none)\n");
+                               continue;
+                       }
+               }
+
                if (!cui->has_input) {
                        cui->has_input = true;
                        if (cui->client) {