diff --git a/src/utils/error.c b/src/utils/error.c
index 7eef71263d70b695945da5671e55d0e632a05377..f40e31ada656f24e4719783bbe279cf49cfb7be2 100644 (file)
--- a/src/utils/error.c
+++ b/src/utils/error.c
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif /* HAVE_CONFIG_H */
+
#include "utils/error.h"
+#include "utils/strbuf.h"
#include <pthread.h>
typedef struct {
int prio;
- char msg[SDB_MAX_ERROR];
+ sdb_strbuf_t *msg;
_Bool logged;
} sdb_error_ctx_t;
-#define SDB_ERROR_INIT { -1, "", 1 }
+#define SDB_ERROR_INIT { -1, NULL, 1 }
/*
* private variables
static pthread_key_t error_ctx_key;
static _Bool error_ctx_key_initialized = 0;
+static int (*logger)(int prio, const char *msg) = NULL;
+
/*
* private helper functions
*/
static void
-sdb_error_ctx_destructor(void *ctx)
+sdb_error_ctx_destructor(void *p)
{
+ sdb_error_ctx_t *ctx = p;
+
if (! ctx)
return;
+
+ sdb_strbuf_destroy(ctx->msg);
free(ctx);
} /* sdb_error_ctx_destructor */
return NULL;
*ctx = default_error_ctx;
+ ctx->msg = sdb_strbuf_create(64);
+ if (! ctx->msg) {
+ free(ctx);
+ return NULL;
+ }
if (! error_ctx_key_initialized)
sdb_error_ctx_init();
} /* sdb_error_get_ctx */
static int
-sdb_error_clear(void)
+sdb_error_vprintf(const char *fmt, va_list ap)
{
sdb_error_ctx_t *ctx;
if (! ctx)
return -1;
- ctx->prio = -1;
- ctx->msg[0] = '\0';
- ctx->logged = 1;
- return 0;
-} /* sdb_error_clear */
+ ctx->logged = 0;
+ return (int)sdb_strbuf_vsprintf(ctx->msg, fmt, ap);
+} /* sdb_error_vprintf */
static int
sdb_error_vappend(const char *fmt, va_list ap)
{
sdb_error_ctx_t *ctx;
- size_t len;
ctx = sdb_error_get_ctx();
if (! ctx)
return -1;
- len = strlen(ctx->msg);
- if (len >= sizeof(ctx->msg))
- return 0; /* nothing written */
-
ctx->logged = 0;
- return vsnprintf(ctx->msg + len, sizeof(ctx->msg) - len, fmt, ap);
+ return (int)sdb_strbuf_vappend(ctx->msg, fmt, ap);
} /* sdb_error_vappend */
static int
if (ctx->logged)
return 0;
- ret = fprintf(stderr, "[%s] %s\n",
- SDB_LOG_PRIO_TO_STRING(prio), ctx->msg);
+ if (logger)
+ ret = logger(prio, sdb_strbuf_string(ctx->msg));
+ else
+ ret = fprintf(stderr, "[%s] %s\n", SDB_LOG_PRIO_TO_STRING(prio),
+ sdb_strbuf_string(ctx->msg));
+
ctx->logged = 1;
return ret;
} /* sdb_do_log */
* public API
*/
+void
+sdb_error_set_logger(int (*f)(int, const char *))
+{
+ logger = f;
+} /* sdb_error_set_logger */
+
int
sdb_log(int prio, const char *fmt, ...)
{
va_list ap;
int ret;
- if (sdb_error_clear())
- return -1;
-
va_start(ap, fmt);
- ret = sdb_error_vappend(fmt, ap);
+ ret = sdb_error_vprintf(fmt, ap);
va_end(ap);
- sdb_do_log(prio);
+ if (ret > 0)
+ sdb_do_log(prio);
return ret;
} /* sdb_log */
va_list ap;
int ret;
- if (sdb_error_clear())
- return -1;
-
va_start(ap, fmt);
- ret = sdb_error_vappend(fmt, ap);
+ ret = sdb_error_vprintf(fmt, ap);
va_end(ap);
return ret;
return ret;
} /* sdb_error_append */
+int
+sdb_error_chomp(void)
+{
+ sdb_error_ctx_t *ctx;
+
+ ctx = sdb_error_get_ctx();
+ if (! ctx)
+ return -1;
+
+ sdb_strbuf_chomp(ctx->msg);
+ return 0;
+} /* sdb_error_chomp */
+
int
sdb_error_log(int prio)
{
ctx = sdb_error_get_ctx();
if (! ctx)
return "success";
- return ctx->msg;
+ return sdb_strbuf_string(ctx->msg);
} /* sdb_error_get */
int
return ctx->prio;
} /* sdb_error_get_prio */
+char *
+sdb_strerror(int errnum, char *strerrbuf, size_t buflen)
+{
+#if STRERROR_R_CHAR_P
+ {
+ char *tmp = strerror_r(errnum, strerrbuf, buflen);
+ if (*strerrbuf = '\0') {
+ if (tmp && (tmp != strerrbuf) && (*tmp != '\0'))
+ strncpy(strerrbuf, tmp, buflen);
+ else
+ snprintf(strerrbuf, buflen, "unknown error #%i "
+ "(strerror_r(3) did not return an error message)",
+ errnum);
+ }
+ }
+#else
+ if (strerror_r(errnum, strerrbuf, buflen))
+ snprintf(strerrbuf, buflen, "unknown error #%i "
+ "(strerror_r(3) failed)", errnum);
+#endif
+
+ strerrbuf[buflen - 1] = '\0';
+ return strerrbuf;
+} /* sdb_strerror */
+
/* vim: set tw=78 sw=4 ts=4 noexpandtab : */