dnl
AC_DEFUN([AC_USUAL_FUNCTION_CHECK], [
### Functions provided if missing
-AC_CHECK_FUNCS(basename strlcpy strlcat getpeereid sigaction)
-AC_CHECK_FUNCS(inet_ntop poll getline)
+AC_CHECK_FUNCS(basename dirname strlcpy strlcat getpeereid sigaction)
+AC_CHECK_FUNCS(inet_ntop poll getline memrchr)
AC_CHECK_FUNCS(err errx warn warnx getprogname setprogname)
AC_CHECK_FUNCS(posix_memalign memalign valloc)
### Functions provided only on win32
}
#endif
+#ifndef HAVE_MEMRCHR
+void *memrchr(const void *s, int c, size_t n)
+{
+ const uint8_t *p = s;
+ while (n--) {
+ if (p[n] == c)
+ return (void *)(p + n);
+ }
+ return NULL;
+}
+#endif
+
#ifndef HAVE_BASENAME
-char *basename(char *path)
+const char *basename(const char *path)
{
- char *p, *p2;
+ const char *p, *p2;
+ static char buf[256];
+ unsigned len;
+
if (path == NULL || path[0] == 0)
- return ".";
+ return memcpy(buf, ".", 2);
if ((p = strrchr(path, '/')) == NULL)
return path;
if (p[1])
/* last char is '/' */
for (p2 = p; p2 > path; p2--) {
if (p2[-1] != '/') {
- *p2 = 0;
- return basename(path);
+ len = p2 - path;
+ if (len > sizeof(buf) - 1)
+ len = sizeof(buf) - 1;
+ memcpy(buf, p2 - len, len);
+ buf[len] = 0;
+ return basename(buf);
}
}
/* path contains only '/' chars */
}
#endif
+#ifndef HAVE_DIRNAME
+const char *dirname(const char *path)
+{
+ const char *p;
+ size_t len;
+ static char buf[1024];
+
+ if (path == NULL || path[0] == 0)
+ return memcpy(buf, ".", 2);
+
+ /* ignore tailing '/' */
+ len = strlen(path);
+ while (len && path[len - 1] == '/')
+ len--;
+ if (!len)
+ return memcpy(buf, "/", 2);
+
+ /* find end of dirname, strip '/' */
+ if ((p = memrchr(path, '/', len)) == NULL)
+ return memcpy(buf, ".", 2);
+ len = p - path;
+ while (len && path[len - 1] == '/')
+ len--;
+ if (!len)
+ return memcpy(buf, "/", 2);
+
+ /* return it */
+ if (len > sizeof(buf) - 1) {
+ errno = ENAMETOOLONG;
+ return NULL;
+ }
+ memcpy(buf, path, len);
+ buf[len] = 0;
+ return buf;
+}
+#endif
+
#ifdef WIN32
const char *win32_strerror(int e)
{
static char buf[1024];
return strerror_r(e, buf, sizeof(buf));
}
-const char *win32_strerror_r(int e, char *dst, size_t dstlen)
+#endif
+
+/* restore original strerror_r() */
+#undef strerror_r
+
+const char *usual_strerror_r(int e, char *dst, size_t dstlen)
{
+#ifdef WIN32
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, e,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
dst, dstlen, NULL);
- return dst;
-}
-#else
-const char *wrap_strerror_r(int e, char *dst, size_t dstlen)
-{
-#undef strerror_r
+#else /* !WIN32 */
+
#ifdef STRERROR_R_CHAR_P
- return strerror_r(e, dst, dstlen);
+ dst = strerror_r(e, dst, dstlen);
#else
if (strerror_r(e, dst, dstlen) != 0)
strlcpy(dst, "ERR", dstlen);
- return dst;
#endif
+
+#endif /* !WIN32 */
+
+ return dst;
}
-#endif
size_t strlcat(char *dst, const char *src, size_t n);
#endif
+#ifndef HAVE_MEMRCHR
+#define memrchr(a,b,c) usual_memrchr(a,b,c)
+void *memrchr(const void *s, int c, size_t n);
+#endif
+
typedef bool (*str_cb)(void *arg, const char *s);
struct StrList;
#ifndef HAVE_BASENAME
-#define basename(a) compat_basename(a)
-char *basename(char *path);
+#define basename(a) usual_basename(a)
+const char *basename(const char *path);
+#endif
+
+#ifndef HAVE_DIRNAME
+#define dirname(a) usual_dirname(a)
+const char *dirname(const char *path);
#endif
/*
* strerror, strerror_r
*/
+
#ifdef WIN32
const char *win32_strerror(int e);
#define strerror(x) win32_strerror(x)
-const char *win32_strerror_r(int e, char *dst, size_t dstlen);
-#define strerror_r(a,b,c) win32_strerror_r(a,b,c)
-#else
-/* otherwise convert native strerror_r() to GNU signature */
-const char *wrap_strerror_r(int e, char *dst, size_t dstlen);
-#define strerror_r(a,b,c) wrap_strerror_r(a,b,c)
#endif
+/* convert native strerror_r() to GNU signature */
+const char *usual_strerror_r(int e, char *dst, size_t dstlen);
+#define strerror_r(a,b,c) usual_strerror_r(a,b,c)
+
#endif