From d6ea5bd26d54218fdc0e5a4cb48fabc0baedec75 Mon Sep 17 00:00:00 2001 From: Andrew Gregory Date: Sun, 21 Feb 2016 21:46:37 -0500 Subject: use multi-byte character matching for user input Fixes FS#47992 Signed-off-by: Andrew Gregory Signed-off-by: Allan McRae (cherry picked from commit 02731189f1ced6050238e4af7e76a54d4ac6f3bd) --- src/pacman/util.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/pacman/util.c b/src/pacman/util.c index e2c99003..3346a340 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef HAVE_TERMIOS_H #include /* tcflush */ #endif @@ -1487,6 +1488,37 @@ int select_question(int count) return (preset - 1); } +static int mbscasecmp(const char *s1, const char *s2) +{ + size_t len1 = strlen(s1), len2 = strlen(s2); + wchar_t c1, c2; + const char *p1 = s1, *p2 = s2; + mbstate_t ps1, ps2; + memset(&ps1, 0, sizeof(mbstate_t)); + memset(&ps2, 0, sizeof(mbstate_t)); + while(*p1 && *p2) { + size_t b1 = mbrtowc(&c1, p1, len1, &ps1); + size_t b2 = mbrtowc(&c2, p2, len2, &ps2); + if(b1 == (size_t) -2 || b1 == (size_t) -1 + || b2 == (size_t) -2 || b2 == (size_t) -1) { + /* invalid multi-byte string, fall back to strcasecmp */ + return strcasecmp(p1, p2); + } + if(b1 == 0 || b2 == 0) { + return c1 - c2; + } + c1 = towlower(c1); + c2 = towlower(c2); + if(c1 != c2) { + return c1 - c2; + } + p1 += b1; + p2 += b2; + len1 -= b1; + len2 -= b2; + } + return *p1 - *p2; +} /* presents a prompt and gets a Y/N answer */ __attribute__((format(printf, 2, 0))) @@ -1538,9 +1570,9 @@ static int question(short preset, const char *format, va_list args) fprintf(stream, "%s\n", response); } - if(strcasecmp(response, _("Y")) == 0 || strcasecmp(response, _("YES")) == 0) { + if(mbscasecmp(response, _("Y")) == 0 || mbscasecmp(response, _("YES")) == 0) { return 1; - } else if(strcasecmp(response, _("N")) == 0 || strcasecmp(response, _("NO")) == 0) { + } else if(mbscasecmp(response, _("N")) == 0 || mbscasecmp(response, _("NO")) == 0) { return 0; } } -- cgit v1.2.3-70-g09d2