From 714a67ff68f7e2a7b3f9ede538cc2e2b0f4870cc Mon Sep 17 00:00:00 2001
From: Pantelis Panayiotou
Date: Fri, 5 Sep 2025 14:14:46 +0300
Subject: [PATCH] Fallback of strcasestr() for systems that don't use libc
(issue #68)
(GURU context: This is a backport of [1] to 1.5.0, fixing a build issue
on musl systems.)
[1]: https://github.com/plp13/qman/commit/1dcda6e0fef34fa5c592b133b7d899dce4264f46
---
src/program.c | 2 +-
src/util.c | 29 +++++++++++++++++++++++++++++
src/util.h | 11 ++++++++---
3 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/src/program.c b/src/program.c
index c194f48..219fa34 100644
--- a/src/program.c
+++ b/src/program.c
@@ -389,7 +389,7 @@ bool man_loc(char *dst, unsigned dst_len, const wchar_t *args,
ret = false;
FILE *pp = xpopen(cmdstr, "r");
while (-1 != sreadline(dst, dst_len, pp)) {
- combo_ptr = strcasestr(dst, combo);
+ combo_ptr = xstrcasestr(dst, combo);
if (NULL != combo_ptr) {
combo_post = combo_ptr[strlen(combo)];
if ('.' == combo_post || '\0' == combo_post) {
diff --git a/src/util.c b/src/util.c
index 1216080..47adfab 100644
--- a/src/util.c
+++ b/src/util.c
@@ -326,6 +326,35 @@ size_t xmbstowcs(wchar_t *dest, const char *src, size_t n) {
return res;
}
+char *xstrcasestr(const char *haystack, const char *needle) {
+#if defined(__GLIBC__) && (defined(_GNU_SOURCE) || defined(_DEFAULT_SOURCE))
+ return strcasestr(haystack, needle);
+#else
+ unsigned i = 0, j;
+ char haystack_c, needle_c;
+
+ if (L'\0' == needle[0])
+ return (char *)haystack;
+
+ while (L'\0' != haystack[i]) {
+ j = 0;
+ while (TRUE) {
+ haystack_c = tolower(haystack[i + j]);
+ needle_c = tolower(needle[j]);
+ if (L'\0' == needle_c)
+ return (char *)&haystack[i];
+ else if (haystack_c != needle_c)
+ break;
+ else
+ j++;
+ }
+ i++;
+ }
+
+ return NULL;
+#endif
+}
+
int xsystem(const char *cmd, bool fail) {
int res = system(cmd);
diff --git a/src/util.h b/src/util.h
index 2f5caf1..2ca4185 100644
--- a/src/util.h
+++ b/src/util.h
@@ -193,7 +193,8 @@ void is_readable(const char *path);
// Safely call `calloc()`
extern void *xcalloc(size_t nmemb, size_t size);
-// Safely call `reallocarray()`
+// Safely call `reallocarray()` if it exists, or our own local implementation if
+// it doesn't
extern void *xreallocarray(void *ptr, size_t nmemb, size_t size);
// Safely call `popen()`
@@ -258,12 +259,16 @@ extern wchar_t *xwcsdup(const wchar_t *s);
// you're converting/copying parts of strings), use their vanilla counterparts
// instead.
-// Safely call wcstombs()
+// Safely call `wcstombs()`
extern size_t xwcstombs(char *dest, const wchar_t *src, size_t n);
-// Safely call mbstowcs()
+// Safely call `mbstowcs()`
size_t xmbstowcs(wchar_t *dest, const char *src, size_t n);
+// Safely call `strcasestr()` if it exists, or our own local implementation if
+// it doesn't
+extern char *xstrcasestr(const char *haystack, const char *needle);
+
// Safely call `system(cmd)`, to execute `cmd` in a new shell. If `fail` is
// true, and the return value of `system()` is non-zero, terminate. Otherwise
// return said return value.
--
2.55.0