pcsc-lite 1.9.8
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
90INTERNAL void DebugLogCategory(const int category, const unsigned char *buffer,
91 const int len)
92{
93 (void)category;
94 (void)buffer;
95 (void)len;
96}
97
98#else
99
103#define DEBUG_BUF_SIZE 2048
104
105static char LogMsgType = DEBUGLOG_NO_DEBUG;
106static char LogCategory = DEBUG_CATEGORY_NOTHING;
107
109static char LogLevel = PCSC_LOG_ERROR;
110
111static signed char LogDoColor = 0;
113static void log_line(const int priority, const char *DebugBuffer);
114
115void log_msg(const int priority, const char *fmt, ...)
116{
117 char DebugBuffer[DEBUG_BUF_SIZE];
118 va_list argptr;
119
120 if ((priority < LogLevel) /* log priority lower than threshold? */
121 || (DEBUGLOG_NO_DEBUG == LogMsgType))
122 return;
123
124 va_start(argptr, fmt);
125 vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr);
126 va_end(argptr);
127
128 log_line(priority, DebugBuffer);
129} /* log_msg */
130
131static void log_line(const int priority, const char *DebugBuffer)
132{
133 if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
134 syslog(LOG_INFO, "%s", DebugBuffer);
135 else
136 {
137 static struct timeval last_time = { 0, 0 };
138 struct timeval new_time = { 0, 0 };
139 struct timeval tmp;
140 int delta;
141 pthread_t thread_id;
142
143 gettimeofday(&new_time, NULL);
144 if (0 == last_time.tv_sec)
145 last_time = new_time;
146
147 tmp.tv_sec = new_time.tv_sec - last_time.tv_sec;
148 tmp.tv_usec = new_time.tv_usec - last_time.tv_usec;
149 if (tmp.tv_usec < 0)
150 {
151 tmp.tv_sec--;
152 tmp.tv_usec += 1000000;
153 }
154 if (tmp.tv_sec < 100)
155 delta = tmp.tv_sec * 1000000 + tmp.tv_usec;
156 else
157 delta = 99999999;
158
159 last_time = new_time;
160
161 thread_id = pthread_self();
162
163 if (LogDoColor)
164 {
165 const char *color_pfx = "", *color_sfx = "\33[0m";
166 const char *time_pfx = "\33[36m", *time_sfx = color_sfx;
167
168 switch (priority)
169 {
170 case PCSC_LOG_CRITICAL:
171 color_pfx = "\33[01;31m"; /* bright + Red */
172 break;
173
174 case PCSC_LOG_ERROR:
175 color_pfx = "\33[35m"; /* Magenta */
176 break;
177
178 case PCSC_LOG_INFO:
179 color_pfx = "\33[34m"; /* Blue */
180 break;
181
182 case PCSC_LOG_DEBUG:
183 color_pfx = ""; /* normal (black) */
184 color_sfx = "";
185 break;
186 }
187
188#ifdef __APPLE__
189#define THREAD_FORMAT "%p"
190#else
191#define THREAD_FORMAT "%lu"
192#endif
193 printf("%s%.8d%s [" THREAD_FORMAT "] %s%s%s\n",
194 time_pfx, delta, time_sfx, thread_id,
195 color_pfx, DebugBuffer, color_sfx);
196 }
197 else
198 {
199 printf("%.8d %s\n", delta, DebugBuffer);
200 }
201 fflush(stdout);
202 }
203} /* log_line */
204
205static void log_xxd_always(const int priority, const char *msg,
206 const unsigned char *buffer, const int len)
207{
208 char DebugBuffer[len*3 + strlen(msg) +1];
209 int i;
210 char *c;
211
212 /* DebugBuffer is always big enough for msg */
213 strcpy(DebugBuffer, msg);
214 c = DebugBuffer + strlen(DebugBuffer);
215
216 for (i = 0; (i < len); ++i)
217 {
218 /* 2 hex characters, 1 space, 1 NUL : total 4 characters */
219 snprintf(c, 4, "%02X ", buffer[i]);
220 c += 3;
221 }
222
223 log_line(priority, DebugBuffer);
224} /* log_xxd_always */
225
226void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
227 const int len)
228{
229 if ((priority < LogLevel) /* log priority lower than threshold? */
230 || (DEBUGLOG_NO_DEBUG == LogMsgType))
231 return;
232
233 /* len is an error value? */
234 if (len < 0)
235 return;
236
237 log_xxd_always(priority, msg, buffer, len);
238} /* log_xxd */
239
240void DebugLogSetLogType(const int dbgtype)
241{
242 switch (dbgtype)
243 {
244 case DEBUGLOG_NO_DEBUG:
245 case DEBUGLOG_SYSLOG_DEBUG:
246 case DEBUGLOG_STDOUT_DEBUG:
247 case DEBUGLOG_STDOUT_COLOR_DEBUG:
248 LogMsgType = dbgtype;
249 break;
250 default:
251 Log2(PCSC_LOG_CRITICAL, "unknown log type (%d), using stdout",
252 dbgtype);
253 LogMsgType = DEBUGLOG_STDOUT_DEBUG;
254 }
255
256 /* log to stdout and stdout is a tty? */
257 if ((DEBUGLOG_STDOUT_DEBUG == LogMsgType && isatty(fileno(stdout)))
258 || (DEBUGLOG_STDOUT_COLOR_DEBUG == LogMsgType))
259 {
260 char *term;
261
262 term = getenv("TERM");
263 if (term)
264 {
265 const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode", "xterm-256color" };
266 unsigned int i;
267
268 /* for each known color terminal */
269 for (i = 0; i < COUNT_OF(terms); i++)
270 {
271 /* we found a supported term? */
272 if (0 == strcmp(terms[i], term))
273 {
274 LogDoColor = 1;
275 break;
276 }
277 }
278 }
279 }
280}
281
282void DebugLogSetLevel(const int level)
283{
284 LogLevel = level;
285 switch (level)
286 {
287 case PCSC_LOG_CRITICAL:
288 case PCSC_LOG_ERROR:
289 /* do not log anything */
290 break;
291
292 case PCSC_LOG_INFO:
293 Log1(PCSC_LOG_INFO, "debug level=info");
294 break;
295
296 case PCSC_LOG_DEBUG:
297 Log1(PCSC_LOG_DEBUG, "debug level=debug");
298 break;
299
300 default:
301 LogLevel = PCSC_LOG_INFO;
302 Log2(PCSC_LOG_CRITICAL, "unknown level (%d), using level=info",
303 level);
304 }
305}
306
307INTERNAL void DebugLogSetCategory(const int dbginfo)
308{
309 /* use a negative number to UNset
310 * typically use ~DEBUG_CATEGORY_APDU
311 */
312 if (dbginfo < 0)
313 LogCategory &= dbginfo;
314 else
315 LogCategory |= dbginfo;
316
317 if (LogCategory & DEBUG_CATEGORY_APDU)
318 Log1(PCSC_LOG_INFO, "Debug options: APDU");
319}
320
321INTERNAL void DebugLogCategory(const int category, const unsigned char *buffer,
322 const int len)
323{
324 if ((category & DEBUG_CATEGORY_APDU)
325 && (LogCategory & DEBUG_CATEGORY_APDU))
326 log_xxd_always(PCSC_LOG_INFO, "APDU: ", buffer, len);
327
328 if ((category & DEBUG_CATEGORY_SW)
329 && (LogCategory & DEBUG_CATEGORY_APDU))
330 log_xxd_always(PCSC_LOG_INFO, "SW: ", buffer, len);
331}
332
333/*
334 * old function supported for backward object code compatibility
335 * defined only for pcscd
336 */
337#ifdef PCSCD
338void debug_msg(const char *fmt, ...);
339void debug_msg(const char *fmt, ...)
340{
341 char DebugBuffer[DEBUG_BUF_SIZE];
342 va_list argptr;
343
344 if (DEBUGLOG_NO_DEBUG == LogMsgType)
345 return;
346
347 va_start(argptr, fmt);
348 vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr);
349 va_end(argptr);
350
351 if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
352 syslog(LOG_INFO, "%s", DebugBuffer);
353 else
354 puts(DebugBuffer);
355} /* debug_msg */
356
357void debug_xxd(const char *msg, const unsigned char *buffer, const int len);
358void debug_xxd(const char *msg, const unsigned char *buffer, const int len)
359{
360 log_xxd(PCSC_LOG_ERROR, msg, buffer, len);
361} /* debug_xxd */
362#endif
363
364#endif /* NO_LOG */
365
static char LogLevel
default level
Definition: debuglog.c:109
#define DEBUG_BUF_SIZE
Max string size dumping a maxmium of 2 lines of 80 characters.
Definition: debuglog.c:103
static signed char LogDoColor
no color by default
Definition: debuglog.c:111
This handles debugging.
This keeps a list of defines for pcsc-lite.
This handles abstract system level calls.