pcsc-lite 1.5.5
|
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