summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Gregory <andrew.gregory.8@gmail.com>2016-02-21 21:46:37 -0500
committerAndrew Gregory <andrew.gregory.8@gmail.com>2017-04-27 22:21:54 -0400
commitd6ea5bd26d54218fdc0e5a4cb48fabc0baedec75 (patch)
treecf4f0b7be067faeeb74707fbc279b9db2d624a6f /src
parentcd7acd75299e3124424d92113ba0241d5f8b084b (diff)
downloadpacman-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.c36
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;
}
}