pcsc-lite  1.8.14
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  * $Id$
33  */
34 
40 #include "config.h"
41 #ifdef HAVE_SYSLOG_H
42 #include <syslog.h>
43 #endif
44 #include <unistd.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <stdarg.h>
49 #include <assert.h>
50 #include <sys/types.h>
51 #include <sys/time.h>
52 #include <time.h>
53 
54 #include "pcsclite.h"
55 #include "misc.h"
56 #include "debuglog.h"
57 #include "sys_generic.h"
58 
59 #ifdef NO_LOG
60 
61 void log_msg(const int priority, const char *fmt, ...)
62 {
63  (void)priority;
64  (void)fmt;
65 }
66 
67 void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
68  const int len)
69 {
70  (void)priority;
71  (void)msg;
72  (void)buffer;
73  (void)len;
74 }
75 
76 void DebugLogSetLogType(const int dbgtype)
77 {
78  (void)dbgtype;
79 }
80 
81 void DebugLogSetLevel(const int level)
82 {
83  (void)level;
84 }
85 
86 INTERNAL int DebugLogSetCategory(const int dbginfo)
87 {
88  (void)dbginfo;
89 
90  return 0;
91 }
92 
93 INTERNAL void DebugLogCategory(const int category, const unsigned char *buffer,
94  const int len)
95 {
96  (void)category;
97  (void)buffer;
98  (void)len;
99 }
100 
101 #else
102 
106 #define DEBUG_BUF_SIZE 2048
107 
108 static char LogMsgType = DEBUGLOG_NO_DEBUG;
109 static char LogCategory = DEBUG_CATEGORY_NOTHING;
110 
112 static char LogLevel = PCSC_LOG_ERROR;
113 
114 static signed char LogDoColor = 0;
116 static void log_line(const int priority, const char *DebugBuffer);
117 
118 void log_msg(const int priority, const char *fmt, ...)
119 {
120  char DebugBuffer[DEBUG_BUF_SIZE];
121  va_list argptr;
122 
123  if ((priority < LogLevel) /* log priority lower than threshold? */
124  || (DEBUGLOG_NO_DEBUG == LogMsgType))
125  return;
126 
127  va_start(argptr, fmt);
128  vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr);
129  va_end(argptr);
130 
131  log_line(priority, DebugBuffer);
132 } /* log_msg */
133 
134 static void log_line(const int priority, const char *DebugBuffer)
135 {
136  if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
137  syslog(LOG_INFO, "%s", DebugBuffer);
138  else
139  {
140  static struct timeval last_time = { 0, 0 };
141  struct timeval new_time = { 0, 0 };
142  struct timeval tmp;
143  int delta;
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  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  printf("%s%.8d%s %s%s%s\n", time_pfx, delta, time_sfx,
189  color_pfx, DebugBuffer, color_sfx);
190  }
191  else
192  {
193  printf("%.8d %s\n", delta, DebugBuffer);
194  }
195  fflush(stdout);
196  }
197 } /* log_msg */
198 
199 static void log_xxd_always(const int priority, const char *msg,
200  const unsigned char *buffer, const int len)
201 {
202  char DebugBuffer[len*3 + strlen(msg) +1];
203  int i;
204  char *c;
205 
206  /* DebugBuffer is always big enough for msg */
207  strcpy(DebugBuffer, msg);
208  c = DebugBuffer + strlen(DebugBuffer);
209 
210  for (i = 0; (i < len); ++i)
211  {
212  /* 2 hex characters, 1 space, 1 NUL : total 4 characters */
213  snprintf(c, 4, "%02X ", buffer[i]);
214  c += 3;
215  }
216 
217  log_line(priority, DebugBuffer);
218 } /* log_xxd_always */
219 
220 void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
221  const int len)
222 {
223  if ((priority < LogLevel) /* log priority lower than threshold? */
224  || (DEBUGLOG_NO_DEBUG == LogMsgType))
225  return;
226 
227  /* len is an error value? */
228  if (len < 0)
229  return;
230 
231  log_xxd_always(priority, msg, buffer, len);
232 } /* log_xxd */
233 
234 void DebugLogSetLogType(const int dbgtype)
235 {
236  switch (dbgtype)
237  {
238  case DEBUGLOG_NO_DEBUG:
239  case DEBUGLOG_SYSLOG_DEBUG:
240  case DEBUGLOG_STDOUT_DEBUG:
241  case DEBUGLOG_STDOUT_COLOR_DEBUG:
242  LogMsgType = dbgtype;
243  break;
244  default:
245  Log2(PCSC_LOG_CRITICAL, "unknown log type (%d), using stdout",
246  dbgtype);
247  LogMsgType = DEBUGLOG_STDOUT_DEBUG;
248  }
249 
250  /* log to stdout and stdout is a tty? */
251  if ((DEBUGLOG_STDOUT_DEBUG == LogMsgType && isatty(fileno(stdout)))
252  || (DEBUGLOG_STDOUT_COLOR_DEBUG == LogMsgType))
253  {
254  char *term;
255 
256  term = getenv("TERM");
257  if (term)
258  {
259  const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode", "xterm-256color" };
260  unsigned int i;
261 
262  /* for each known color terminal */
263  for (i = 0; i < COUNT_OF(terms); i++)
264  {
265  /* we found a supported term? */
266  if (0 == strcmp(terms[i], term))
267  {
268  LogDoColor = 1;
269  break;
270  }
271  }
272  }
273  }
274 }
275 
276 void DebugLogSetLevel(const int level)
277 {
278  LogLevel = level;
279  switch (level)
280  {
281  case PCSC_LOG_CRITICAL:
282  case PCSC_LOG_ERROR:
283  /* do not log anything */
284  break;
285 
286  case PCSC_LOG_INFO:
287  Log1(PCSC_LOG_INFO, "debug level=notice");
288  break;
289 
290  case PCSC_LOG_DEBUG:
291  Log1(PCSC_LOG_DEBUG, "debug level=debug");
292  break;
293 
294  default:
295  LogLevel = PCSC_LOG_INFO;
296  Log2(PCSC_LOG_CRITICAL, "unknown level (%d), using level=notice",
297  level);
298  }
299 }
300 
301 INTERNAL int DebugLogSetCategory(const int dbginfo)
302 {
303  /* use a negative number to UNset
304  * typically use ~DEBUG_CATEGORY_APDU
305  */
306  if (dbginfo < 0)
307  LogCategory &= dbginfo;
308  else
309  LogCategory |= dbginfo;
310 
311  if (LogCategory & DEBUG_CATEGORY_APDU)
312  Log1(PCSC_LOG_INFO, "Debug options: APDU");
313 
314  return LogCategory;
315 }
316 
317 INTERNAL void DebugLogCategory(const int category, const unsigned char *buffer,
318  const int len)
319 {
320  if ((category & DEBUG_CATEGORY_APDU)
321  && (LogCategory & DEBUG_CATEGORY_APDU))
322  log_xxd_always(PCSC_LOG_INFO, "APDU: ", buffer, len);
323 
324  if ((category & DEBUG_CATEGORY_SW)
325  && (LogCategory & DEBUG_CATEGORY_APDU))
326  log_xxd_always(PCSC_LOG_INFO, "SW: ", buffer, len);
327 }
328 
329 /*
330  * old function supported for backward object code compatibility
331  * defined only for pcscd
332  */
333 #ifdef PCSCD
334 void debug_msg(const char *fmt, ...);
335 void debug_msg(const char *fmt, ...)
336 {
337  char DebugBuffer[DEBUG_BUF_SIZE];
338  va_list argptr;
339 
340  if (DEBUGLOG_NO_DEBUG == LogMsgType)
341  return;
342 
343  va_start(argptr, fmt);
344  vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr);
345  va_end(argptr);
346 
347  if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
348  syslog(LOG_INFO, "%s", DebugBuffer);
349  else
350  puts(DebugBuffer);
351 } /* debug_msg */
352 
353 void debug_xxd(const char *msg, const unsigned char *buffer, const int len);
354 void debug_xxd(const char *msg, const unsigned char *buffer, const int len)
355 {
356  log_xxd(PCSC_LOG_ERROR, msg, buffer, len);
357 } /* debug_xxd */
358 #endif
359 
360 #endif /* NO_LOG */
361 
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:106
static char LogLevel
default level
Definition: debuglog.c:112
This keeps a list of defines for pcsc-lite.
This handles debugging.
static signed char LogDoColor
no color by default
Definition: debuglog.c:114