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 2896 2008-04-22 09:20:00Z 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_INFO;
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 #ifndef WIN32
00066     vsnprintf(DebugBuffer, DEBUG_BUF_SIZE, fmt, argptr);
00067 #else
00068 #if HAVE_VSNPRINTF
00069     vsnprintf(DebugBuffer, DEBUG_BUF_SIZE, fmt, argptr);
00070 #else
00071     vsprintf(DebugBuffer, fmt, argptr);
00072 #endif
00073 #endif
00074     va_end(argptr);
00075 
00076     log_line(priority, DebugBuffer);
00077 } /* log_msg */
00078 
00079 static void log_line(const int priority, const char *DebugBuffer)
00080 {
00081 #ifndef WIN32
00082     if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
00083         syslog(LOG_INFO, "%s", DebugBuffer);
00084     else
00085     {
00086         if (LogDoColor)
00087         {
00088             const char *color_pfx = "", *color_sfx = "\33[0m";
00089             const char *time_pfx = "\33[36m", *time_sfx = color_sfx;
00090             static struct timeval last_time = { 0, 0 };
00091             struct timeval new_time = { 0, 0 };
00092             struct timeval tmp;
00093             int delta;
00094 
00095             switch (priority)
00096             {
00097                 case PCSC_LOG_CRITICAL:
00098                     color_pfx = "\33[01;31m"; /* bright + Red */
00099                     break;
00100 
00101                 case PCSC_LOG_ERROR:
00102                     color_pfx = "\33[35m"; /* Magenta */
00103                     break;
00104 
00105                 case PCSC_LOG_INFO:
00106                     color_pfx = "\33[34m"; /* Blue */
00107                     break;
00108 
00109                 case PCSC_LOG_DEBUG:
00110                     color_pfx = ""; /* normal (black) */
00111                     color_sfx = "";
00112                     break;
00113             }
00114 
00115             gettimeofday(&new_time, NULL);
00116             if (0 == last_time.tv_sec)
00117                 last_time = new_time;
00118 
00119             tmp.tv_sec = new_time.tv_sec - last_time.tv_sec;
00120             tmp.tv_usec = new_time.tv_usec - last_time.tv_usec;
00121             if (tmp.tv_usec < 0)
00122             {
00123                 tmp.tv_sec--;
00124                 tmp.tv_usec += 1000000;
00125             }
00126             if (tmp.tv_sec < 100)
00127                 delta = tmp.tv_sec * 1000000 + tmp.tv_usec;
00128             else
00129                 delta = 99999999;
00130 
00131             fprintf(stderr, "%s%.8d%s %s%s%s\n", time_pfx, delta, time_sfx,
00132                 color_pfx, DebugBuffer, color_sfx);
00133             last_time = new_time;
00134         }
00135         else
00136             fprintf(stderr, "%s\n", DebugBuffer);
00137     }
00138 #else
00139     fprintf(stderr, "%s\n", DebugBuffer);
00140 #endif
00141 } /* log_msg */
00142 
00143 void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
00144     const int len)
00145 {
00146     char DebugBuffer[DEBUG_BUF_SIZE];
00147     int i;
00148     char *c;
00149     char *debug_buf_end;
00150 
00151     if ((LogSuppress != DEBUGLOG_LOG_ENTRIES)
00152         || (priority < LogLevel) /* log priority lower than threshold? */
00153         || (DEBUGLOG_NO_DEBUG == LogMsgType))
00154         return;
00155 
00156     debug_buf_end = DebugBuffer + DEBUG_BUF_SIZE - 5;
00157 
00158     strlcpy(DebugBuffer, msg, sizeof(DebugBuffer));
00159     c = DebugBuffer + strlen(DebugBuffer);
00160 
00161     for (i = 0; (i < len) && (c < debug_buf_end); ++i)
00162     {
00163         sprintf(c, "%02X ", buffer[i]);
00164         c += 3;
00165     }
00166 
00167     /* the buffer is too small so end it with "..." */
00168     if ((c >= debug_buf_end) && (i < len))
00169         c[-3] = c[-2] = c[-1] = '.';
00170 
00171     log_line(priority, DebugBuffer);
00172 } /* log_xxd */
00173 
00174 #ifdef PCSCD
00175 void DebugLogSuppress(const int lSType)
00176 {
00177     LogSuppress = lSType;
00178 }
00179 #endif
00180 
00181 void DebugLogSetLogType(const int dbgtype)
00182 {
00183     switch (dbgtype)
00184     {
00185         case DEBUGLOG_NO_DEBUG:
00186         case DEBUGLOG_SYSLOG_DEBUG:
00187         case DEBUGLOG_STDERR_DEBUG:
00188             LogMsgType = dbgtype;
00189             break;
00190         default:
00191             Log2(PCSC_LOG_CRITICAL, "unknown log type (%d), using stderr",
00192                 dbgtype);
00193             LogMsgType = DEBUGLOG_STDERR_DEBUG;
00194     }
00195 
00196     /* no color under Windows */
00197 #ifndef WIN32
00198     /* log to stderr and stderr is a tty? */
00199     if (DEBUGLOG_STDERR_DEBUG == LogMsgType && isatty(fileno(stderr)))
00200     {
00201         const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode" };
00202         char *term;
00203 
00204         term = getenv("TERM");
00205         if (term)
00206         {
00207             unsigned int i;
00208 
00209             /* for each known color terminal */
00210             for (i = 0; i < sizeof(terms) / sizeof(terms[0]); i++)
00211             {
00212                 /* we found a supported term? */
00213                 if (0 == strcmp(terms[i], term))
00214                 {
00215                     LogDoColor = 1;
00216                     break;
00217                 }
00218             }
00219         }
00220     }
00221 #endif
00222 }
00223 
00224 void DebugLogSetLevel(const int level)
00225 {
00226     LogLevel = level;
00227     switch (level)
00228     {
00229         case PCSC_LOG_CRITICAL:
00230         case PCSC_LOG_ERROR:
00231             /* do not log anything */
00232             break;
00233 
00234         case PCSC_LOG_INFO:
00235             Log1(PCSC_LOG_INFO, "debug level=notice");
00236             break;
00237 
00238         case PCSC_LOG_DEBUG:
00239             Log1(PCSC_LOG_DEBUG, "debug level=debug");
00240             break;
00241 
00242         default:
00243             LogLevel = PCSC_LOG_INFO;
00244             Log2(PCSC_LOG_CRITICAL, "unknown level (%d), using level=notice",
00245                 level);
00246     }
00247 }
00248 
00249 INTERNAL int DebugLogSetCategory(const int dbginfo)
00250 {
00251 #define DEBUG_INFO_LENGTH 80
00252     char text[DEBUG_INFO_LENGTH];
00253 
00254     /* use a negative number to UNset
00255      * typically use ~DEBUG_CATEGORY_APDU
00256      */
00257     if (dbginfo < 0)
00258         LogCategory &= dbginfo;
00259     else
00260         LogCategory |= dbginfo;
00261 
00262     /* set to empty string */
00263     text[0] = '\0';
00264 
00265     if (LogCategory & DEBUG_CATEGORY_APDU)
00266         strlcat(text, " APDU", sizeof(text));
00267 
00268     Log2(PCSC_LOG_INFO, "Debug options:%s", text);
00269 
00270     return LogCategory;
00271 }
00272 
00273 INTERNAL void DebugLogCategory(const int category, const unsigned char *buffer,
00274     const int len)
00275 {
00276     if ((category & DEBUG_CATEGORY_APDU)
00277         && (LogCategory & DEBUG_CATEGORY_APDU))
00278         log_xxd(PCSC_LOG_INFO, "APDU: ", (const unsigned char *)buffer, len);
00279 
00280     if ((category & DEBUG_CATEGORY_SW)
00281         && (LogCategory & DEBUG_CATEGORY_APDU))
00282         log_xxd(PCSC_LOG_INFO, "SW: ", (const unsigned char *)buffer, len);
00283 }
00284 
00285 /*
00286  * old function supported for backward object code compatibility
00287  * defined only for pcscd
00288  */
00289 #ifdef PCSCD
00290 void debug_msg(const char *fmt, ...);
00291 void debug_msg(const char *fmt, ...)
00292 {
00293     char DebugBuffer[DEBUG_BUF_SIZE];
00294     va_list argptr;
00295 
00296     if ((LogSuppress != DEBUGLOG_LOG_ENTRIES)
00297         || (DEBUGLOG_NO_DEBUG == LogMsgType))
00298         return;
00299 
00300     va_start(argptr, fmt);
00301 #ifndef WIN32
00302     vsnprintf(DebugBuffer, DEBUG_BUF_SIZE, fmt, argptr);
00303 #else
00304 #if HAVE_VSNPRINTF
00305     vsnprintf(DebugBuffer, DEBUG_BUF_SIZE, fmt, argptr);
00306 #else
00307     vsprintf(DebugBuffer, fmt, argptr);
00308 #endif
00309 #endif
00310     va_end(argptr);
00311 
00312 #ifndef WIN32
00313     if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
00314         syslog(LOG_INFO, "%s", DebugBuffer);
00315     else
00316 #endif
00317         fprintf(stderr, "%s\n", DebugBuffer);
00318 } /* debug_msg */
00319 
00320 void debug_xxd(const char *msg, const unsigned char *buffer, const int len);
00321 void debug_xxd(const char *msg, const unsigned char *buffer, const int len)
00322 {
00323     log_xxd(PCSC_LOG_ERROR, msg, buffer, len);
00324 } /* debug_xxd */
00325 #endif
00326 

Generated on Mon Aug 17 01:00:08 2009 for pcsc-lite by  doxygen 1.5.9