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