pcsc-lite  1.8.13
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: debuglog.c 7004 2014-10-02 09:26:36Z rousseau $
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 #include "strlcpycat.h"
59 
60 #ifdef NO_LOG
61 
62 void log_msg(const int priority, const char *fmt, ...)
63 {
64  (void)priority;
65  (void)fmt;
66 }
67 
68 void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
69  const int len)
70 {
71  (void)priority;
72  (void)msg;
73  (void)buffer;
74  (void)len;
75 }
76 
77 void DebugLogSetLogType(const int dbgtype)
78 {
79  (void)dbgtype;
80 }
81 
82 void DebugLogSetLevel(const int level)
83 {
84  (void)level;
85 }
86 
87 INTERNAL int DebugLogSetCategory(const int dbginfo)
88 {
89  (void)dbginfo;
90 
91  return 0;
92 }
93 
94 INTERNAL void DebugLogCategory(const int category, const unsigned char *buffer,
95  const int len)
96 {
97  (void)category;
98  (void)buffer;
99  (void)len;
100 }
101 
102 #else
103 
107 #define DEBUG_BUF_SIZE 2048
108 
109 static char LogMsgType = DEBUGLOG_NO_DEBUG;
110 static char LogCategory = DEBUG_CATEGORY_NOTHING;
111 
113 static char LogLevel = PCSC_LOG_ERROR;
114 
115 static signed char LogDoColor = 0;
117 static void log_line(const int priority, const char *DebugBuffer);
118 
119 void log_msg(const int priority, 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);
133 } /* log_msg */
134 
135 static void log_line(const int priority, const char *DebugBuffer)
136 {
137  if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
138  syslog(LOG_INFO, "%s", DebugBuffer);
139  else
140  {
141  static struct timeval last_time = { 0, 0 };
142  struct timeval new_time = { 0, 0 };
143  struct timeval tmp;
144  int delta;
145 
146  gettimeofday(&new_time, NULL);
147  if (0 == last_time.tv_sec)
148  last_time = new_time;
149 
150  tmp.tv_sec = new_time.tv_sec - last_time.tv_sec;
151  tmp.tv_usec = new_time.tv_usec - last_time.tv_usec;
152  if (tmp.tv_usec < 0)
153  {
154  tmp.tv_sec--;
155  tmp.tv_usec += 1000000;
156  }
157  if (tmp.tv_sec < 100)
158  delta = tmp.tv_sec * 1000000 + tmp.tv_usec;
159  else
160  delta = 99999999;
161 
162  last_time = new_time;
163 
164  if (LogDoColor)
165  {
166  const char *color_pfx = "", *color_sfx = "\33[0m";
167  const char *time_pfx = "\33[36m", *time_sfx = color_sfx;
168 
169  switch (priority)
170  {
171  case PCSC_LOG_CRITICAL:
172  color_pfx = "\33[01;31m"; /* bright + Red */
173  break;
174 
175  case PCSC_LOG_ERROR:
176  color_pfx = "\33[35m"; /* Magenta */
177  break;
178 
179  case PCSC_LOG_INFO:
180  color_pfx = "\33[34m"; /* Blue */
181  break;
182 
183  case PCSC_LOG_DEBUG:
184  color_pfx = ""; /* normal (black) */
185  color_sfx = "";
186  break;
187  }
188 
189  printf("%s%.8d%s %s%s%s\n", time_pfx, delta, time_sfx,
190  color_pfx, DebugBuffer, color_sfx);
191  }
192  else
193  {
194  printf("%.8d %s\n", delta, DebugBuffer);
195  }
196  fflush(stdout);
197  }
198 } /* log_msg */
199 
200 static void log_xxd_always(const int priority, const char *msg,
201  const unsigned char *buffer, const int len)
202 {
203  char DebugBuffer[len*3 + strlen(msg) +1];
204  int i;
205  char *c;
206  size_t l;
207 
208  l = strlcpy(DebugBuffer, msg, sizeof(DebugBuffer));
209  c = DebugBuffer + l;
210 
211  for (i = 0; (i < len); ++i)
212  {
213  /* 2 hex characters, 1 space, 1 NUL : total 4 characters */
214  snprintf(c, 4, "%02X ", buffer[i]);
215  c += 3;
216  }
217 
218  log_line(priority, DebugBuffer);
219 } /* log_xxd_always */
220 
221 void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
222  const int len)
223 {
224  if ((priority < LogLevel) /* log priority lower than threshold? */
225  || (DEBUGLOG_NO_DEBUG == LogMsgType))
226  return;
227 
228  /* len is an error value? */
229  if (len < 0)
230  return;
231 
232  log_xxd_always(priority, msg, buffer, len);
233 } /* log_xxd */
234 
235 void DebugLogSetLogType(const int dbgtype)
236 {
237  switch (dbgtype)
238  {
239  case DEBUGLOG_NO_DEBUG:
240  case DEBUGLOG_SYSLOG_DEBUG:
241  case DEBUGLOG_STDOUT_DEBUG:
242  case DEBUGLOG_STDOUT_COLOR_DEBUG:
243  LogMsgType = dbgtype;
244  break;
245  default:
246  Log2(PCSC_LOG_CRITICAL, "unknown log type (%d), using stdout",
247  dbgtype);
248  LogMsgType = DEBUGLOG_STDOUT_DEBUG;
249  }
250 
251  /* log to stdout and stdout is a tty? */
252  if ((DEBUGLOG_STDOUT_DEBUG == LogMsgType && isatty(fileno(stdout)))
253  || (DEBUGLOG_STDOUT_COLOR_DEBUG == LogMsgType))
254  {
255  char *term;
256 
257  term = getenv("TERM");
258  if (term)
259  {
260  const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode", "xterm-256color" };
261  unsigned int i;
262 
263  /* for each known color terminal */
264  for (i = 0; i < COUNT_OF(terms); i++)
265  {
266  /* we found a supported term? */
267  if (0 == strcmp(terms[i], term))
268  {
269  LogDoColor = 1;
270  break;
271  }
272  }
273  }
274  }
275 }
276 
277 void DebugLogSetLevel(const int level)
278 {
279  LogLevel = level;
280  switch (level)
281  {
282  case PCSC_LOG_CRITICAL:
283  case PCSC_LOG_ERROR:
284  /* do not log anything */
285  break;
286 
287  case PCSC_LOG_INFO:
288  Log1(PCSC_LOG_INFO, "debug level=notice");
289  break;
290 
291  case PCSC_LOG_DEBUG:
292  Log1(PCSC_LOG_DEBUG, "debug level=debug");
293  break;
294 
295  default:
296  LogLevel = PCSC_LOG_INFO;
297  Log2(PCSC_LOG_CRITICAL, "unknown level (%d), using level=notice",
298  level);
299  }
300 }
301 
302 INTERNAL int DebugLogSetCategory(const int dbginfo)
303 {
304 #define DEBUG_INFO_LENGTH 80
305  char text[DEBUG_INFO_LENGTH];
306 
307  /* use a negative number to UNset
308  * typically use ~DEBUG_CATEGORY_APDU
309  */
310  if (dbginfo < 0)
311  LogCategory &= dbginfo;
312  else
313  LogCategory |= dbginfo;
314 
315  /* set to empty string */
316  text[0] = '\0';
317 
318  if (LogCategory & DEBUG_CATEGORY_APDU)
319  strlcat(text, " APDU", sizeof(text));
320 
321  Log2(PCSC_LOG_INFO, "Debug options:%s", text);
322 
323  return LogCategory;
324 }
325 
326 INTERNAL void DebugLogCategory(const int category, const unsigned char *buffer,
327  const int len)
328 {
329  if ((category & DEBUG_CATEGORY_APDU)
330  && (LogCategory & DEBUG_CATEGORY_APDU))
331  log_xxd_always(PCSC_LOG_INFO, "APDU: ", buffer, len);
332 
333  if ((category & DEBUG_CATEGORY_SW)
334  && (LogCategory & DEBUG_CATEGORY_APDU))
335  log_xxd_always(PCSC_LOG_INFO, "SW: ", buffer, len);
336 }
337 
338 /*
339  * old function supported for backward object code compatibility
340  * defined only for pcscd
341  */
342 #ifdef PCSCD
343 void debug_msg(const char *fmt, ...);
344 void debug_msg(const char *fmt, ...)
345 {
346  char DebugBuffer[DEBUG_BUF_SIZE];
347  va_list argptr;
348 
349  if (DEBUGLOG_NO_DEBUG == LogMsgType)
350  return;
351 
352  va_start(argptr, fmt);
353  vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr);
354  va_end(argptr);
355 
356  if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
357  syslog(LOG_INFO, "%s", DebugBuffer);
358  else
359  puts(DebugBuffer);
360 } /* debug_msg */
361 
362 void debug_xxd(const char *msg, const unsigned char *buffer, const int len);
363 void debug_xxd(const char *msg, const unsigned char *buffer, const int len)
364 {
365  log_xxd(PCSC_LOG_ERROR, msg, buffer, len);
366 } /* debug_xxd */
367 #endif
368 
369 #endif /* NO_LOG */
370 
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:107
static char LogLevel
default level
Definition: debuglog.c:113
prototypes of strlcpy()/strlcat() imported from OpenBSD
This keeps a list of defines for pcsc-lite.
This handles debugging.
static signed char LogDoColor
no color by default
Definition: debuglog.c:115