diff options
author | Andrew Gregory <andrew.gregory.8@gmail.com> | 2016-02-21 21:46:37 -0500 |
---|---|---|
committer | Andrew Gregory <andrew.gregory.8@gmail.com> | 2017-04-27 22:21:54 -0400 |
commit | d6ea5bd26d54218fdc0e5a4cb48fabc0baedec75 (patch) | |
tree | cf4f0b7be067faeeb74707fbc279b9db2d624a6f /src | |
parent | cd7acd75299e3124424d92113ba0241d5f8b084b (diff) | |
download | pacman-d6ea5bd26d54218fdc0e5a4cb48fabc0baedec75.tar.xz |
use multi-byte character matching for user input
Fixes FS#47992
Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
Signed-off-by: Allan McRae <allan@archlinux.org>
(cherry picked from commit 02731189f1ced6050238e4af7e76a54d4ac6f3bd)
Diffstat (limited to 'src')
-rw-r--r-- | src/pacman/util.c | 36 |
1 files changed, 34 insertions, 2 deletions
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 <unistd.h> #include <limits.h> #include <wchar.h> +#include <wctype.h> #ifdef HAVE_TERMIOS_H #include <termios.h> /* 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; } } |