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_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)
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 }
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";
00090 break;
00091
00092 case PCSC_LOG_ERROR:
00093 color_pfx = "\33[35m";
00094 break;
00095
00096 case PCSC_LOG_INFO:
00097 color_pfx = "\33[34m";
00098 break;
00099
00100 case PCSC_LOG_DEBUG:
00101 color_pfx = "";
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 }
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
00151 if ((c >= debug_buf_end) && (i < len))
00152 c[-3] = c[-2] = c[-1] = '.';
00153
00154 log_line(priority, DebugBuffer);
00155 }
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)
00162 || (DEBUGLOG_NO_DEBUG == LogMsgType))
00163 return;
00164
00165 log_xxd_always(priority, msg, buffer, len);
00166 }
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
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
00202 for (i = 0; i < sizeof(terms) / sizeof(terms[0]); i++)
00203 {
00204
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
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
00246
00247
00248 if (dbginfo < 0)
00249 LogCategory &= dbginfo;
00250 else
00251 LogCategory |= dbginfo;
00252
00253
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
00278
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 }
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 }
00306 #endif
00307