/*
* DEBUG - debugging functions
*
* Author:
* Emile van Bergen, emile@evbergen.xs4all.nl
*
* Permission to redistribute an original or modified version of this program
* in source, intermediate or object code form is hereby granted exclusively
* under the terms of the GNU General Public License, version 2. Please see the
* file COPYING for details, or refer to http://www.gnu.org/copyleft/gpl.html.
*
* History:
* 2000/12/02 - EvB - Created
* 2001/02/06 - EvB - Made dbg_cvtstr NULL-proof
* 2001/11/01 - EvB - Added standard logging functions
* 2002/02/06 - EvB - Added msg_line interface and made meta_printav
* and hexdump use it instead of writing to stderr
* 2005/06/20 - EvB - Add tag if we run as a module
*/
char debug_id[] = "DEBUG - Copyright (C) 2000 Emile van Bergen.";
/*
* INCLUDES & DEFINES
*/
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h> /* For vsprintf / vsnprintf */
#include <misc.h> /* For MIN */
#include <metatype.h> /* For meta_atoprt() and meta_ordtoa() */
#include <debug.h>
#include <platform.h>
/*
* GLOBALS
*/
int debuglevel = 0; /* Backwards compatibility only */
int msg_syslogfac = -1; /* Syslog facility to which we output all */
int msg_nostderr = 0; /* Be quiet on stderr */
char *msg_tag = 0; /* Extra tag to add to each line */
int msg_tagl = 0;
int msg_thresh[F_CNT] = { /* Priority threshold (only lower-numbered */
L_ERR, L_ERR, /* or equal gets through */
L_ERR, L_ERR,
L_ERR, L_ERR
};
char *msg_f_names[F_CNT+1] = { /* Names for our own internal facilities */
"misc", /* miscellaneous */
"text", /* textfile handling (dictionary) */
"lang", /* language */
"proc", /* subprocess events */
"recv", /* packet reception */
"send", /* packet sending */
0 /* not found */
};
#ifdef HAVE_SYSLOG
#include <syslog.h>
#define SYSLOG_F_CNT 18 /* Syslog facilities */
struct {
char *name;
int fac;
} syslog_f_map[SYSLOG_F_CNT + 1] = {
{ "auth", LOG_AUTH },
{ "cron", LOG_CRON },
{ "daemon", LOG_DAEMON },
{ "kern", LOG_KERN },
{ "lpr", LOG_LPR },
{ "mail", LOG_MAIL },
{ "news", LOG_NEWS },
{ "syslog", LOG_SYSLOG },
{ "user", LOG_USER },
{ "uucp", LOG_UUCP },
{ "local0", LOG_LOCAL0 },
{ "local1", LOG_LOCAL1 },
{ "local2", LOG_LOCAL2 },
{ "local3", LOG_LOCAL3 },
{ "local4", LOG_LOCAL4 },
{ "local5", LOG_LOCAL5 },
{ "local6", LOG_LOCAL6 },
{ "local7", LOG_LOCAL7 },
{ 0, -1 }, /* not found */
};
#ifndef LOG_MAKEPRI
#define LOG_MAKEPRI(f, p) ((f) | (p))
#endif
#endif
/*
* FUNCTIONS
*/
void msg_init(int syslogfac, int nostderr)
{
msg_syslogfac = syslogfac;
msg_nostderr = nostderr;
#ifdef HAVE_SYSLOG
if (msg_syslogfac != -1) openlog("openradius", 0, msg_syslogfac);
#endif
}
void msg_setthresh(int ourfac, int level)
{
if (ourfac >= 0 && ourfac < F_CNT) msg_thresh[ourfac] = level;
}
void msg_settag(char *tag, int tagl)
{
if (tagl < 32 && tag) { msg_tag = tag; msg_tagl = tagl; }
}
int msg_getfacbyname(char *name)
{
int ret;
for(ret = 0;
ret < F_CNT && strcmp(name, msg_f_names[ret]);
ret++);
return ret;
}
#if 0
char *msg_getfacbynr(int ourfac)
{
return (ourfac >= 0 && ourfac < F_CNT) ? msg_f_names[ourfac] : "****";
}
#endif
int msg_getsyslogfacbyname(char *name)
{
#ifdef HAVE_SYSLOG
int ret;
for(ret = 0;
ret < SYSLOG_F_CNT && strcmp(name, syslog_f_map[ret].name);
ret++);
return syslog_f_map[ret].fac;
#else
return -1;
#endif
}
void msg(int ourfac, int level, char *fmt, ...)
{
static char logline[4096];
char *o;
int n;
va_list ap;
/* Return if level is not high (numerically low) enough */
if (level > msg_thresh[ourfac]) return;
/* Init logline */
o = logline;
if (msg_tagl && msg_tag) {
*o++ = '[';
memcpy(o, msg_tag, msg_tagl); o += msg_tagl;
*o++ = ']';
*o++ = ' ';
}
*o++ = '[';
memcpy(o, msg_f_names[ourfac], 4); o += 4;
*o ++ = ']';
*o ++ = ' ';
/* Prepare arglist and create formatted line */
va_start(ap, fmt);
n = logline + sizeof(logline) - 16 - o;
#ifdef HAVE_VSNPRINTF
vsnprintf(o, n, fmt, ap);
#else
if (vsprintf(o, fmt, ap) >= n) _exit(254); /* safest */
#endif
msg_line(level, logline);
va_end(ap);
}
void msg_line(int level, char *logline)
{
/* Write line to stderr if we haven't been told to be quiet */
if (!msg_nostderr)
write(2, logline, strlen(logline));
#ifdef HAVE_SYSLOG
/* Write line to syslog if facility is not none */
if (msg_syslogfac != -1)
syslog(LOG_MAKEPRI(msg_syslogfac, level), "%s", logline);
#endif
}
char *dbg_cvtstr(char *s, int slen)
{
static char dbg_cvtbuf[DBG_CVTBUFLEN];
int len;
len = s ? meta_atoprt(s,slen, 0,0,0,0, dbg_cvtbuf,DBG_CVTBUFLEN-1) : 0;
dbg_cvtbuf[len] = 0;
return dbg_cvtbuf;
}
#define DBG_HEXBUFLEN (4 + 2 + 16 * 3 + 1 + 16 + 1 + 1)
void hexdump(char *s, int slen)
{
static char hexbuf[DBG_HEXBUFLEN];
char *o;
int ofs, i;
for(ofs = 0; ofs < slen; ofs += 16, s += 16) {
o = hexbuf;
memset(o, ' ', DBG_HEXBUFLEN - 1);
o += meta_ordtoa(o, 4, 4, 16, ofs) + 2;
for(i = 0; i < MIN(slen - ofs, 16); i++)
o += meta_ordtoa(o, 2, 2, 16, s[i] & 0xff) + 1;
o = hexbuf + 4 + 2 + 16 * 3 + 1;
for(i = 0; i < MIN(slen - ofs, 16); i++)
*o++ = s[i] > 31 && s[i] < 127 ? s[i] : '.';
hexbuf[4 + 2 + 16 * 3 + 1 + 16] = '\n';
hexbuf[DBG_HEXBUFLEN - 1] = 0;
msg_line(L_DEBUG, hexbuf);
}
}
syntax highlighted by Code2HTML, v. 0.9.1