summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Gregory <andrew.gregory.8@gmail.com>2016-02-21 21:46:37 -0500
committerAllan McRae <allan@archlinux.org>2016-02-26 15:52:25 +1000
commit02731189f1ced6050238e4af7e76a54d4ac6f3bd (patch)
treea790668c0ff70d1cfb3cf4e976e16a0cd99a38ee
parent1a94c00e363081594bd6940d98117289b03692d6 (diff)
downloadpacman-02731189f1ced6050238e4af7e76a54d4ac6f3bd.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>
-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 0862de0c..d924bf36 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
@@ -1480,6 +1481,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)))
@@ -1531,9 +1563,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;
}
}