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