#include "config.h"
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
#endif
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>
#include <sys/types.h>
#include "wintypes.h"
#include "pcsclite.h"
#include "debuglog.h"
#include "sys_generic.h"
#define DEBUG_BUF_SIZE 2048
static char LogSuppress = DEBUGLOG_LOG_ENTRIES;
static char LogMsgType = DEBUGLOG_NO_DEBUG;
static char LogCategory = DEBUG_CATEGORY_NOTHING;
static char LogLevel = PCSC_LOG_INFO;
static signed char LogDoColor = 0;
void log_msg(const int priority, const char *fmt, ...)
{
char DebugBuffer[DEBUG_BUF_SIZE];
va_list argptr;
if ((LogSuppress != DEBUGLOG_LOG_ENTRIES)
|| (priority < LogLevel)
|| (DEBUGLOG_NO_DEBUG == LogMsgType))
return;
va_start(argptr, fmt);
vsnprintf(DebugBuffer, DEBUG_BUF_SIZE, fmt, argptr);
va_end(argptr);
if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
syslog(LOG_INFO, "%s", DebugBuffer);
else
{
if (LogDoColor)
{
const char *color_pfx = "", *color_sfx = "\33[0m";
switch (priority)
{
case PCSC_LOG_CRITICAL:
color_pfx = "\33[01;31m";
break;
case PCSC_LOG_ERROR:
color_pfx = "\33[35m";
break;
case PCSC_LOG_INFO:
color_pfx = "\33[34m";
break;
case PCSC_LOG_DEBUG:
color_pfx = "";
color_sfx = "";
break;
}
fprintf(stderr, "%s%s%s\n", color_pfx, DebugBuffer, color_sfx);
}
else
fprintf(stderr, "%s\n", DebugBuffer);
}
}
void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
const int len)
{
char DebugBuffer[DEBUG_BUF_SIZE];
int i;
char *c;
char *debug_buf_end;
if ((LogSuppress != DEBUGLOG_LOG_ENTRIES)
|| (priority < LogLevel)
|| (DEBUGLOG_NO_DEBUG == LogMsgType))
return;
debug_buf_end = DebugBuffer + DEBUG_BUF_SIZE - 5;
strlcpy(DebugBuffer, msg, sizeof(DebugBuffer));
c = DebugBuffer + strlen(DebugBuffer);
for (i = 0; (i < len) && (c < debug_buf_end); ++i)
{
sprintf(c, "%02X ", buffer[i]);
c += 3;
}
if ((c >= debug_buf_end) && (i < len))
c[-3] = c[-2] = c[-1] = '.';
if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
syslog(LOG_INFO, "%s", DebugBuffer);
else
fprintf(stderr, "%s\n", DebugBuffer);
}
#ifdef PCSCD
void DebugLogSuppress(const int lSType)
{
LogSuppress = lSType;
}
#endif
void DebugLogSetLogType(const int dbgtype)
{
switch (dbgtype)
{
case DEBUGLOG_NO_DEBUG:
case DEBUGLOG_SYSLOG_DEBUG:
case DEBUGLOG_STDERR_DEBUG:
LogMsgType = dbgtype;
break;
default:
Log2(PCSC_LOG_CRITICAL, "unknown log type (%d), using stderr",
dbgtype);
LogMsgType = DEBUGLOG_STDERR_DEBUG;
}
if (DEBUGLOG_STDERR_DEBUG == LogMsgType && isatty(fileno(stderr)))
{
const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode" };
char *term;
term = getenv("TERM");
if (term)
{
unsigned int i;
for (i = 0; i < sizeof(terms) / sizeof(terms[0]); i++)
{
if (0 == strcmp(terms[i], term))
{
LogDoColor = 1;
break;
}
}
}
}
}
void DebugLogSetLevel(const int level)
{
LogLevel = level;
switch (level)
{
case PCSC_LOG_CRITICAL:
case PCSC_LOG_ERROR:
break;
case PCSC_LOG_INFO:
Log1(PCSC_LOG_INFO, "debug level=notice");
break;
case PCSC_LOG_DEBUG:
Log1(PCSC_LOG_DEBUG, "debug level=debug");
break;
default:
LogLevel = PCSC_LOG_INFO;
Log2(PCSC_LOG_CRITICAL, "unknown level (%d), using level=notice",
level);
}
}
int DebugLogSetCategory(const int dbginfo)
{
#define DEBUG_INFO_LENGTH 80
char text[DEBUG_INFO_LENGTH];
if (dbginfo < 0)
LogCategory &= dbginfo;
else
LogCategory |= dbginfo;
text[0] = '\0';
if (LogCategory & DEBUG_CATEGORY_APDU)
strlcat(text, " APDU", sizeof(text));
Log2(PCSC_LOG_INFO, "Debug options:%s", text);
return LogCategory;
}
void DebugLogCategory(const int category, const unsigned char *buffer,
const int len)
{
if ((category & DEBUG_CATEGORY_APDU)
&& (LogCategory & DEBUG_CATEGORY_APDU))
log_xxd(PCSC_LOG_INFO, "APDU: ", (const unsigned char *)buffer, len);
if ((category & DEBUG_CATEGORY_SW)
&& (LogCategory & DEBUG_CATEGORY_APDU))
log_xxd(PCSC_LOG_INFO, "SW: ", (const unsigned char *)buffer, len);
}
#ifdef PCSCD
void debug_msg(const char *fmt, ...);
void debug_msg(const char *fmt, ...)
{
char DebugBuffer[DEBUG_BUF_SIZE];
va_list argptr;
if ((LogSuppress != DEBUGLOG_LOG_ENTRIES)
|| (DEBUGLOG_NO_DEBUG == LogMsgType))
return;
va_start(argptr, fmt);
vsnprintf(DebugBuffer, DEBUG_BUF_SIZE, fmt, argptr);
va_end(argptr);
if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
syslog(LOG_INFO, "%s", DebugBuffer);
else
fprintf(stderr, "%s\n", DebugBuffer);
}
void debug_xxd(const char *msg, const unsigned char *buffer, const int len);
void debug_xxd(const char *msg, const unsigned char *buffer, const int len)
{
log_xxd(PCSC_LOG_ERROR, msg, buffer, len);
}
#endif