pcsc-lite  1.8.26
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  return 0;
90 }
91 
92 INTERNAL 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 
107 static char LogMsgType = DEBUGLOG_NO_DEBUG;
108 static char LogCategory = DEBUG_CATEGORY_NOTHING;
109 
111 static char LogLevel = PCSC_LOG_ERROR;
112 
113 static signed char LogDoColor = 0;
115 static void log_line(const int priority, const char *DebugBuffer);
116 
117 void 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 
133 static 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 
207 static 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 
228 void 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 
242 void 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 
284 void 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 
309 INTERNAL 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 
323 INTERNAL 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
340 void debug_msg(const char *fmt, ...);
341 void 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 
359 void debug_xxd(const char *msg, const unsigned char *buffer, const int len);
360 void 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 
debuglog.h
This handles debugging.
sys_generic.h
This handles abstract system level calls.
LogLevel
static char LogLevel
default level
Definition: debuglog.c:111
DEBUG_BUF_SIZE
#define DEBUG_BUF_SIZE
Max string size dumping a maxmium of 2 lines of 80 characters.
Definition: debuglog.c:105
LogDoColor
static signed char LogDoColor
no color by default
Definition: debuglog.c:113
pcsclite.h
This keeps a list of defines for pcsc-lite.