[pacman-dev] [PATCH] use multi-byte character matching for user input

Andrew Gregory andrew.gregory.8 at gmail.com
Mon Feb 22 02:46:37 UTC 2016


Fixes FS#47992

Signed-off-by: Andrew Gregory <andrew.gregory.8 at gmail.com>
---
 src/pacman/util.c | 36 ++++++++++++++++++++++++++++++++++--
 1 file changed, 34 insertions(+), 2 deletions(-)

diff --git a/src/pacman/util.c b/src/pacman/util.c
index 48a3600..3f66947 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;
 		}
 	}
-- 
2.7.1


More information about the pacman-dev mailing list