00001
00002
00003
00004
00005
00006
00007
00008
00009
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)
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 }
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";
00099 break;
00100
00101 case PCSC_LOG_ERROR:
00102 color_pfx = "\33[35m";
00103 break;
00104
00105 case PCSC_LOG_INFO:
00106 color_pfx = "\33[34m";
00107 break;
00108
00109 case PCSC_LOG_DEBUG:
00110 color_pfx = "";
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 }
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)
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
00168 if ((c >= debug_buf_end) && (i < len))
00169 c[-3] = c[-2] = c[-1] = '.';
00170
00171 log_line(priority, DebugBuffer);
00172 }
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
00197 #ifndef WIN32
00198
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
00210 for (i = 0; i < sizeof(terms) / sizeof(terms[0]); i++)
00211 {
00212
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
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
00255
00256
00257 if (dbginfo < 0)
00258 LogCategory &= dbginfo;
00259 else
00260 LogCategory |= dbginfo;
00261
00262
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
00287
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 }
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 }
00325 #endif
00326