pcsc-lite  1.8.11
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 Changes to this license can be made only by the copyright author with
22 explicit written consent.
23 
24 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  *
35  * $Id: debuglog.c 6851 2014-02-14 15:43:32Z rousseau $
36  */
37 
43 #include "config.h"
44 #ifdef HAVE_SYSLOG_H
45 #include <syslog.h>
46 #endif
47 #include <unistd.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <stdarg.h>
52 #include <assert.h>
53 #include <sys/types.h>
54 #include <sys/time.h>
55 #include <time.h>
56 
57 #include "pcsclite.h"
58 #include "misc.h"
59 #include "debuglog.h"
60 #include "sys_generic.h"
61 #include "strlcpycat.h"
62 
63 #ifdef NO_LOG
64 
65 void log_msg(const int priority, const char *fmt, ...)
66 {
67  (void)priority;
68  (void)fmt;
69 }
70 
71 void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
72  const int len)
73 {
74  (void)priority;
75  (void)msg;
76  (void)buffer;
77  (void)len;
78 }
79 
80 void DebugLogSetLogType(const int dbgtype)
81 {
82  (void)dbgtype;
83 }
84 
85 void DebugLogSetLevel(const int level)
86 {
87  (void)level;
88 }
89 
90 INTERNAL int DebugLogSetCategory(const int dbginfo)
91 {
92  (void)dbginfo;
93 
94  return 0;
95 }
96 
97 INTERNAL void DebugLogCategory(const int category, const unsigned char *buffer,
98  const int len)
99 {
100  (void)category;
101  (void)buffer;
102  (void)len;
103 }
104 
105 #else
106 
110 #define DEBUG_BUF_SIZE 2048
111 
112 static char LogMsgType = DEBUGLOG_NO_DEBUG;
113 static char LogCategory = DEBUG_CATEGORY_NOTHING;
114 
116 static char LogLevel = PCSC_LOG_ERROR;
117 
118 static signed char LogDoColor = 0;
120 static void log_line(const int priority, const char *DebugBuffer);
121 
122 void log_msg(const int priority, const char *fmt, ...)
123 {
124  char DebugBuffer[DEBUG_BUF_SIZE];
125  va_list argptr;
126 
127  if ((priority < LogLevel) /* log priority lower than threshold? */
128  || (DEBUGLOG_NO_DEBUG == LogMsgType))
129  return;
130 
131  va_start(argptr, fmt);
132  vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr);
133  va_end(argptr);
134 
135  log_line(priority, DebugBuffer);
136 } /* log_msg */
137 
138 static void log_line(const int priority, const char *DebugBuffer)
139 {
140  if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
141  syslog(LOG_INFO, "%s", DebugBuffer);
142  else
143  {
144  static struct timeval last_time = { 0, 0 };
145  struct timeval new_time = { 0, 0 };
146  struct timeval tmp;
147  int delta;
148 
149  gettimeofday(&new_time, NULL);
150  if (0 == last_time.tv_sec)
151  last_time = new_time;
152 
153  tmp.tv_sec = new_time.tv_sec - last_time.tv_sec;
154  tmp.tv_usec = new_time.tv_usec - last_time.tv_usec;
155  if (tmp.tv_usec < 0)
156  {
157  tmp.tv_sec--;
158  tmp.tv_usec += 1000000;
159  }
160  if (tmp.tv_sec < 100)
161  delta = tmp.tv_sec * 1000000 + tmp.tv_usec;
162  else
163  delta = 99999999;
164 
165  last_time = new_time;
166 
167  if (LogDoColor)
168  {
169  const char *color_pfx = "", *color_sfx = "\33[0m";
170  const char *time_pfx = "\33[36m", *time_sfx = color_sfx;
171 
172  switch (priority)
173  {
174  case PCSC_LOG_CRITICAL:
175  color_pfx = "\33[01;31m"; /* bright + Red */
176  break;
177 
178  case PCSC_LOG_ERROR:
179  color_pfx = "\33[35m"; /* Magenta */
180  break;
181 
182  case PCSC_LOG_INFO:
183  color_pfx = "\33[34m"; /* Blue */
184  break;
185 
186  case PCSC_LOG_DEBUG:
187  color_pfx = ""; /* normal (black) */
188  color_sfx = "";
189  break;
190  }
191 
192  printf("%s%.8d%s %s%s%s\n", time_pfx, delta, time_sfx,
193  color_pfx, DebugBuffer, color_sfx);
194  }
195  else
196  {
197  printf("%.8d %s\n", delta, DebugBuffer);
198  }
199  fflush(stdout);
200  }
201 } /* log_msg */
202 
203 static void log_xxd_always(const int priority, const char *msg,
204  const unsigned char *buffer, const int len)
205 {
206  char DebugBuffer[len*3 + strlen(msg) +1];
207  int i;
208  char *c;
209  size_t l;
210 
211  l = strlcpy(DebugBuffer, msg, sizeof(DebugBuffer));
212  c = DebugBuffer + l;
213 
214  for (i = 0; (i < len); ++i)
215  {
216  /* 2 hex characters, 1 space, 1 NUL : total 4 characters */
217  snprintf(c, 4, "%02X ", buffer[i]);
218  c += 3;
219  }
220 
221  log_line(priority, DebugBuffer);
222 } /* log_xxd_always */
223 
224 void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
225  const int len)
226 {
227  if ((priority < LogLevel) /* log priority lower than threshold? */
228  || (DEBUGLOG_NO_DEBUG == LogMsgType))
229  return;
230 
231  /* len is an error value? */
232  if (len < 0)
233  return;
234 
235  log_xxd_always(priority, msg, buffer, len);
236 } /* log_xxd */
237 
238 void DebugLogSetLogType(const int dbgtype)
239 {
240  switch (dbgtype)
241  {
242  case DEBUGLOG_NO_DEBUG:
243  case DEBUGLOG_SYSLOG_DEBUG:
244  case DEBUGLOG_STDOUT_DEBUG:
245  case DEBUGLOG_STDOUT_COLOR_DEBUG:
246  LogMsgType = dbgtype;
247  break;
248  default:
249  Log2(PCSC_LOG_CRITICAL, "unknown log type (%d), using stdout",
250  dbgtype);
251  LogMsgType = DEBUGLOG_STDOUT_DEBUG;
252  }
253 
254  /* log to stdout and stdout is a tty? */
255  if ((DEBUGLOG_STDOUT_DEBUG == LogMsgType && isatty(fileno(stdout)))
256  || (DEBUGLOG_STDOUT_COLOR_DEBUG == LogMsgType))
257  {
258  char *term;
259 
260  term = getenv("TERM");
261  if (term)
262  {
263  const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode", "xterm-256color" };
264  unsigned int i;
265 
266  /* for each known color terminal */
267  for (i = 0; i < COUNT_OF(terms); i++)
268  {
269  /* we found a supported term? */
270  if (0 == strcmp(terms[i], term))
271  {
272  LogDoColor = 1;
273  break;
274  }
275  }
276  }
277  }
278 }
279 
280 void DebugLogSetLevel(const int level)
281 {
282  LogLevel = level;
283  switch (level)
284  {
285  case PCSC_LOG_CRITICAL:
286  case PCSC_LOG_ERROR:
287  /* do not log anything */
288  break;
289 
290  case PCSC_LOG_INFO:
291  Log1(PCSC_LOG_INFO, "debug level=notice");
292  break;
293 
294  case PCSC_LOG_DEBUG:
295  Log1(PCSC_LOG_DEBUG, "debug level=debug");
296  break;
297 
298  default:
299  LogLevel = PCSC_LOG_INFO;
300  Log2(PCSC_LOG_CRITICAL, "unknown level (%d), using level=notice",
301  level);
302  }
303 }
304 
305 INTERNAL int DebugLogSetCategory(const int dbginfo)
306 {
307 #define DEBUG_INFO_LENGTH 80
308  char text[DEBUG_INFO_LENGTH];
309 
310  /* use a negative number to UNset
311  * typically use ~DEBUG_CATEGORY_APDU
312  */
313  if (dbginfo < 0)
314  LogCategory &= dbginfo;
315  else
316  LogCategory |= dbginfo;
317 
318  /* set to empty string */
319  text[0] = '\0';
320 
321  if (LogCategory & DEBUG_CATEGORY_APDU)
322  strlcat(text, " APDU", sizeof(text));
323 
324  Log2(PCSC_LOG_INFO, "Debug options:%s", text);
325 
326  return LogCategory;
327 }
328 
329 INTERNAL void DebugLogCategory(const int category, const unsigned char *buffer,
330  const int len)
331 {
332  if ((category & DEBUG_CATEGORY_APDU)
333  && (LogCategory & DEBUG_CATEGORY_APDU))
334  log_xxd_always(PCSC_LOG_INFO, "APDU: ", buffer, len);
335 
336  if ((category & DEBUG_CATEGORY_SW)
337  && (LogCategory & DEBUG_CATEGORY_APDU))
338  log_xxd_always(PCSC_LOG_INFO, "SW: ", buffer, len);
339 }
340 
341 /*
342  * old function supported for backward object code compatibility
343  * defined only for pcscd
344  */
345 #ifdef PCSCD
346 void debug_msg(const char *fmt, ...);
347 void debug_msg(const char *fmt, ...)
348 {
349  char DebugBuffer[DEBUG_BUF_SIZE];
350  va_list argptr;
351 
352  if (DEBUGLOG_NO_DEBUG == LogMsgType)
353  return;
354 
355  va_start(argptr, fmt);
356  vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr);
357  va_end(argptr);
358 
359  if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
360  syslog(LOG_INFO, "%s", DebugBuffer);
361  else
362  puts(DebugBuffer);
363 } /* debug_msg */
364 
365 void debug_xxd(const char *msg, const unsigned char *buffer, const int len);
366 void debug_xxd(const char *msg, const unsigned char *buffer, const int len)
367 {
368  log_xxd(PCSC_LOG_ERROR, msg, buffer, len);
369 } /* debug_xxd */
370 #endif
371 
372 #endif /* NO_LOG */
373 
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:110
static char LogLevel
default level
Definition: debuglog.c:116
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:118