#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <syslog.h>
#include <stdarg.h>
#include <stdlib.h>
#include <time.h>
#include "debugutil.h"
#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b))
int debuglevel = 0;
FILE *debugfp = NULL;
static int prio_idx_inititialized = 0;
static void set_prio_idx_init(void);
#ifndef countof
#define countof(x) (sizeof((x)) / sizeof((x)[0]))
#endif
#define VAL_NAME(x) { (x), #x}
#ifndef LOG_PRI
#define LOG_PRI(p) ((p) & LOG_PRIMASK)
#endif
static int use_syslog = 1;
static int no_debuglog = 0;
static int syslog_level_adjust = 0;
static struct {
int prio;
const char *name;
} prio_name[] = {
VAL_NAME(LOG_EMERG),
VAL_NAME(LOG_ALERT),
VAL_NAME(LOG_CRIT),
VAL_NAME(LOG_ERR),
VAL_NAME(LOG_WARNING),
VAL_NAME(LOG_NOTICE),
VAL_NAME(LOG_INFO),
VAL_NAME(LOG_DEBUG)
};
static const char *prio_name_idx[16];
static void
set_prio_idx_init()
{
int i;
if (prio_idx_inititialized)
return;
for (i = 0; i < (int)countof(prio_name); i++) {
ASSERT(prio_name[i].prio < countof(prio_name_idx));
if (prio_name[i].prio >= (int)countof(prio_name_idx))
continue;
prio_name_idx[prio_name[i].prio] = &prio_name[i].name[4];
}
prio_idx_inititialized = 1;
}
void
debug_set_debugfp(FILE *fp)
{
debugfp = fp;
}
void
debug_use_syslog(int b)
{
if (b)
use_syslog = 1;
else
use_syslog = 0;
}
void
debug_set_no_debuglog(int no_debuglog0)
{
if (no_debuglog0)
no_debuglog = 1;
else
no_debuglog = 0;
}
FILE *
debug_get_debugfp()
{
return debugfp;
}
#define DL(p) ((p) >> 24 & 0xff)
int
vlog_printf(uint32_t prio, const char *format, va_list ap)
{
int status = 0, i, fmtoff = 0, state = 0, fmtlen, saved_errno, level;
char fmt[8192];
struct tm *lt;
time_t now;
ASSERT(format != NULL);
ASSERT(format[0] != '\0');
if (DL(prio) > 0 && debuglevel < (int)DL(prio))
return -1;
if (no_debuglog && LOG_PRI(prio) >= LOG_DEBUG)
return -1;
if (!prio_idx_inititialized)
set_prio_idx_init();
if (use_syslog && DL(prio) == 0) {
level = LOG_PRI(prio) + syslog_level_adjust;
if (!no_debuglog || level < LOG_DEBUG) {
level = MINIMUM(LOG_DEBUG, level);
level = MAXIMUM(LOG_EMERG, level);
level |= (prio & LOG_FACMASK);
vsyslog(level, format, ap);
}
}
if (debugfp == NULL)
return -1;
time(&now);
lt = localtime(&now);
fmtlen = strlen(format);
for (i = 0; i < fmtlen; i++) {
if (sizeof(fmt) - fmtoff < 4)
break;
switch(state) {
case 0:
switch(format[i]) {
case '%':
state = 1;
goto copy_loop;
case '\n':
fmt[fmtoff++] = '\n';
fmt[fmtoff++] = '\t';
goto copy_loop;
}
break;
case 1:
switch(format[i]) {
default:
case '%':
fmt[fmtoff++] = '%';
state = 0;
break;
case 'm':
fmt[fmtoff] = '\0';
saved_errno = errno;
strlcat(fmt, strerror(errno), sizeof(fmt) - 1);
errno = saved_errno;
fmtoff = strlen(fmt);
state = 0;
goto copy_loop;
}
}
fmt[fmtoff++] = format[i];
copy_loop:
continue;
}
if (fmtoff > 0 && fmt[fmtoff - 1] == '\t')
fmtoff--;
if (fmtoff == 0 || fmt[fmtoff-1] != '\n')
fmt[fmtoff++] = '\n';
fmt[fmtoff] = '\0';
ASSERT(0 <= LOG_PRI(prio)
&& LOG_PRI(prio) < countof(prio_name_idx)
&& prio_name_idx[LOG_PRI(prio)] != NULL);
ftell(debugfp);
fprintf(debugfp,
"%04d-%02d-%02d %02d:%02d:%02d:%s: "
, lt->tm_year + 1900
, lt->tm_mon + 1
, lt->tm_mday
, lt->tm_hour
, lt->tm_min
, lt->tm_sec
, (prio & 0xff000000) ? "DEBUG" : prio_name_idx[LOG_PRI(prio)]
);
status = vfprintf(debugfp, fmt, ap);
fflush(debugfp);
return status;
}
int
log_printf(int prio, const char *fmt, ...)
{
int status;
va_list ap;
va_start(ap, fmt);
status = vlog_printf((uint32_t)prio, fmt, ap);
va_end(ap);
return status;
}
void
debug_set_syslog_level_adjust(int adjust)
{
syslog_level_adjust = adjust;
}
int
debug_get_syslog_level_adjust(void)
{
return syslog_level_adjust;
}
void
show_hd(FILE *file, const u_char *buf, int len)
{
int i, o = 0;
int hd_cnt = 0;
char linebuf[80];
char asciibuf[17];
memset(asciibuf, ' ', sizeof(asciibuf));
asciibuf[sizeof(asciibuf)-1] = '\0';
for (i = 0; i < len; i++) {
if (0x20 <= *(buf+i) && *(buf+i) <= 0x7e)
asciibuf[hd_cnt % 16] = *(buf+i);
else
asciibuf[hd_cnt % 16] = '.';
switch (hd_cnt % 16) {
case 0:
o += snprintf(linebuf + o, sizeof(linebuf) - o,
"%04x %02x", hd_cnt,
(unsigned char)*(buf+i));
break;
case 15:
o += snprintf(linebuf + o, sizeof(linebuf) - o,
"%02x", (unsigned char)*(buf+i));
if (file)
fprintf(file, "\t%-47s |%s|\n", linebuf,
asciibuf);
else
syslog(LOG_ERR, "%-47s |%s|\n", linebuf,
asciibuf);
memset(asciibuf, ' ', sizeof(asciibuf));
asciibuf[sizeof(asciibuf)-1] = '\0';
o = 0;
break;
case 8:
o += snprintf(linebuf + o, sizeof(linebuf) - o,
"- %02x", (unsigned char)*(buf+i));
break;
default:
if (hd_cnt % 2 == 1)
o += snprintf(linebuf + o, sizeof(linebuf) - o,
"%02x ", (unsigned char)*(buf+i));
else
o += snprintf(linebuf + o, sizeof(linebuf) - o,
"%02x", (unsigned char)*(buf+i));
break;
}
hd_cnt++;
}
if (hd_cnt > 0 && (hd_cnt % 16) != 0) {
if (file)
fprintf(file, "\t%-47s |%s|\n", linebuf, asciibuf);
else
syslog(LOG_ERR, "%-47s |%s|\n", linebuf, asciibuf);
}
if (file)
fflush(file);
}