/*
* Debugging fonctions
*
* Copyright 2004-2009 Nicolas Bernard
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include
#include
#include
#include
#include
#include "confloader/confloader.h"
#include "debug.h"
/** \todo: errstack is not compatible with priorities (dumperrstack LOG__SYSLOG
will dump everythink with priority LOG_ERR). */
#ifdef _WITH_ERRSTACK_
#include "list.h"
static list_t errorstack = -1;
#endif /* _WITH_ERRSTACK_*/
#define MAXLOGLINE 512
static void
/* Flawfinder: ignore */ /* logline is a pointer */
pushlogline(char logline[MAXLOGLINE], int priority)
{
switch(logtype) {
case LOG__NOTDEF:
case LOG__STDERR:
case LOG__STDOUT:
logfiledesc = stderr;
if (logtype == LOG__STDOUT)
logfiledesc = stdout;
else
logfiledesc = stderr;
logtype = LOG__FILE;
case LOG__FILE:
fprintf(logfiledesc, "%s\n", logline);
break;
case LOG__SYSLOG:
/* The user of our fct must be wary of string format
vulnerabilities when using our fct and not only
when logtype is LOG__SYSLOG. */
syslog(priority, logline); /* Flawfinder: ignore */
break;
case LOG__NONE:
break;
#ifdef _WITH_ERRSTACK_
case LOG__ERRSTACK:
if (errorstack == -1) {
errorstack = list_create();
if (errorstack == -1)
return;
}
list_add_head(errorstack, logline);
break;
#endif
default:
case ELOG:
fprintf(stderr, "Log error, exiting\n");
break;
}
return;
}
static void
logcommon(const char* file, int line, const char* func, int priority,
const char* fmt, va_list ap)
{
/* loglines are truncated */
char lbuf[MAXLOGLINE] = {0}; /* Flawfinder: ignore */
char *buf = lbuf;
int where = 0;
#ifdef _WITH_ERRSTACK_
if (logtype == LOG__ERRSTACK) {
buf = calloc(MAXLOGLINE, sizeof(char));
if (buf == NULL) {
return;
}
}
#endif /* _WITH_ERRSTACK_*/
if (file != NULL) {
assert(func != NULL);
/* Flawfinder: ignore */ /* We assume a C99-compliant system. */
where = snprintf(buf, MAXLOGLINE, "(%d)[%s:%d %s] ",
(int) getpid(), file, line, func);
}
/* The user of our fct must be wary of string format
vulnerabilities when using our functions. */
/* Flawfinder: ignore */
(void) vsnprintf(buf + where, MAXLOGLINE - where, fmt, ap);
pushlogline(buf, priority);
return;
}
#ifdef _WITH_ERRSTACK_
void
dumperrstack(log_t where)
{
if (where == LOG__ERRSTACK)
return;
if (errorstack == -1)
return;
log_t oldlt = logtype;
logtype = where;
char* logline = list_get_tail(errorstack);
while (logline != NULL) {
pushlogline(logline, LOG_ERR);
list_del_tail(errorstack);
logline = list_get_tail(errorstack);
}
logtype = oldlt;
return;
}
void
dumperrstackstderr(void)
{
dumperrstack(LOG__STDERR);
}
void
flusherrstack(void)
{
if (errorstack == -1)
return;
while(list_get_tail(errorstack) != NULL)
list_del_tail(errorstack);
}
void
stkdebugf(const char* file, int line, const char* func, const char* fmt, ...)
{
log_t oldlt = logtype;
logtype = LOG__ERRSTACK;
va_list ap;
va_start(ap, fmt);
logcommon(file, line, func, LOG_DEBUG, fmt, ap);
va_end(ap);
logtype = oldlt;
}
#endif /* _WITH_ERRSTACK_*/
void
debugf(const char* file, int line, const char* func, const char* fmt, ...)
{
#ifdef DEBUG
va_list ap;
va_start(ap, fmt);
logcommon(file, line, func, LOG_DEBUG, fmt, ap);
va_end(ap);
#endif /* DEBUG */
}
void
loggerf(const char* file, int line, const char* func, int priority, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
logcommon(file, line, func, priority, fmt, ap);
va_end(ap);
}
void
panicf(const char* file, int line, const char* func, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
#ifdef _WITH_ERRSTACK_
dumperrstack(LOG__STDERR);
#endif
logcommon(file, line, func, LOG_ERR, fmt, ap);
va_end(ap);
abort();
}