debuglog.c

Go to the documentation of this file.
00001 /*
00002  * MUSCLE SmartCard Development ( http://www.linuxnet.com )
00003  *
00004  * Copyright (C) 1999-2002
00005  *  David Corcoran <corcoran@linuxnet.com>
00006  * Copyright (C) 1999-2005
00007  *  Ludovic Rousseau <ludovic.rousseau@free.fr>
00008  *
00009  * $Id: debuglog.c 4241 2009-06-02 13:50:52Z rousseau $
00010  */
00011 
00017 #include "config.h"
00018 #ifdef HAVE_SYSLOG_H
00019 #include <syslog.h>
00020 #endif
00021 #include <unistd.h>
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #include <stdarg.h>
00026 #include <assert.h>
00027 #include <sys/types.h>
00028 #include <sys/time.h>
00029 #include <time.h>
00030 
00031 #include "pcsclite.h"
00032 #include "misc.h"
00033 #include "debuglog.h"
00034 #include "sys_generic.h"
00035 #include "strlcpycat.h"
00036 
00041 #define DEBUG_BUF_SIZE 2048
00042 
00043 static char LogSuppress = DEBUGLOG_LOG_ENTRIES;
00044 static char LogMsgType = DEBUGLOG_NO_DEBUG;
00045 static char LogCategory = DEBUG_CATEGORY_NOTHING;
00046 
00048 static char LogLevel = PCSC_LOG_ERROR;
00049 
00050 static signed char LogDoColor = 0;  
00052 static void log_line(const int priority, const char *DebugBuffer);
00053 
00054 void log_msg(const int priority, const char *fmt, ...)
00055 {
00056     char DebugBuffer[DEBUG_BUF_SIZE];
00057     va_list argptr;
00058 
00059     if ((LogSuppress != DEBUGLOG_LOG_ENTRIES)
00060         || (priority < LogLevel) /* log priority lower than threshold? */
00061         || (DEBUGLOG_NO_DEBUG == LogMsgType))
00062         return;
00063 
00064     va_start(argptr, fmt);
00065     vsnprintf(DebugBuffer, DEBUG_BUF_SIZE, fmt, argptr);
00066     va_end(argptr);
00067 
00068     log_line(priority, DebugBuffer);
00069 } /* log_msg */
00070 
00071 static void log_line(const int priority, const char *DebugBuffer)
00072 {
00073     if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
00074         syslog(LOG_INFO, "%s", DebugBuffer);
00075     else
00076     {
00077         if (LogDoColor)
00078         {
00079             const char *color_pfx = "", *color_sfx = "\33[0m";
00080             const char *time_pfx = "\33[36m", *time_sfx = color_sfx;
00081             static struct timeval last_time = { 0, 0 };
00082             struct timeval new_time = { 0, 0 };
00083             struct timeval tmp;
00084             int delta;
00085 
00086             switch (priority)
00087             {
00088                 case PCSC_LOG_CRITICAL:
00089                     color_pfx = "\33[01;31m"; /* bright + Red */
00090                     break;
00091 
00092                 case PCSC_LOG_ERROR:
00093                     color_pfx = "\33[35m"; /* Magenta */
00094                     break;
00095 
00096                 case PCSC_LOG_INFO:
00097                     color_pfx = "\33[34m"; /* Blue */
00098                     break;
00099 
00100                 case PCSC_LOG_DEBUG:
00101                     color_pfx = ""; /* normal (black) */
00102                     color_sfx = "";
00103                     break;
00104             }
00105 
00106             gettimeofday(&new_time, NULL);
00107             if (0 == last_time.tv_sec)
00108                 last_time = new_time;
00109 
00110             tmp.tv_sec = new_time.tv_sec - last_time.tv_sec;
00111             tmp.tv_usec = new_time.tv_usec - last_time.tv_usec;
00112             if (tmp.tv_usec < 0)
00113             {
00114                 tmp.tv_sec--;
00115                 tmp.tv_usec += 1000000;
00116             }
00117             if (tmp.tv_sec < 100)
00118                 delta = tmp.tv_sec * 1000000 + tmp.tv_usec;
00119             else
00120                 delta = 99999999;
00121 
00122             fprintf(stderr, "%s%.8d%s %s%s%s\n", time_pfx, delta, time_sfx,
00123                 color_pfx, DebugBuffer, color_sfx);
00124             last_time = new_time;
00125         }
00126         else
00127             fprintf(stderr, "%s\n", DebugBuffer);
00128     }
00129 } /* log_msg */
00130 
00131 static void log_xxd_always(const int priority, const char *msg,
00132     const unsigned char *buffer, const int len)
00133 {
00134     char DebugBuffer[DEBUG_BUF_SIZE];
00135     int i;
00136     char *c;
00137     char *debug_buf_end;
00138 
00139     debug_buf_end = DebugBuffer + DEBUG_BUF_SIZE - 5;
00140 
00141     strlcpy(DebugBuffer, msg, sizeof(DebugBuffer));
00142     c = DebugBuffer + strlen(DebugBuffer);
00143 
00144     for (i = 0; (i < len) && (c < debug_buf_end); ++i)
00145     {
00146         sprintf(c, "%02X ", buffer[i]);
00147         c += 3;
00148     }
00149 
00150     /* the buffer is too small so end it with "..." */
00151     if ((c >= debug_buf_end) && (i < len))
00152         c[-3] = c[-2] = c[-1] = '.';
00153 
00154     log_line(priority, DebugBuffer);
00155 } /* log_xxd_always */
00156 
00157 void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
00158     const int len)
00159 {
00160     if ((LogSuppress != DEBUGLOG_LOG_ENTRIES)
00161         || (priority < LogLevel) /* log priority lower than threshold? */
00162         || (DEBUGLOG_NO_DEBUG == LogMsgType))
00163         return;
00164 
00165     log_xxd_always(priority, msg, buffer, len);
00166 } /* log_xxd */
00167 
00168 #ifdef PCSCD
00169 void DebugLogSuppress(const int lSType)
00170 {
00171     LogSuppress = lSType;
00172 }
00173 #endif
00174 
00175 void DebugLogSetLogType(const int dbgtype)
00176 {
00177     switch (dbgtype)
00178     {
00179         case DEBUGLOG_NO_DEBUG:
00180         case DEBUGLOG_SYSLOG_DEBUG:
00181         case DEBUGLOG_STDERR_DEBUG:
00182             LogMsgType = dbgtype;
00183             break;
00184         default:
00185             Log2(PCSC_LOG_CRITICAL, "unknown log type (%d), using stderr",
00186                 dbgtype);
00187             LogMsgType = DEBUGLOG_STDERR_DEBUG;
00188     }
00189 
00190     /* log to stderr and stderr is a tty? */
00191     if (DEBUGLOG_STDERR_DEBUG == LogMsgType && isatty(fileno(stderr)))
00192     {
00193         const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode" };
00194         char *term;
00195 
00196         term = getenv("TERM");
00197         if (term)
00198         {
00199             unsigned int i;
00200 
00201             /* for each known color terminal */
00202             for (i = 0; i < sizeof(terms) / sizeof(terms[0]); i++)
00203             {
00204                 /* we found a supported term? */
00205                 if (0 == strcmp(terms[i], term))
00206                 {
00207                     LogDoColor = 1;
00208                     break;
00209                 }
00210             }
00211         }
00212     }
00213 }
00214 
00215 void DebugLogSetLevel(const int level)
00216 {
00217     LogLevel = level;
00218     switch (level)
00219     {
00220         case PCSC_LOG_CRITICAL:
00221         case PCSC_LOG_ERROR:
00222             /* do not log anything */
00223             break;
00224 
00225         case PCSC_LOG_INFO:
00226             Log1(PCSC_LOG_INFO, "debug level=notice");
00227             break;
00228 
00229         case PCSC_LOG_DEBUG:
00230             Log1(PCSC_LOG_DEBUG, "debug level=debug");
00231             break;
00232 
00233         default:
00234             LogLevel = PCSC_LOG_INFO;
00235             Log2(PCSC_LOG_CRITICAL, "unknown level (%d), using level=notice",
00236                 level);
00237     }
00238 }
00239 
00240 INTERNAL int DebugLogSetCategory(const int dbginfo)
00241 {
00242 #define DEBUG_INFO_LENGTH 80
00243     char text[DEBUG_INFO_LENGTH];
00244 
00245     /* use a negative number to UNset
00246      * typically use ~DEBUG_CATEGORY_APDU
00247      */
00248     if (dbginfo < 0)
00249         LogCategory &= dbginfo;
00250     else
00251         LogCategory |= dbginfo;
00252 
00253     /* set to empty string */
00254     text[0] = '\0';
00255 
00256     if (LogCategory & DEBUG_CATEGORY_APDU)
00257         strlcat(text, " APDU", sizeof(text));
00258 
00259     Log2(PCSC_LOG_INFO, "Debug options:%s", text);
00260 
00261     return LogCategory;
00262 }
00263 
00264 INTERNAL void DebugLogCategory(const int category, const unsigned char *buffer,
00265     const int len)
00266 {
00267     if ((category & DEBUG_CATEGORY_APDU)
00268         && (LogCategory & DEBUG_CATEGORY_APDU))
00269         log_xxd_always(PCSC_LOG_INFO, "APDU: ", buffer, len);
00270 
00271     if ((category & DEBUG_CATEGORY_SW)
00272         && (LogCategory & DEBUG_CATEGORY_APDU))
00273         log_xxd_always(PCSC_LOG_INFO, "SW: ", buffer, len);
00274 }
00275 
00276 /*
00277  * old function supported for backward object code compatibility
00278  * defined only for pcscd
00279  */
00280 #ifdef PCSCD
00281 void debug_msg(const char *fmt, ...);
00282 void debug_msg(const char *fmt, ...)
00283 {
00284     char DebugBuffer[DEBUG_BUF_SIZE];
00285     va_list argptr;
00286 
00287     if ((LogSuppress != DEBUGLOG_LOG_ENTRIES)
00288         || (DEBUGLOG_NO_DEBUG == LogMsgType))
00289         return;
00290 
00291     va_start(argptr, fmt);
00292     vsnprintf(DebugBuffer, DEBUG_BUF_SIZE, fmt, argptr);
00293     va_end(argptr);
00294 
00295     if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
00296         syslog(LOG_INFO, "%s", DebugBuffer);
00297     else
00298         fprintf(stderr, "%s\n", DebugBuffer);
00299 } /* debug_msg */
00300 
00301 void debug_xxd(const char *msg, const unsigned char *buffer, const int len);
00302 void debug_xxd(const char *msg, const unsigned char *buffer, const int len)
00303 {
00304     log_xxd(PCSC_LOG_ERROR, msg, buffer, len);
00305 } /* debug_xxd */
00306 #endif
00307 

Generated on Wed Jul 22 21:08:11 2009 for pcsc-lite by  doxygen 1.5.8