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