/* * debug.cc - Self explanitory * Copyright (C) 1997-2000 SpellCaster Telecommunications Inc. * $Id: debug.cc,v 1.3 2004/08/15 23:20:02 bcrl Exp $ * Released under the GNU Public License. See LICENSE file for details. */ #include "debug.h" #include #include #include #include #include #ifndef MIN #define MIN(x,y) ((x < y) ? (x) : (y)) #endif static dbg_info_t dbg_settings; dbg_info_t *dbg_ptr = &dbg_settings; ////////////////////////////////////////////////////////////////////////// // PRINTING ////////////////////////////////////////////////////////////////////////// /* * Take an unsigned character array and make it human readable. out_buf * must be long enough to handle the printed string * */ inline int PrintBuffer(const unsigned char *in_buf, char *out_buf, unsigned int in_len) { register uint i, j = 0; int trunc_f = 0; char hex_table[] = "0123456789ABCDEF"; if(in_len > 256) { in_len = 256; trunc_f = 1; } for(i = 0 ; i < in_len ; i++) { out_buf[j++] = hex_table[(in_buf[i] & 0xf0) >> 4]; out_buf[j++] = hex_table[in_buf[i] & 0x0f]; if(i + 1 != in_len) { /* Last byte? */ out_buf[j++] = '-'; } } if(trunc_f) { // The buffer was truncated due to length out_buf[j++] = '.'; out_buf[j++] = '.'; out_buf[j++] = '.'; } return j; } void PrintSyslog(unsigned char level, char * msg) { syslog(level, msg); } void PrintFile(char *str) { fprintf(dbg_ptr->log_file_fd, "%s\n", str); fflush(dbg_ptr->log_file_fd); } void PrintStderr(char *str) { fprintf(stderr, "%s\n", str); fflush(stderr); } static inline int WillLog(unsigned short fl) { if ((dbg_ptr->log_state == OPEN) && (!fl || ((dbg_ptr->log_flags > (fl & 0xf000)) && ((dbg_ptr->log_flags & 0x0fff) & fl)))) { return (dbg_ptr->log_facility & LT_SYSLOG) || (dbg_ptr->log_facility & LT_FILE) || (dbg_ptr->log_facility & LT_STDERR); } return 0; } void Log(unsigned short fl, const char *fmt, ...) { va_list args; /* * See if we should log this message */ if (!WillLog(fl)) return; dbg_ptr->log_buffer[0] = 0; va_start(args, fmt); vsnprintf(dbg_ptr->log_buffer, LOG_BUFFER_SIZE, fmt, args); va_end(args); if (dbg_ptr->log_facility & LT_SYSLOG) PrintSyslog((unsigned char)(dbg_ptr->log_flags >> 12), dbg_ptr->log_buffer); if (dbg_ptr->log_facility & LT_FILE) PrintFile(dbg_ptr->log_buffer); if (dbg_ptr->log_facility & LT_STDERR) PrintStderr(dbg_ptr->log_buffer); } static inline char tohex(unsigned char foo) { if (foo >= 10) return 'a' + foo - 0xa; return foo + '0'; } void LogPacket(unsigned short fl, unsigned char *buf, int len) { char line[80]; int x, i; if (!WillLog(fl)) return; memset(line, ' ', sizeof(line)); for (x=i=0; i> 12) & 0xf); line[x++] = tohex((i >> 8) & 0xf); line[x++] = tohex((i >> 4) & 0xf); line[x++] = tohex(i & 0xf); line[x++] = ':'; x++; } line[x++] = tohex(buf[i] >> 4); line[x++] = tohex(buf[i] & 0xf); if (3 == (i % 4)) x++; line[(i % 16) + 48] = isprint(buf[i]) ? buf[i] : '.'; if (15 == (i % 16)) { line[16 + 48] = 0; Log(fl, "%s", line); x = 0; } } if (i % 16) { line[48 + (i % 16)] = 0; for (; i % 16; i++) { line[x++] = ' '; line[x++] = ' '; if (3 == (i % 4)) x++; } Log(fl, "%s", line); } } ////////////////////////////////////////////////////////////////////////// // INITIALIZATION AND CLEANUP ////////////////////////////////////////////////////////////////////////// /* * Open and possibly initialize the logging facility. * Returns 0 (FALSE) if successful. Returns -1 of no logs were * initialized. */ int InitLog(const char *program_name) { if(dbg_ptr->log_state == OPEN) // We're already opened! return 0; /* * Initialize the function stack */ memset(dbg_ptr->f_stack, 0, sizeof(struct f_info) * STACK_SIZE); dbg_ptr->f_sp = 0; /* * If we're doing syslog, open the log and set the * mask */ if(dbg_ptr->log_facility & LT_SYSLOG) { strcpy(dbg_ptr->p_name, program_name); openlog(program_name, LOG_NDELAY | LOG_PID, dbg_ptr->sl_facility); setlogmask(LOG_UPTO(dbg_ptr->log_flags >> 12)); dbg_ptr->log_state = OPEN; } /* * If we're logging to a file, open the file now */ if(dbg_ptr->log_facility & LT_FILE) { dbg_ptr->log_file_fd = fopen(dbg_ptr->log_file_name, "w"); if(dbg_ptr->log_file_fd) dbg_ptr->log_state = OPEN; } /* * If we're logging to stderr, do nothing but indicate * the log is open */ if(dbg_ptr->log_facility & LT_STDERR) dbg_ptr->log_state = OPEN; if(dbg_ptr->log_state == OPEN) return 0; else return -1; } /* * Call to reset the log flags after the log is aready opened. * properly handles syslog masking */ void ResetLogFlags(void) { if(dbg_ptr->log_state == OPEN) { /* * Close syslog in case something changed */ closelog(); /* * reset the syslog mask if we're doing syslog */ if(dbg_ptr->log_flags & LT_SYSLOG) { openlog(dbg_ptr->p_name, LOG_NDELAY | LOG_PID, dbg_ptr->sl_facility); setlogmask(LOG_UPTO(dbg_ptr->log_flags >> 24)); } } } /* * Close the log facility opened with InitLog. This is probably optional * but is here for completeness. */ void CloseLog(void) { if(dbg_ptr->log_state == OPEN) { /* * close syslog */ if(dbg_ptr->log_facility & LT_SYSLOG) closelog(); /* * Close the log file */ if((dbg_ptr->log_facility & LT_FILE) && dbg_ptr->log_file_fd) fclose(dbg_ptr->log_file_fd); dbg_ptr->log_state = CLOSED; } } #ifdef DEBUG_TRACE /* * Tell the logging system we've entered a function */ void DebugEnter(char *func_name) { dbg_ptr->f_sp++; if(dbg_ptr->f_sp == STACK_SIZE) { // Stack overrun, back off Log(LF_DEBUG, "!!! Debug stack overrun !!!"); --dbg_ptr->f_sp; } strcpy(dbg_ptr->f_stack[dbg_ptr->f_sp].name, func_name); gettimeofday(&dbg_ptr->f_stack[dbg_ptr->f_sp].time_in, NULL); Log(LF_DEBUG | LF_FUNCS, ">>> %d ----- Entered %s ------ >>>", dbg_ptr->f_sp-1, dbg_ptr->f_stack[dbg_ptr->f_sp].name); } /* * Tell the logging system we've left a function */ void DebugExit(void) { struct timeval tn; unsigned long td = 0L; unsigned int s; /* * calculate the difference in time between going into * the function and leaving it */ gettimeofday(&tn, NULL); s = tn.tv_sec - dbg_ptr->f_stack[dbg_ptr->f_sp].time_in.tv_sec; td = s * 1000000 + (tn.tv_usec - dbg_ptr->f_stack[dbg_ptr->f_sp].time_in.tv_usec); dbg_ptr->f_sp--; if(dbg_ptr->f_sp < 0) { // Stack underrun! Log(LF_DEBUG, "!!! Debug stack underrun !!!"); ++dbg_ptr->f_sp; } Log(LF_DEBUG | LF_FUNCS, "<<< %d ----- Leaving %s after %ldus ------ <<<", dbg_ptr->f_sp, dbg_ptr->f_stack[dbg_ptr->f_sp + 1].name, td); } #endif