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  *
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 
115 void 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 
131 static 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 
205 static 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 
226 void 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 
240 void 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 
282 void 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 
307 INTERNAL 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 
321 INTERNAL 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
338 void debug_msg(const char *fmt, ...);
339 void 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 
357 void debug_xxd(const char *msg, const unsigned char *buffer, const int len);
358 void 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.