pcsc-lite  1.9.9
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  *
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 #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 
60 void log_msg(const int priority, const char *fmt, ...)
61 {
62  (void)priority;
63  (void)fmt;
64 }
65 
66 void 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 
75 void DebugLogSetLogType(const int dbgtype)
76 {
77  (void)dbgtype;
78 }
79 
80 void DebugLogSetLevel(const int level)
81 {
82  (void)level;
83 }
84 
85 INTERNAL void DebugLogSetCategory(const int dbginfo)
86 {
87  (void)dbginfo;
88 }
89 
90 INTERNAL 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 
105 static char LogMsgType = DEBUGLOG_NO_DEBUG;
106 static char LogCategory = DEBUG_CATEGORY_NOTHING;
107 
109 static char LogLevel = PCSC_LOG_ERROR;
110 
111 static signed char LogDoColor = 0;
113 static void log_line(const int priority, const char *DebugBuffer,
114  unsigned int rv);
115 
116 /*
117  * log a message with the RV value returned by the daemon
118  */
119 void log_msg_rv(const int priority, unsigned int rv, const char *fmt, ...)
120 {
121  char DebugBuffer[DEBUG_BUF_SIZE];
122  va_list argptr;
123 
124  if ((priority < LogLevel) /* log priority lower than threshold? */
125  || (DEBUGLOG_NO_DEBUG == LogMsgType))
126  return;
127 
128  va_start(argptr, fmt);
129  vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr);
130  va_end(argptr);
131 
132  log_line(priority, DebugBuffer, rv);
133 }
134 
135 void log_msg(const int priority, const char *fmt, ...)
136 {
137  char DebugBuffer[DEBUG_BUF_SIZE];
138  va_list argptr;
139 
140  if ((priority < LogLevel) /* log priority lower than threshold? */
141  || (DEBUGLOG_NO_DEBUG == LogMsgType))
142  return;
143 
144  va_start(argptr, fmt);
145  vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr);
146  va_end(argptr);
147 
148  log_line(priority, DebugBuffer, -1);
149 } /* log_msg */
150 
151 /* convert from integer rv value to a string value
152  * SCARD_S_SUCCESS -> "SCARD_S_SUCCESS"
153  */
154 const char * rv2text(unsigned int rv)
155 {
156  const char *rv_text = NULL;
157  static __thread char strError[30];
158 
159 #define CASE(x) \
160  case x: \
161  rv_text = "rv=" #x; \
162  break
163 
164  if (rv != (unsigned int)-1)
165  {
166  switch (rv)
167  {
168  CASE(SCARD_S_SUCCESS);
169  CASE(SCARD_E_CANCELLED);
173  CASE(SCARD_E_INVALID_VALUE);
174  CASE(SCARD_E_NO_MEMORY);
175  CASE(SCARD_E_NO_SERVICE);
176  CASE(SCARD_E_NO_SMARTCARD);
181  CASE(SCARD_E_TIMEOUT);
184  CASE(SCARD_F_COMM_ERROR);
186  CASE(SCARD_W_REMOVED_CARD);
187  CASE(SCARD_W_RESET_CARD);
191 
192  default:
193  (void)snprintf(strError, sizeof(strError)-1,
194  "Unknown error: 0x%08X", rv);
195  rv_text = strError;
196  }
197  }
198 
199  return rv_text;
200 }
201 
202 static void log_line(const int priority, const char *DebugBuffer,
203  unsigned int rv)
204 {
205  if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
206  syslog(LOG_INFO, "%s", DebugBuffer);
207  else
208  {
209  static struct timeval last_time = { 0, 0 };
210  struct timeval new_time = { 0, 0 };
211  struct timeval tmp;
212  int delta;
213  pthread_t thread_id;
214  const char *rv_text = NULL;
215 
216  gettimeofday(&new_time, NULL);
217  if (0 == last_time.tv_sec)
218  last_time = new_time;
219 
220  tmp.tv_sec = new_time.tv_sec - last_time.tv_sec;
221  tmp.tv_usec = new_time.tv_usec - last_time.tv_usec;
222  if (tmp.tv_usec < 0)
223  {
224  tmp.tv_sec--;
225  tmp.tv_usec += 1000000;
226  }
227  if (tmp.tv_sec < 100)
228  delta = tmp.tv_sec * 1000000 + tmp.tv_usec;
229  else
230  delta = 99999999;
231 
232  last_time = new_time;
233 
234  thread_id = pthread_self();
235 
236  rv_text = rv2text(rv);
237 
238  if (LogDoColor)
239  {
240  const char *color_pfx = "", *color_sfx = "\33[0m";
241  const char *time_pfx = "\33[36m", *time_sfx = color_sfx;
242 
243  switch (priority)
244  {
245  case PCSC_LOG_CRITICAL:
246  color_pfx = "\33[01;31m"; /* bright + Red */
247  break;
248 
249  case PCSC_LOG_ERROR:
250  color_pfx = "\33[35m"; /* Magenta */
251  break;
252 
253  case PCSC_LOG_INFO:
254  color_pfx = "\33[34m"; /* Blue */
255  break;
256 
257  case PCSC_LOG_DEBUG:
258  color_pfx = ""; /* normal (black) */
259  color_sfx = "";
260  break;
261  }
262 
263 #ifdef __APPLE__
264 #define THREAD_FORMAT "%p"
265 #else
266 #define THREAD_FORMAT "%lu"
267 #endif
268  if (rv_text)
269  {
270  const char * rv_pfx = "", * rv_sfx = "";
271  if (rv != SCARD_S_SUCCESS)
272  {
273  rv_pfx = "\33[31m"; /* Red */
274  rv_sfx = "\33[0m";
275  }
276 
277  printf("%s%.8d%s [" THREAD_FORMAT "] %s%s%s, %s%s%s\n",
278  time_pfx, delta, time_sfx, thread_id,
279  color_pfx, DebugBuffer, color_sfx,
280  rv_pfx, rv_text, rv_sfx);
281  }
282  else
283  printf("%s%.8d%s [" THREAD_FORMAT "] %s%s%s\n",
284  time_pfx, delta, time_sfx, thread_id,
285  color_pfx, DebugBuffer, color_sfx);
286  }
287  else
288  {
289  if (rv_text)
290  printf("%.8d %s, %s\n", delta, DebugBuffer, rv_text);
291  else
292  printf("%.8d %s\n", delta, DebugBuffer);
293  }
294  fflush(stdout);
295  }
296 } /* log_line */
297 
298 static void log_xxd_always(const int priority, const char *msg,
299  const unsigned char *buffer, const int len)
300 {
301  char DebugBuffer[len*3 + strlen(msg) +1];
302  int i;
303  char *c;
304 
305  /* DebugBuffer is always big enough for msg */
306  strcpy(DebugBuffer, msg);
307  c = DebugBuffer + strlen(DebugBuffer);
308 
309  for (i = 0; (i < len); ++i)
310  {
311  /* 2 hex characters, 1 space, 1 NUL : total 4 characters */
312  snprintf(c, 4, "%02X ", buffer[i]);
313  c += 3;
314  }
315 
316  log_line(priority, DebugBuffer, -1);
317 } /* log_xxd_always */
318 
319 void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
320  const int len)
321 {
322  if ((priority < LogLevel) /* log priority lower than threshold? */
323  || (DEBUGLOG_NO_DEBUG == LogMsgType))
324  return;
325 
326  /* len is an error value? */
327  if (len < 0)
328  return;
329 
330  log_xxd_always(priority, msg, buffer, len);
331 } /* log_xxd */
332 
333 void DebugLogSetLogType(const int dbgtype)
334 {
335  switch (dbgtype)
336  {
337  case DEBUGLOG_NO_DEBUG:
338  case DEBUGLOG_SYSLOG_DEBUG:
339  case DEBUGLOG_STDOUT_DEBUG:
340  case DEBUGLOG_STDOUT_COLOR_DEBUG:
341  LogMsgType = dbgtype;
342  break;
343  default:
344  Log2(PCSC_LOG_CRITICAL, "unknown log type (%d), using stdout",
345  dbgtype);
346  LogMsgType = DEBUGLOG_STDOUT_DEBUG;
347  }
348 
349  /* log to stdout and stdout is a tty? */
350  if ((DEBUGLOG_STDOUT_DEBUG == LogMsgType && isatty(fileno(stdout)))
351  || (DEBUGLOG_STDOUT_COLOR_DEBUG == LogMsgType))
352  {
353  char *term;
354 
355  term = getenv("TERM");
356  if (term)
357  {
358  const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode", "xterm-256color" };
359  unsigned int i;
360 
361  /* for each known color terminal */
362  for (i = 0; i < COUNT_OF(terms); i++)
363  {
364  /* we found a supported term? */
365  if (0 == strcmp(terms[i], term))
366  {
367  LogDoColor = 1;
368  break;
369  }
370  }
371  }
372  }
373 }
374 
375 void DebugLogSetLevel(const int level)
376 {
377  LogLevel = level;
378  switch (level)
379  {
380  case PCSC_LOG_CRITICAL:
381  case PCSC_LOG_ERROR:
382  /* do not log anything */
383  break;
384 
385  case PCSC_LOG_INFO:
386  Log1(PCSC_LOG_INFO, "debug level=info");
387  break;
388 
389  case PCSC_LOG_DEBUG:
390  Log1(PCSC_LOG_DEBUG, "debug level=debug");
391  break;
392 
393  default:
394  LogLevel = PCSC_LOG_INFO;
395  Log2(PCSC_LOG_CRITICAL, "unknown level (%d), using level=info",
396  level);
397  }
398 }
399 
400 INTERNAL void DebugLogSetCategory(const int dbginfo)
401 {
402  /* use a negative number to UNset
403  * typically use ~DEBUG_CATEGORY_APDU
404  */
405  if (dbginfo < 0)
406  LogCategory &= dbginfo;
407  else
408  LogCategory |= dbginfo;
409 
410  if (LogCategory & DEBUG_CATEGORY_APDU)
411  Log1(PCSC_LOG_INFO, "Debug options: APDU");
412 }
413 
414 INTERNAL void DebugLogCategory(const int category, const unsigned char *buffer,
415  const int len)
416 {
417  if ((category & DEBUG_CATEGORY_APDU)
418  && (LogCategory & DEBUG_CATEGORY_APDU))
419  log_xxd_always(PCSC_LOG_INFO, "APDU: ", buffer, len);
420 
421  if ((category & DEBUG_CATEGORY_SW)
422  && (LogCategory & DEBUG_CATEGORY_APDU))
423  log_xxd_always(PCSC_LOG_INFO, "SW: ", buffer, len);
424 }
425 
426 /*
427  * old function supported for backward object code compatibility
428  * defined only for pcscd
429  */
430 #ifdef PCSCD
431 void debug_msg(const char *fmt, ...);
432 void debug_msg(const char *fmt, ...)
433 {
434  char DebugBuffer[DEBUG_BUF_SIZE];
435  va_list argptr;
436 
437  if (DEBUGLOG_NO_DEBUG == LogMsgType)
438  return;
439 
440  va_start(argptr, fmt);
441  vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr);
442  va_end(argptr);
443 
444  if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
445  syslog(LOG_INFO, "%s", DebugBuffer);
446  else
447  puts(DebugBuffer);
448 } /* debug_msg */
449 
450 void debug_xxd(const char *msg, const unsigned char *buffer, const int len);
451 void debug_xxd(const char *msg, const unsigned char *buffer, const int len)
452 {
453  log_xxd(PCSC_LOG_ERROR, msg, buffer, len);
454 } /* debug_xxd */
455 #endif
456 
457 #endif /* NO_LOG */
458 
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.
#define SCARD_E_INVALID_HANDLE
The supplied handle was invalid.
Definition: pcsclite.h:113
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.
Definition: pcsclite.h:109
#define SCARD_E_UNKNOWN_READER
The specified reader name is not recognized.
Definition: pcsclite.h:125
#define SCARD_W_RESET_CARD
The smart card has been reset, so any shared state information is invalid.
Definition: pcsclite.h:216
#define SCARD_W_UNRESPONSIVE_CARD
The smart card is not responding to a reset.
Definition: pcsclite.h:212
#define SCARD_E_PROTO_MISMATCH
The requested protocols are incompatible with the protocol currently in use with the smart card.
Definition: pcsclite.h:137
#define SCARD_E_INVALID_PARAMETER
One or more of the supplied parameters could not be properly interpreted.
Definition: pcsclite.h:115
#define SCARD_E_CANCELLED
The action was cancelled by an SCardCancel request.
Definition: pcsclite.h:111
#define SCARD_S_SUCCESS
No error was encountered.
Definition: pcsclite.h:107
#define SCARD_E_NO_MEMORY
Not enough memory available to complete this command.
Definition: pcsclite.h:119
#define SCARD_E_NO_READERS_AVAILABLE
Cannot find a smart card reader.
Definition: pcsclite.h:201
#define SCARD_E_SHARING_VIOLATION
The smart card cannot be accessed because of other connections outstanding.
Definition: pcsclite.h:129
#define SCARD_F_COMM_ERROR
An internal communications error has been detected.
Definition: pcsclite.h:145
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
Definition: pcsclite.h:141
#define SCARD_E_TIMEOUT
The user-specified timeout value has expired.
Definition: pcsclite.h:127
#define SCARD_W_REMOVED_CARD
The smart card has been removed, so further communication is not possible.
Definition: pcsclite.h:218
#define SCARD_E_INSUFFICIENT_BUFFER
The data buffer to receive returned data is too small for the returned data.
Definition: pcsclite.h:123
#define SCARD_E_NO_SMARTCARD
The operation requires a Smart Card, but no Smart Card is currently in the device.
Definition: pcsclite.h:131
#define SCARD_E_NOT_TRANSACTED
An attempt was made to end a non-existent transaction.
Definition: pcsclite.h:151
#define SCARD_E_NO_SERVICE
The Smart card resource manager is not running.
Definition: pcsclite.h:165
#define SCARD_E_READER_UNAVAILABLE
The specified reader is not currently available for use.
Definition: pcsclite.h:153
#define SCARD_W_UNPOWERED_CARD
Power has been removed from the smart card, so that further communication is not possible.
Definition: pcsclite.h:214
#define SCARD_E_UNSUPPORTED_FEATURE
This smart card does not support the requested feature.
Definition: pcsclite.h:171
This keeps a list of defines for pcsc-lite.
This handles abstract system level calls.