int debug_level = -1;\r
\r
static FILE* log_output;\r
+static log_callback_t *log_callbacks = NULL;\r
\r
-static void *privData;\r
-static logCallback callback;\r
static time_t start;\r
\r
-void log_setCallback(logCallback c, void *p)\r
-{\r
- callback = c;\r
- privData = p;\r
-}\r
-\r
-static char *log_strings[5] = \r
+static char *log_strings[5] =\r
{\r
"User: ",\r
"Error: ",\r
count++;\r
va_list args;\r
char buffer[512];\r
+ log_callback_t *cb;\r
\r
if (level > debug_level)\r
return;\r
\r
va_start(args, format);\r
vsnprintf(buffer, 512, format, args);\r
+ va_end(args);\r
+\r
+ if (level == LOG_OUTPUT)\r
+ {\r
+ /* do not prepend any headers, just print out what we were given and return */\r
+ fputs(buffer, log_output);\r
+ fflush(log_output);\r
+ return;\r
+ }\r
\r
char *f = strrchr(file, '/');\r
if (f != NULL)\r
\r
fflush(log_output);\r
\r
- va_end(args);\r
-\r
/* Never forward LOG_DEBUG, too verbose and they can be found in the log if need be */\r
- if (callback && (level <= LOG_INFO))\r
+ if (level <= LOG_INFO)\r
{\r
- va_start(args, format);\r
- callback(privData, file, line, function, format, args);\r
- va_end(args);\r
+ for (cb = log_callbacks; cb; cb = cb->next)\r
+ {\r
+ va_start(args, format);\r
+ cb->fn(cb->priv, file, line, function, format, args);\r
+ va_end(args);\r
+ }\r
}\r
}\r
\r
return ERROR_OK;\r
}\r
\r
+/* add/remove log callback handler */\r
+int log_add_callback(log_callback_fn fn, void *priv)\r
+{\r
+ log_callback_t *cb;\r
+\r
+ /* prevent the same callback to be registered more than once, just for sure */\r
+ for (cb = log_callbacks; cb; cb = cb->next)\r
+ {\r
+ if (cb->fn == fn && cb->priv == priv)\r
+ return ERROR_INVALID_ARGUMENTS;\r
+ }\r
+\r
+ /* alloc memory, it is safe just to return in case of an error, no need for the caller to check this */\r
+ if ((cb = malloc(sizeof(log_callback_t))) == NULL)\r
+ return ERROR_BUF_TOO_SMALL;\r
+\r
+ /* add item to the beginning of the linked list */\r
+ cb->fn = fn;\r
+ cb->priv = priv;\r
+ cb->next = log_callbacks;\r
+ log_callbacks = cb;\r
+\r
+ return ERROR_OK;\r
+}\r
+\r
+int log_remove_callback(log_callback_fn fn, void *priv)\r
+{\r
+ log_callback_t *cb, **p;\r
+\r
+ for (p = &log_callbacks; cb = *p; p = &(*p)->next)\r
+ {\r
+ if (cb->fn == fn && cb->priv == priv)\r
+ {\r
+ *p = cb->next;\r
+ free(cb);\r
+ return ERROR_OK;\r
+ }\r
+ }\r
+\r
+ /* no such item */\r
+ return ERROR_INVALID_ARGUMENTS;\r
+}\r
+\r
/* return allocated string w/printf() result */\r
-char *allocPrintf(const char *fmt, va_list ap)\r
+char *alloc_printf(const char *fmt, va_list ap)\r
{\r
char *string = NULL;\r
\r