diff options
Diffstat (limited to 'proxy/src/gp_util.c')
-rw-r--r-- | proxy/src/gp_util.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/proxy/src/gp_util.c b/proxy/src/gp_util.c index a6c870f..4fbac4e 100644 --- a/proxy/src/gp_util.c +++ b/proxy/src/gp_util.c @@ -27,6 +27,8 @@ #include <stdbool.h> #include <string.h> #include <stdlib.h> +#include <stdio.h> +#include <errno.h> bool gp_same(const char *a, const char *b) { @@ -66,3 +68,60 @@ char *gp_getenv(const char *name) return NULL; #endif } + +/* NOTE: because strerror_r() is such a mess with glibc, we need to do some + * magic checking to find out what function prototype is being used of the + * two incompatible ones, and pray it doesn't change in the future. + * On top of that to avoid impacting the current code too much we've got to use + * thread-local storage to hold a buffer. + * gp_strerror() is basically a thread-safe version of strerror() that can + * never fail. + */ +const char gp_internal_err[] = "Internal strerror_r() error."; +#define MAX_GP_STRERROR 1024 +char *gp_strerror(int errnum) +{ + static __thread char buf[MAX_GP_STRERROR]; + int saved_errno = errno; + +#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) + /* XSI version */ + int ret; + + ret = strerror_r(errnum, buf, MAX_GP_STRERROR); + if (ret == -1) ret = errno; + switch (ret) { + case 0: + break; + case EINVAL: + ret = snprintf(buf, MAX_GP_STRERROR, + "Unknown error code: %d", errnum); + if (ret > 0) break; + /* fallthrough */ + default: + ret = snprintf(buf, MAX_GP_STRERROR, + "Internal error describing error code: %d", errnum); + if (ret > 0) break; + memset(buf, 0, MAX_GP_STRERROR); + strncpy(buf, gp_internal_err, MAX_GP_STRERROR); + buf[MAX_GP_STRERROR -1] = '\0'; + } +#else + /* GNU-specific version */ + char *ret; + + ret = strerror_r(errnum, buf, MAX_GP_STRERROR); + if (ret == NULL) { + memset(buf, 0, MAX_GP_STRERROR); + strncpy(buf, gp_internal_err, MAX_GP_STRERROR); + buf[MAX_GP_STRERROR -1] = '\0'; + } else if (ret != buf) { + memset(buf, 0, MAX_GP_STRERROR); + strncpy(buf, ret, MAX_GP_STRERROR); + buf[MAX_GP_STRERROR -1] = '\0'; + } +#endif + + errno = saved_errno; + return buf; +} |