Nicolas Bernard's Toolbox - Debugging Functions

Download: debug.h debug.c

debug.h

  1: /*
  2:  * Debugging fonctions
  3:  *
  4:  * Copyright 2004-2009 Nicolas Bernard <http://www.lafraze.net/nbernard/>
  5:  * All rights reserved.
  6:  *
  7:  * Permission to use, copy, modify, and distribute this software for any
  8:  * purpose with or without fee is hereby granted, provided that the above
  9:  * copyright notice and this permission notice appear in all copies.
 10:  *
 11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 17:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 18:  *
 19:  */
 20: 
 21: /*
 22:  * IMPORTANT WARNING
 23:  *
 24:  * Beware of string format vulnerabilities: ensure an attacker cannot control
 25:  * the format string!
 26:  */
 27: 
 28: #ifndef _DEBUG_H_
 29: #define _DEBUG_H_
 30: 
 31: #include <stdarg.h>
 32: #include <stdio.h>
 33: #include <stdlib.h>
 34: #include <syslog.h>
 35: #include <unistd.h>
 36: #include "confloader/confloader.h"
 37: 
 38: log_t logtype;
 39: 
 40: FILE* logfiledesc;
 41: 
 42: #ifndef WITHOUT_DEBUG_POS
 43: #define debug(...) debugf(debug.h.html, 52, __func__, __VA_ARGS__)
 44: #define panic(...) panicf(debug.h.html, 53, __func__, __VA_ARGS__)
 45: #define logger(...) loggerf(debug.h.html, 54, __func__, __VA_ARGS__)
 46: #ifdef _WITH_ERRSTACK_
 47: #define stkdbg(...) stkdebugf(debug.h.html, 56, __func__, __VA_ARGS__)
 48: #else
 49: #define stkdbg(...) debugf(debug.h.html, 58, __func__, __VA_ARGS__)
 50: #endif
 51: #else
 52: #define debug(...) debugf(NULL, 0, NULL, __VA_ARGS__)
 53: #define panic(...) panicf(NULL, 0, NULL, __VA_ARGS__)
 54: #define logger(...) loggerf(NULL, 0, NULL, __VA_ARGS__)
 55: #ifdef _WITH_ERRSTACK_
 56: #define stkdbg(...) stkdebugf(NULL, 0, NULL, __VA_ARGS__)
 57: #else
 58: #define stkdbg(...) debugf(NULL, 0, NULL, __VA_ARGS__)
 59: #endif
 60: #endif  /* ! WITH_DEBUG_POS */
 61: 
 62: void debugf(const char* file, int line, const char* func, const char* fmt, ...)
 63:         __attribute__ ((format (printf, 4, 5))); /* Flawfinder: ignore */
 64: void panicf(const char* file, int line, const char* func, const char* fmt, ...)
 65:         __attribute__ ((format (printf, 4, 5), noreturn)); /* Flawfinder: ignore */
 66: void loggerf(const char* file, int line, const char* func, int priority, const char* fmt, ...)
 67:         __attribute__ ((format (printf, 5, 6)));  /* Flawfinder: ignore */
 68: 
 69: //#define free(a) debugf(debug.h.html, 78, __func__, "free(%p)", (void*) a); free(a);
 70: //#define close(a) 0; debugf(debug.h.html, 79, __func__, "close(%d)", a); close(a)
 71: #define exit(a) {debugf(debug.h.html, 80, __func__, "exit(%d)", a); exit(a);};
 72: 
 73: #include "dsession.h"
 74: #define dsessionforceclosed(a)  {debugf(debug.h.html, 83, __func__, "dsessionforceclosed(%p)", a); dsessionforceclosedf(a);};
 75: 
 76: #ifdef _WITH_ERRSTACK_
 77: void dumperrstack(log_t where);
 78: void dumperrstackstderr(void); /* useful with atexit */
 79: void flusherrstack(void); /* if the error was recovered and doesn't need to be
 80:                              remembered... */
 81: void stkdebugf(const char* file, int line, const char* func, const char* fmt, ...);
 82: #endif /* _WITH_ERRSTACK_*/
 83: 
 84: #endif /* _DEBUG_H_ */

