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