1/* 2 * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * debuglog.c 26 * SmartCardServices 27 */ 28 29/* 30 * MUSCLE SmartCard Development ( http://www.linuxnet.com ) 31 * 32 * Copyright (C) 1999-2002 33 * David Corcoran <corcoran@linuxnet.com> 34 * Copyright (C) 1999-2005 35 * Ludovic Rousseau <ludovic.rousseau@free.fr> 36 * 37 * $Id: debuglog.c 123 2010-03-27 10:50:42Z ludovic.rousseau@gmail.com $ 38 */ 39 40/** 41 * @file 42 * @brief This handles debugging for pcscd. 43 */ 44 45#include "config.h" 46#ifdef HAVE_SYSLOG_H 47#include <syslog.h> 48#endif 49#include <unistd.h> 50#include <stdio.h> 51#include <stdlib.h> 52#include <string.h> 53#include <stdarg.h> 54#include <assert.h> 55#include <sys/types.h> 56 57#include "wintypes.h" 58#include "pcsclite.h" 59#include "debuglog.h" 60#include "sys_generic.h" 61//#include "strlcpy.h" 62 63/** 64 * Max string size when dumping a 256 bytes longs APDU 65 * Should be bigger than 256*3+30 66 */ 67#define DEBUG_BUF_SIZE 2048 68 69static char LogSuppress = DEBUGLOG_LOG_ENTRIES; 70static char LogMsgType = DEBUGLOG_NO_DEBUG; 71static char LogCategory = DEBUG_CATEGORY_NOTHING; 72 73/* default level is a bit verbose to be backward compatible */ 74static char LogLevel = PCSC_LOG_INFO; 75 76static signed char LogDoColor = 0; /* no color by default */ 77 78void log_msg(const int priority, const char *fmt, ...) 79{ 80 char DebugBuffer[DEBUG_BUF_SIZE]; 81 va_list argptr; 82 83 if ((LogSuppress != DEBUGLOG_LOG_ENTRIES) 84 || (priority < LogLevel) /* log priority lower than threshold? */ 85 || (DEBUGLOG_NO_DEBUG == LogMsgType)) 86 return; 87 88 va_start(argptr, fmt); 89 vsnprintf(DebugBuffer, DEBUG_BUF_SIZE, fmt, argptr); 90 va_end(argptr); 91 92 if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType) 93 syslog(LOG_INFO, "%s", DebugBuffer); 94 else 95 { 96 if (LogDoColor) 97 { 98 const char *color_pfx = "", *color_sfx = "\33[0m"; 99 100 switch (priority) 101 { 102 case PCSC_LOG_CRITICAL: 103 color_pfx = "\33[01;31m"; /* bright + Red */ 104 break; 105 106 case PCSC_LOG_ERROR: 107 color_pfx = "\33[35m"; /* Magenta */ 108 break; 109 110 case PCSC_LOG_INFO: 111 color_pfx = "\33[34m"; /* Blue */ 112 break; 113 114 case PCSC_LOG_DEBUG: 115 color_pfx = ""; /* normal (black) */ 116 color_sfx = ""; 117 break; 118 } 119 fprintf(stderr, "%s%s%s\n", color_pfx, DebugBuffer, color_sfx); 120 } 121 else 122 fprintf(stderr, "%s\n", DebugBuffer); 123 } 124} /* log_msg */ 125 126void log_xxd(const int priority, const char *msg, const unsigned char *buffer, 127 const int len) 128{ 129 char DebugBuffer[DEBUG_BUF_SIZE]; 130 int i; 131 char *c; 132 char *debug_buf_end; 133 134 if ((LogSuppress != DEBUGLOG_LOG_ENTRIES) 135 || (priority < LogLevel) /* log priority lower than threshold? */ 136 || (DEBUGLOG_NO_DEBUG == LogMsgType)) 137 return; 138 139 debug_buf_end = DebugBuffer + DEBUG_BUF_SIZE - 5; 140 141 strlcpy(DebugBuffer, msg, sizeof(DebugBuffer)); 142 c = DebugBuffer + strlen(DebugBuffer); 143 144 for (i = 0; (i < len) && (c < debug_buf_end); ++i) 145 { 146 sprintf(c, "%02X ", buffer[i]); 147 c += 3; 148 } 149 150 /* the buffer is too small so end it with "..." */ 151 if ((c >= debug_buf_end) && (i < len)) 152 c[-3] = c[-2] = c[-1] = '.'; 153 154 if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType) 155 syslog(LOG_INFO, "%s", DebugBuffer); 156 else 157 fprintf(stderr, "%s\n", DebugBuffer); 158} /* log_xxd */ 159 160#ifdef PCSCD 161void DebugLogSuppress(const int lSType) 162{ 163 LogSuppress = lSType; 164} 165#endif 166 167void DebugLogSetLogType(const int dbgtype) 168{ 169 switch (dbgtype) 170 { 171 case DEBUGLOG_NO_DEBUG: 172 case DEBUGLOG_SYSLOG_DEBUG: 173 case DEBUGLOG_STDERR_DEBUG: 174 LogMsgType = dbgtype; 175 break; 176 default: 177 Log2(PCSC_LOG_CRITICAL, "unknown log type (%d), using stderr", 178 dbgtype); 179 LogMsgType = DEBUGLOG_STDERR_DEBUG; 180 } 181 182 /* log to stderr and stderr is a tty? */ 183 if (DEBUGLOG_STDERR_DEBUG == LogMsgType && isatty(fileno(stderr))) 184 { 185 const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode" }; 186 char *term; 187 188 term = getenv("TERM"); 189 if (term) 190 { 191 unsigned int i; 192 193 /* for each known color terminal */ 194 for (i = 0; i < sizeof(terms) / sizeof(terms[0]); i++) 195 { 196 /* we found a supported term? */ 197 if (0 == strcmp(terms[i], term)) 198 { 199 LogDoColor = 1; 200 break; 201 } 202 } 203 } 204 } 205} 206 207void DebugLogSetLevel(const int level) 208{ 209 LogLevel = level; 210 switch (level) 211 { 212 case PCSC_LOG_CRITICAL: 213 case PCSC_LOG_ERROR: 214 /* do not log anything */ 215 break; 216 217 case PCSC_LOG_INFO: 218 Log1(PCSC_LOG_INFO, "debug level=notice"); 219 break; 220 221 case PCSC_LOG_DEBUG: 222 Log1(PCSC_LOG_DEBUG, "debug level=debug"); 223 break; 224 225 default: 226 LogLevel = PCSC_LOG_INFO; 227 Log2(PCSC_LOG_CRITICAL, "unknown level (%d), using level=notice", 228 level); 229 } 230} 231 232int DebugLogSetCategory(const int dbginfo) 233{ 234#define DEBUG_INFO_LENGTH 80 235 char text[DEBUG_INFO_LENGTH]; 236 237 /* use a negative number to UNset 238 * typically use ~DEBUG_CATEGORY_APDU 239 */ 240 if (dbginfo < 0) 241 LogCategory &= dbginfo; 242 else 243 LogCategory |= dbginfo; 244 245 /* set to empty string */ 246 text[0] = '\0'; 247 248 if (LogCategory & DEBUG_CATEGORY_APDU) 249 strlcat(text, " APDU", sizeof(text)); 250 251 Log2(PCSC_LOG_INFO, "Debug options:%s", text); 252 253 return LogCategory; 254} 255 256void DebugLogCategory(const int category, const unsigned char *buffer, 257 const int len) 258{ 259 if ((category & DEBUG_CATEGORY_APDU) 260 && (LogCategory & DEBUG_CATEGORY_APDU)) 261 log_xxd(PCSC_LOG_INFO, "APDU: ", (const unsigned char *)buffer, len); 262 263 if ((category & DEBUG_CATEGORY_SW) 264 && (LogCategory & DEBUG_CATEGORY_APDU)) 265 log_xxd(PCSC_LOG_INFO, "SW: ", (const unsigned char *)buffer, len); 266} 267 268/* 269 * old function supported for backward object code compatibility 270 * defined only for pcscd 271 */ 272#ifdef PCSCD 273void debug_msg(const char *fmt, ...); 274void debug_msg(const char *fmt, ...) 275{ 276 char DebugBuffer[DEBUG_BUF_SIZE]; 277 va_list argptr; 278 279 if ((LogSuppress != DEBUGLOG_LOG_ENTRIES) 280 || (DEBUGLOG_NO_DEBUG == LogMsgType)) 281 return; 282 283 va_start(argptr, fmt); 284 vsnprintf(DebugBuffer, DEBUG_BUF_SIZE, fmt, argptr); 285 va_end(argptr); 286 287 if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType) 288 syslog(LOG_INFO, "%s", DebugBuffer); 289 else 290 fprintf(stderr, "%s\n", DebugBuffer); 291} /* debug_msg */ 292 293void debug_xxd(const char *msg, const unsigned char *buffer, const int len); 294void debug_xxd(const char *msg, const unsigned char *buffer, const int len) 295{ 296 log_xxd(PCSC_LOG_ERROR, msg, buffer, len); 297} /* debug_xxd */ 298#endif 299 300