debug.c

  1: /*
  2:  * Debugging fonctions
  3:  *
  4:  * Copyright 2004-2009 Nicolas Bernard <http://www.lafraze.net/nbernard/>
  5:  * All rights reserved.
  6:  *
  7:  * Permission to use, copy, modify, and distribute this software for any
  8:  * purpose with or without fee is hereby granted, provided that the above
  9:  * copyright notice and this permission notice appear in all copies.
 10:  *
 11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 17:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 18:  *
 19:  */
 20: 
 21: #include <sys/types.h>
 22: 
 23: #include <assert.h>
 24: #include <stdlib.h>
 25: #include <string.h>
 26: #include <unistd.h>
 27: 
 28: #include "confloader/confloader.h"
 29: #include "debug.h"
 30: 
 31: 
 32: /** \todo: errstack is not compatible with priorities (dumperrstack LOG__SYSLOG
 33:     will dump everythink with priority LOG_ERR). */
 34: 
 35: 
 36: #ifdef _WITH_ERRSTACK_
 37: 
 38: #include "list.h"
 39: 
 40: static list_t errorstack = -1;
 41: 
 42: #endif /* _WITH_ERRSTACK_*/
 43: 
 44: 
 45: 
 46: #define MAXLOGLINE 512
 47: 
 48: static void
 49: /* Flawfinder: ignore */ /* logline is a pointer */
 50: pushlogline(char logline[MAXLOGLINE], int priority)
 51: {
 52:         switch(logtype) {
 53:         case LOG__NOTDEF:
 54:         case LOG__STDERR:
 55:         case LOG__STDOUT:
 56:                 logfiledesc = stderr;
 57:                 if (logtype == LOG__STDOUT)
 58:                         logfiledesc = stdout;
 59:                 else
 60:                         logfiledesc = stderr;
 61:                 logtype = LOG__FILE;
 62:         case LOG__FILE:
 63:                 fprintf(logfiledesc, "%s\n", logline);
 64:                 break;
 65:         case LOG__SYSLOG:
 66:                 /* The user of our fct must be wary of string format
 67:                    vulnerabilities when using our fct and not only
 68:                    when logtype is LOG__SYSLOG. */
 69:                 syslog(priority, logline); /* Flawfinder: ignore */
 70:                 break;
 71:         case LOG__NONE:
 72:                 break;
 73: #ifdef _WITH_ERRSTACK_
 74:         case LOG__ERRSTACK:
 75:                 if (errorstack == -1) {
 76:                         errorstack = list_create();
 77:                         if (errorstack == -1)
 78:                                 return;
 79:                 }
 80:                 list_add_head(errorstack, logline);
 81:                 break;
 82: #endif
 83:         default:
 84:         case ELOG:
 85:                 fprintf(stderr, "Log error, exiting\n");
 86:                 break;
 87:         }
 88:         return;
 89: }
 90: 
 91: static void
 92: logcommon(const char* file, int line, const char* func, int priority,
 93:           const char* fmt, va_list ap)
 94: {
 95:         /* loglines are truncated */
 96:         char lbuf[MAXLOGLINE] = {0}; /* Flawfinder: ignore */
 97:         char *buf = lbuf;
 98:         int where = 0;
 99: 
100: #ifdef _WITH_ERRSTACK_
101:         if (logtype == LOG__ERRSTACK) {
102:                 buf = calloc(MAXLOGLINE, sizeof(char));
103:                 if (buf == NULL) {
104:                         return;
105:                 }
106:         }
107: #endif /* _WITH_ERRSTACK_*/
108: 
109:         if (file != NULL) {
110:                 assert(func != NULL);
111:                 /* Flawfinder: ignore */ /* We assume a C99-compliant system. */
112:                 where = snprintf(buf, MAXLOGLINE, "(%d)[%s:%d %s] ",
113:                                  (int) getpid(), file, line, func);
114:         }
115: 
116:         /* The user of our fct must be wary of string format
117:            vulnerabilities when using our functions. */
118:         /* Flawfinder: ignore */
119:         (void) vsnprintf(buf + where, MAXLOGLINE - where, fmt, ap);
120: 
121:         pushlogline(buf, priority);
122:         return;
123: }
124: 
125: #ifdef _WITH_ERRSTACK_
126: void
127: dumperrstack(log_t where)
128: {
129:         if (where == LOG__ERRSTACK)
130:                 return;
131:         if (errorstack == -1)
132:                 return;
133: 
134:         log_t oldlt = logtype;
135:         logtype = where;
136: 
137:         char* logline = list_get_tail(errorstack);
138:         while (logline != NULL) {
139:                 pushlogline(logline, LOG_ERR);
140:                 list_del_tail(errorstack);
141:                 logline = list_get_tail(errorstack);
142:         }
143: 
144:         logtype = oldlt;
145:         return;
146: }
147: 
148: void
149: dumperrstackstderr(void)
150: {
151:         dumperrstack(LOG__STDERR);
152: }
153: 
154: void
155: flusherrstack(void)
156: {
157:         if (errorstack == -1)
158:                 return;
159:         while(list_get_tail(errorstack) != NULL)
160:                 list_del_tail(errorstack);
161: }
162: 
163: void
164: stkdebugf(const char* file, int line, const char* func, const char* fmt, ...)
165: {
166:         log_t oldlt = logtype;
167:         logtype = LOG__ERRSTACK;
168:         va_list ap;
169:         va_start(ap, fmt);
170:         logcommon(file, line, func, LOG_DEBUG, fmt, ap);
171:         va_end(ap);
172:         logtype = oldlt;
173: }
174: #endif /* _WITH_ERRSTACK_*/
175: 
176: void
177: debugf(const char* file, int line, const char* func, const char* fmt, ...)
178: {
179: #ifdef DEBUG
180:         va_list ap;
181:         va_start(ap, fmt);
182:         logcommon(file, line, func, LOG_DEBUG, fmt, ap);
183:         va_end(ap);
184: #endif /* DEBUG */
185: }
186: 
187: 
188: void
189: loggerf(const char* file, int line, const char* func, int priority, const char* fmt, ...)
190: {
191:         va_list ap;
192:         va_start(ap, fmt);
193:         logcommon(file, line, func, priority, fmt, ap);
194:         va_end(ap);
195: }
196: 
197: void
198: panicf(const char* file, int line, const char* func, const char* fmt, ...)
199: {
200:         va_list ap;
201:         va_start(ap, fmt);
202: #ifdef _WITH_ERRSTACK_
203:         dumperrstack(LOG__STDERR);
204: #endif
205:         logcommon(file, line, func, LOG_ERR, fmt, ap);
206:         va_end(ap);
207:         abort();
208: }