summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorJeremy Kerr <jk@ozlabs.org>2014-03-13 15:18:04 +0800
committerJeremy Kerr <jk@ozlabs.org>2014-04-10 11:18:26 +0800
commitada4ea46dd44e667bfe6341e0b7b5366e5741351 (patch)
tree99359c98216639782deb2623c6a9ed8f6d4808d7 /ui
parent6c7cf0a58b0e4be046b2367c93925e1c4895dd6c (diff)
downloadtalos-petitboot-ada4ea46dd44e667bfe6341e0b7b5366e5741351.tar.gz
talos-petitboot-ada4ea46dd44e667bfe6341e0b7b5366e5741351.zip
ui/ncurses: Ensure boot option labels are displayable as menu items
ncurses' new_item() expects the name parameter to be a "printable string", by converting it to a wchar *, and checking that each character is printable with iswprint(). If it fails, we won't see a boot option at all. This change introduces a function to convert the label into something we know is printable, and valid UTF-8. If mbstowcs fails, we replace it with a generic 'Invalid option' label. If we encounter a valid multibyte string with unprintable characters, we replace those with U+fffd REPLACEMENT CHARACTER. Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Diffstat (limited to 'ui')
-rw-r--r--ui/ncurses/nc-menu.c44
1 files changed, 43 insertions, 1 deletions
diff --git a/ui/ncurses/nc-menu.c b/ui/ncurses/nc-menu.c
index 8738c48..7d4442b 100644
--- a/ui/ncurses/nc-menu.c
+++ b/ui/ncurses/nc-menu.c
@@ -23,6 +23,8 @@
#include <assert.h>
#include <errno.h>
#include <string.h>
+#include <stdlib.h>
+#include <wctype.h>
#include "log/log.h"
#include "talloc/talloc.h"
@@ -83,6 +85,43 @@ static int pmenu_item_destructor(void *arg)
return 0;
}
+static const char *pmenu_item_label(struct pmenu_item *item, const char *name)
+{
+ static int invalid_idx;
+ unsigned int i;
+ wchar_t *tmp;
+ char *label;
+ size_t len;
+
+ len = mbstowcs(NULL, name, 0);
+
+ /* if we have an invalid multibyte sequence, create an entirely
+ * new name, indicating that we had invalid input */
+ if (len == SIZE_MAX) {
+ name = talloc_asprintf(item, "!Invalid option %d\n",
+ ++invalid_idx);
+ return name;
+ }
+
+ tmp = talloc_array(item, wchar_t, len + 1);
+ mbstowcs(tmp, name, len + 1);
+
+ /* replace anything unprintable with U+FFFD REPLACEMENT CHARACTER */
+ for (i = 0; i < len; i++) {
+ if (!iswprint(tmp[i]))
+ tmp[i] = 0xfffd;
+ }
+
+ len = wcstombs(NULL, tmp, 0);
+ label = talloc_array(item, char, len + 1);
+ wcstombs(label, tmp, len + 1);
+
+ pb_log("%s: %s\n", __func__, label);
+
+ talloc_free(tmp);
+ return label;
+}
+
/**
* pmenu_item_create - Allocate and initialize a new pmenu_item instance.
*
@@ -93,10 +132,13 @@ static int pmenu_item_destructor(void *arg)
struct pmenu_item *pmenu_item_create(struct pmenu *menu, const char *name)
{
struct pmenu_item *item = talloc_zero(menu, struct pmenu_item);
+ const char *label;
+
+ label = pmenu_item_label(item, name);
item->i_sig = pb_item_sig;
item->pmenu = menu;
- item->nci = new_item(name, NULL);
+ item->nci = new_item(label, NULL);
if (!item->nci) {
talloc_free(item);
OpenPOWER on IntegriCloud