pcsc-lite 1.9.5
debuglog.c
Go to the documentation of this file.
1/*
2 * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ )
3 *
4 * Copyright (C) 1999-2002
5 * David Corcoran <corcoran@musclecard.com>
6 * Copyright (C) 2002-2011
7 * Ludovic Rousseau <ludovic.rousseau@free.fr>
8 *
9Redistribution and use in source and binary forms, with or without
10modification, are permitted provided that the following conditions
11are met:
12
131. Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
152. Redistributions in binary form must reproduce the above copyright
16 notice, this list of conditions and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
183. The name of the author may not be used to endorse or promote products
19 derived from this software without specific prior written permission.
20
21THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
38#include "config.h"
39#ifdef HAVE_SYSLOG_H
40#include <syslog.h>
41#endif
42#include <unistd.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <string.h>
46#include <stdarg.h>
47#include <assert.h>
48#include <sys/types.h>
49#include <sys/time.h>
50#include <time.h>
51#include <pthread.h>
52
53#include "pcsclite.h"
54#include "misc.h"
55#include "debuglog.h"
56#include "sys_generic.h"
57
58#ifdef NO_LOG
59
60void log_msg(const int priority, const char *fmt, ...)
61{
62 (void)priority;
63 (void)fmt;
64}
65
66void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
67 const int len)
68{
69 (void)priority;
70 (void)msg;
71 (void)buffer;
72 (void)len;
73}
74
75void DebugLogSetLogType(const int dbgtype)
76{
77 (void)dbgtype;
78}
79
80void DebugLogSetLevel(const int level)
81{
82 (void)level;
83}
84
85INTERNAL void DebugLogSetCategory(const int dbginfo)
86{
87 (void)dbginfo;
88
89 return 0;
90}
91
92INTERNAL void DebugLogCategory(const int category, const unsigned char *buffer,
93 const int len)
94{
95 (void)category;
96 (void)buffer;
97 (void)len;
98}
99
100#else
101
105#define DEBUG_BUF_SIZE 2048
106
107static char LogMsgType = DEBUGLOG_NO_DEBUG;
108static char LogCategory = DEBUG_CATEGORY_NOTHING;
109
111static char LogLevel = PCSC_LOG_ERROR;
112
113static signed char LogDoColor = 0;
115static void log_line(const int priority, const char *DebugBuffer);
116
117void log_msg(const int priority, const char *fmt, ...)
118{
119 char DebugBuffer[DEBUG_BUF_SIZE];
120 va_list argptr;
121
122 if ((priority < LogLevel) /* log priority lower than threshold? */
123 || (DEBUGLOG_NO_DEBUG == LogMsgType))
124 return;
125
126 va_start(argptr, fmt);
127 vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr);
128 va_end(argptr);
129
130 log_line(priority, DebugBuffer);
131} /* log_msg */
132
133static void log_line(const int priority, const char *DebugBuffer)
134{
135 if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
136 syslog(LOG_INFO, "%s", DebugBuffer);
137 else
138 {
139 static struct timeval last_time = { 0, 0 };
140 struct timeval new_time = { 0, 0 };
141 struct timeval tmp;
142 int delta;
143 pthread_t thread_id;
144
145 gettimeofday(&new_time, NULL);
146 if (0 == last_time.tv_sec)
147 last_time = new_time;
148
149 tmp.tv_sec = new_time.tv_sec - last_time.tv_sec;
150 tmp.tv_usec = new_time.tv_usec - last_time.tv_usec;
151 if (tmp.tv_usec < 0)
152 {
153 tmp.tv_sec--;
154 tmp.tv_usec += 1000000;
155 }
156 if (tmp.tv_sec < 100)
157 delta = tmp.tv_sec * 1000000 + tmp.tv_usec;
158 else
159 delta = 99999999;
160
161 last_time = new_time;
162
163 thread_id = pthread_self();
164
165 if (LogDoColor)
166 {
167 const char *color_pfx = "", *color_sfx = "\33[0m";
168 const char *time_pfx = "\33[36m", *time_sfx = color_sfx;
169
170 switch (priority)
171 {
172 case PCSC_LOG_CRITICAL:
173 color_pfx = "\33[01;31m"; /* bright + Red */
174 break;
175
176 case PCSC_LOG_ERROR:
177 color_pfx = "\33[35m"; /* Magenta */
178 break;
179
180 case PCSC_LOG_INFO:
181 color_pfx = "\33[34m"; /* Blue */
182 break;
183
184 case PCSC_LOG_DEBUG:
185 color_pfx = ""; /* normal (black) */
186 color_sfx = "";
187 break;
188 }
189
190#ifdef __APPLE__
191#define THREAD_FORMAT "%p"
192#else
193#define THREAD_FORMAT "%lu"
194#endif
195 printf("%s%.8d%s [" THREAD_FORMAT "] %s%s%s\n",
196 time_pfx, delta, time_sfx, thread_id,
197 color_pfx, DebugBuffer, color_sfx);
198 }
199 else
200 {
201 printf("%.8d %s\n", delta, DebugBuffer);
202 }
203 fflush(stdout);
204 }
205} /* log_line */
206
207static void log_xxd_always(const int priority, const char *msg,
208 const unsigned char *buffer, const int len)
209{
210 char DebugBuffer[len*3 + strlen(msg) +1];
211 int i;
212 char *c;
213
214 /* DebugBuffer is always big enough for msg */
215 strcpy(DebugBuffer, msg);
216 c = DebugBuffer + strlen(DebugBuffer);
217
218 for (i = 0; (i < len); ++i)
219 {
220 /* 2 hex characters, 1 space, 1 NUL : total 4 characters */
221 snprintf(c, 4, "%02X ", buffer[i]);
222 c += 3;
223 }
224
225 log_line(priority, DebugBuffer);
226} /* log_xxd_always */
227
228void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
229 const int len)
230{
231 if ((priority < LogLevel) /* log priority lower than threshold? */
232 || (DEBUGLOG_NO_DEBUG == LogMsgType))
233 return;
234
235 /* len is an error value? */
236 if (len < 0)
237 return;
238
239 log_xxd_always(priority, msg, buffer, len);
240} /* log_xxd */
241
242void DebugLogSetLogType(const int dbgtype)
243{
244 switch (dbgtype)
245 {
246 case DEBUGLOG_NO_DEBUG:
247 case DEBUGLOG_SYSLOG_DEBUG:
248 case DEBUGLOG_STDOUT_DEBUG:
249 case DEBUGLOG_STDOUT_COLOR_DEBUG:
250 LogMsgType = dbgtype;
251 break;
252 default:
253 Log2(PCSC_LOG_CRITICAL, "unknown log type (%d), using stdout",
254 dbgtype);
255 LogMsgType = DEBUGLOG_STDOUT_DEBUG;
256 }
257
258 /* log to stdout and stdout is a tty? */
259 if ((DEBUGLOG_STDOUT_DEBUG == LogMsgType && isatty(fileno(stdout)))
260 || (DEBUGLOG_STDOUT_COLOR_DEBUG == LogMsgType))
261 {
262 char *term;
263
264 term = getenv("TERM");
265 if (term)
266 {
267 const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode", "xterm-256color" };
268 unsigned int i;
269
270 /* for each known color terminal */
271 for (i = 0; i < COUNT_OF(terms); i++)
272 {
273 /* we found a supported term? */
274 if (0 == strcmp(terms[i], term))
275 {
276 LogDoColor = 1;
277 break;
278 }
279 }
280 }
281 }
282}
283
284void DebugLogSetLevel(const int level)
285{
286 LogLevel = level;
287 switch (level)
288 {
289 case PCSC_LOG_CRITICAL:
290 case PCSC_LOG_ERROR:
291 /* do not log anything */
292 break;
293
294 case PCSC_LOG_INFO:
295 Log1(PCSC_LOG_INFO, "debug level=info");
296 break;
297
298 case PCSC_LOG_DEBUG:
299 Log1(PCSC_LOG_DEBUG, "debug level=debug");
300 break;
301
302 default:
303 LogLevel = PCSC_LOG_INFO;
304 Log2(PCSC_LOG_CRITICAL, "unknown level (%d), using level=info",
305 level);
306 }
307}
308
309INTERNAL void DebugLogSetCategory(const int dbginfo)
310{
311 /* use a negative number to UNset
312 * typically use ~DEBUG_CATEGORY_APDU
313 */
314 if (dbginfo < 0)
315 LogCategory &= dbginfo;
316 else
317 LogCategory |= dbginfo;
318
319 if (LogCategory & DEBUG_CATEGORY_APDU)
320 Log1(PCSC_LOG_INFO, "Debug options: APDU");
321}
322
323INTERNAL void DebugLogCategory(const int category, const unsigned char *buffer,
324 const int len)
325{
326 if ((category & DEBUG_CATEGORY_APDU)
327 && (LogCategory & DEBUG_CATEGORY_APDU))
328 log_xxd_always(PCSC_LOG_INFO, "APDU: ", buffer, len);
329
330 if ((category & DEBUG_CATEGORY_SW)
331 && (LogCategory & DEBUG_CATEGORY_APDU))
332 log_xxd_always(PCSC_LOG_INFO, "SW: ", buffer, len);
333}
334
335/*
336 * old function supported for backward object code compatibility
337 * defined only for pcscd
338 */
339#ifdef PCSCD
340void debug_msg(const char *fmt, ...);
341void debug_msg(const char *fmt, ...)
342{
343 char DebugBuffer[DEBUG_BUF_SIZE];
344 va_list argptr;
345
346 if (DEBUGLOG_NO_DEBUG == LogMsgType)
347 return;
348
349 va_start(argptr, fmt);
350 vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr);
351 va_end(argptr);
352
353 if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
354 syslog(LOG_INFO, "%s", DebugBuffer);
355 else
356 puts(DebugBuffer);
357} /* debug_msg */
358
359void debug_xxd(const char *msg, const unsigned char *buffer, const int len);
360void debug_xxd(const char *msg, const unsigned char *buffer, const int len)
361{
362 log_xxd(PCSC_LOG_ERROR, msg, buffer, len);
363} /* debug_xxd */
364#endif
365
366#endif /* NO_LOG */
367
static char LogLevel
default level
Definition: debuglog.c:111
#define DEBUG_BUF_SIZE
Max string size dumping a maxmium of 2 lines of 80 characters.
Definition: debuglog.c:105
static signed char LogDoColor
no color by default
Definition: debuglog.c:113
This handles debugging.
This keeps a list of defines for pcsc-lite.
This handles abstract system level calls.