pcsc-lite  1.8.8
debuglog.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( http://www.linuxnet.com )
3  *
4  * Copyright (C) 1999-2002
5  * David Corcoran <corcoran@linuxnet.com>
6  * Copyright (C) 2002-2011
7  * Ludovic Rousseau <ludovic.rousseau@free.fr>
8  *
9  * $Id: debuglog.c 6445 2012-08-24 08:27:10Z rousseau $
10  */
11 
17 #include "config.h"
18 #ifdef HAVE_SYSLOG_H
19 #include <syslog.h>
20 #endif
21 #include <unistd.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdarg.h>
26 #include <assert.h>
27 #include <sys/types.h>
28 #include <sys/time.h>
29 #include <time.h>
30 
31 #include "pcsclite.h"
32 #include "misc.h"
33 #include "debuglog.h"
34 #include "sys_generic.h"
35 #include "strlcpycat.h"
36 
37 #ifdef NO_LOG
38 
39 void log_msg(const int priority, const char *fmt, ...)
40 {
41  (void)priority;
42  (void)fmt;
43 }
44 
45 void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
46  const int len)
47 {
48  (void)priority;
49  (void)msg;
50  (void)buffer;
51  (void)len;
52 }
53 
54 void DebugLogSetLogType(const int dbgtype)
55 {
56  (void)dbgtype;
57 }
58 
59 void DebugLogSetLevel(const int level)
60 {
61  (void)level;
62 }
63 
64 INTERNAL int DebugLogSetCategory(const int dbginfo)
65 {
66  (void)dbginfo;
67 
68  return 0;
69 }
70 
71 INTERNAL void DebugLogCategory(const int category, const unsigned char *buffer,
72  const int len)
73 {
74  (void)category;
75  (void)buffer;
76  (void)len;
77 }
78 
79 #else
80 
84 #define DEBUG_BUF_SIZE 2048
85 
86 static char LogMsgType = DEBUGLOG_NO_DEBUG;
87 static char LogCategory = DEBUG_CATEGORY_NOTHING;
88 
90 static char LogLevel = PCSC_LOG_ERROR;
91 
92 static signed char LogDoColor = 0;
94 static void log_line(const int priority, const char *DebugBuffer);
95 
96 void log_msg(const int priority, const char *fmt, ...)
97 {
98  char DebugBuffer[DEBUG_BUF_SIZE];
99  va_list argptr;
100 
101  if ((priority < LogLevel) /* log priority lower than threshold? */
102  || (DEBUGLOG_NO_DEBUG == LogMsgType))
103  return;
104 
105  va_start(argptr, fmt);
106  vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr);
107  va_end(argptr);
108 
109  log_line(priority, DebugBuffer);
110 } /* log_msg */
111 
112 static void log_line(const int priority, const char *DebugBuffer)
113 {
114  if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
115  syslog(LOG_INFO, "%s", DebugBuffer);
116  else
117  {
118  static struct timeval last_time = { 0, 0 };
119  struct timeval new_time = { 0, 0 };
120  struct timeval tmp;
121  int delta;
122 
123  gettimeofday(&new_time, NULL);
124  if (0 == last_time.tv_sec)
125  last_time = new_time;
126 
127  tmp.tv_sec = new_time.tv_sec - last_time.tv_sec;
128  tmp.tv_usec = new_time.tv_usec - last_time.tv_usec;
129  if (tmp.tv_usec < 0)
130  {
131  tmp.tv_sec--;
132  tmp.tv_usec += 1000000;
133  }
134  if (tmp.tv_sec < 100)
135  delta = tmp.tv_sec * 1000000 + tmp.tv_usec;
136  else
137  delta = 99999999;
138 
139  last_time = new_time;
140 
141  if (LogDoColor)
142  {
143  const char *color_pfx = "", *color_sfx = "\33[0m";
144  const char *time_pfx = "\33[36m", *time_sfx = color_sfx;
145 
146  switch (priority)
147  {
148  case PCSC_LOG_CRITICAL:
149  color_pfx = "\33[01;31m"; /* bright + Red */
150  break;
151 
152  case PCSC_LOG_ERROR:
153  color_pfx = "\33[35m"; /* Magenta */
154  break;
155 
156  case PCSC_LOG_INFO:
157  color_pfx = "\33[34m"; /* Blue */
158  break;
159 
160  case PCSC_LOG_DEBUG:
161  color_pfx = ""; /* normal (black) */
162  color_sfx = "";
163  break;
164  }
165 
166  printf("%s%.8d%s %s%s%s\n", time_pfx, delta, time_sfx,
167  color_pfx, DebugBuffer, color_sfx);
168  }
169  else
170  {
171  printf("%.8d %s\n", delta, DebugBuffer);
172  }
173  fflush(stdout);
174  }
175 } /* log_msg */
176 
177 static void log_xxd_always(const int priority, const char *msg,
178  const unsigned char *buffer, const int len)
179 {
180  char DebugBuffer[len*3 + strlen(msg) +1];
181  int i;
182  char *c;
183  size_t l;
184 
185  l = strlcpy(DebugBuffer, msg, sizeof(DebugBuffer));
186  c = DebugBuffer + l;
187 
188  for (i = 0; (i < len); ++i)
189  {
190  /* 2 hex characters, 1 space, 1 NUL : total 4 characters */
191  snprintf(c, 4, "%02X ", buffer[i]);
192  c += 3;
193  }
194 
195  log_line(priority, DebugBuffer);
196 } /* log_xxd_always */
197 
198 void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
199  const int len)
200 {
201  if ((priority < LogLevel) /* log priority lower than threshold? */
202  || (DEBUGLOG_NO_DEBUG == LogMsgType))
203  return;
204 
205  /* len is an error value? */
206  if (len < 0)
207  return;
208 
209  log_xxd_always(priority, msg, buffer, len);
210 } /* log_xxd */
211 
212 void DebugLogSetLogType(const int dbgtype)
213 {
214  switch (dbgtype)
215  {
216  case DEBUGLOG_NO_DEBUG:
217  case DEBUGLOG_SYSLOG_DEBUG:
218  case DEBUGLOG_STDOUT_DEBUG:
219  case DEBUGLOG_STDOUT_COLOR_DEBUG:
220  LogMsgType = dbgtype;
221  break;
222  default:
223  Log2(PCSC_LOG_CRITICAL, "unknown log type (%d), using stdout",
224  dbgtype);
225  LogMsgType = DEBUGLOG_STDOUT_DEBUG;
226  }
227 
228  /* log to stdout and stdout is a tty? */
229  if ((DEBUGLOG_STDOUT_DEBUG == LogMsgType && isatty(fileno(stdout)))
230  || (DEBUGLOG_STDOUT_COLOR_DEBUG == LogMsgType))
231  {
232  const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode", "xterm-256color" };
233  char *term;
234 
235  term = getenv("TERM");
236  if (term)
237  {
238  unsigned int i;
239 
240  /* for each known color terminal */
241  for (i = 0; i < sizeof(terms) / sizeof(terms[0]); i++)
242  {
243  /* we found a supported term? */
244  if (0 == strcmp(terms[i], term))
245  {
246  LogDoColor = 1;
247  break;
248  }
249  }
250  }
251  }
252 }
253 
254 void DebugLogSetLevel(const int level)
255 {
256  LogLevel = level;
257  switch (level)
258  {
259  case PCSC_LOG_CRITICAL:
260  case PCSC_LOG_ERROR:
261  /* do not log anything */
262  break;
263 
264  case PCSC_LOG_INFO:
265  Log1(PCSC_LOG_INFO, "debug level=notice");
266  break;
267 
268  case PCSC_LOG_DEBUG:
269  Log1(PCSC_LOG_DEBUG, "debug level=debug");
270  break;
271 
272  default:
273  LogLevel = PCSC_LOG_INFO;
274  Log2(PCSC_LOG_CRITICAL, "unknown level (%d), using level=notice",
275  level);
276  }
277 }
278 
279 INTERNAL int DebugLogSetCategory(const int dbginfo)
280 {
281 #define DEBUG_INFO_LENGTH 80
282  char text[DEBUG_INFO_LENGTH];
283 
284  /* use a negative number to UNset
285  * typically use ~DEBUG_CATEGORY_APDU
286  */
287  if (dbginfo < 0)
288  LogCategory &= dbginfo;
289  else
290  LogCategory |= dbginfo;
291 
292  /* set to empty string */
293  text[0] = '\0';
294 
295  if (LogCategory & DEBUG_CATEGORY_APDU)
296  strlcat(text, " APDU", sizeof(text));
297 
298  Log2(PCSC_LOG_INFO, "Debug options:%s", text);
299 
300  return LogCategory;
301 }
302 
303 INTERNAL void DebugLogCategory(const int category, const unsigned char *buffer,
304  const int len)
305 {
306  if ((category & DEBUG_CATEGORY_APDU)
307  && (LogCategory & DEBUG_CATEGORY_APDU))
308  log_xxd_always(PCSC_LOG_INFO, "APDU: ", buffer, len);
309 
310  if ((category & DEBUG_CATEGORY_SW)
311  && (LogCategory & DEBUG_CATEGORY_APDU))
312  log_xxd_always(PCSC_LOG_INFO, "SW: ", buffer, len);
313 }
314 
315 /*
316  * old function supported for backward object code compatibility
317  * defined only for pcscd
318  */
319 #ifdef PCSCD
320 void debug_msg(const char *fmt, ...);
321 void debug_msg(const char *fmt, ...)
322 {
323  char DebugBuffer[DEBUG_BUF_SIZE];
324  va_list argptr;
325 
326  if (DEBUGLOG_NO_DEBUG == LogMsgType)
327  return;
328 
329  va_start(argptr, fmt);
330  vsnprintf(DebugBuffer, sizeof DebugBuffer, fmt, argptr);
331  va_end(argptr);
332 
333  if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
334  syslog(LOG_INFO, "%s", DebugBuffer);
335  else
336  puts(DebugBuffer);
337 } /* debug_msg */
338 
339 void debug_xxd(const char *msg, const unsigned char *buffer, const int len);
340 void debug_xxd(const char *msg, const unsigned char *buffer, const int len)
341 {
342  log_xxd(PCSC_LOG_ERROR, msg, buffer, len);
343 } /* debug_xxd */
344 #endif
345 
346 #endif /* NO_LOG */
347 
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:84
static char LogLevel
default level
Definition: debuglog.c:90
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:92