/* * 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(); }