/*
* $Id: report.c,v 1.11 2006/07/18 17:51:01 heas Exp $
*
* Copyright (c) 1995-1998 by Cisco systems, Inc.
*
* Permission to use, copy, modify, and distribute this software for
* any purpose and without fee is hereby granted, provided that this
* copyright and permission notice appear on all copies of the
* software and supporting documentation, the name of Cisco Systems,
* Inc. not be used in advertising or publicity pertaining to
* distribution of the program without specific prior permission, and
* notice be given in supporting documentation that modification,
* copying and distribution is by permission of Cisco Systems, Inc.
*
* Cisco Systems, Inc. makes no representations about the suitability
* of this software for any purpose. THIS SOFTWARE IS PROVIDED ``AS
* IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
* WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "tac_plus.h"
#include <stdio.h>
#ifdef AIX
#include <sys/types.h>
#else
#include <time.h>
#endif
#ifdef __STDC__
#include <stdarg.h> /* ANSI C, variable length args */
#else
#include <varargs.h> /* has 'vararg' definitions */
#endif
FILE *ostream = NULL;
char *logfile = TACPLUS_LOGFILE;
/* report:
*
* This routine reports errors and such via stderr and syslog() if
* appopriate. It just helps avoid a lot of if-else in the code.
*
* LOG_DEBUG messages are ignored unless debugging is on.
* All other priorities are always logged to syslog.
*/
#ifdef __STDC__
void
report(int priority, char *fmt, ...)
#else
/* VARARGS2 */
void
report(priority, fmt, va_alist)
int priority;
char *fmt;
va_dcl /* no terminating semi-colon */
#endif
{
char msg[255]; /* temporary string */
char *fp, *bufp, *charp;
int len, m, i, n;
char digits[16];
va_list ap;
charp = NULL;
m = 0;
#ifdef __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
/* ensure that msg is never overwritten */
n = 255;
fp = fmt;
len = 0;
msg[n-1] = '\0';
bufp = msg;
while (*fp) {
if (*fp != '%') {
if ((len+1) >= n) {
break;
}
*bufp++ = *fp++;
len++;
continue;
}
/* seen a '%' */
fp++;
switch (*fp) {
case 's':
fp++;
charp = va_arg(ap, char *);
m = strlen(charp);
break;
case 'u':
fp++;
i = va_arg(ap, uint);
sprintf(digits, "%u", i);
m = strlen(digits);
charp = digits;
break;
case 'x':
fp++;
i = va_arg(ap, uint);
sprintf(digits, "%x", i);
m = strlen(digits);
charp = digits;
break;
case 'd':
fp++;
i = va_arg(ap, int);
sprintf(digits, "%d", i);
m = strlen(digits);
charp = digits;
break;
}
if ((len + m + 1) >= n) {
break;
}
memcpy(bufp, charp, m);
bufp += m;
len += m;
continue;
}
msg[len] = '\0';
/* check we never overwrote the end of the buffer */
if (msg[n-1]) {
abort();
}
va_end(ap);
if (console) {
if (!ostream)
ostream = fopen("/dev/console", "w");
if (ostream) {
if (priority == LOG_ERR)
fprintf(ostream, "Error ");
fprintf(ostream, "%s\n", msg);
} else
syslog(LOG_ERR, "Cannot open /dev/console errno=%d", errno);
}
if (debug) {
int logfd;
logfd = open(logfile, O_CREAT | O_WRONLY | O_APPEND, 0644);
if (logfd >= 0) {
char buf[512];
time_t t = time(NULL);
char *ct = ctime(&t);
ct[24] = '\0';
tac_lockfd(logfile, logfd);
sprintf(buf, "%s [%d]: ", ct, getpid());
write(logfd, buf, strlen(buf));
if (priority == LOG_ERR)
write(logfd, "Error ", 6);
write(logfd, msg, strlen(msg));
write(logfd, "\n", 1);
close(logfd);
}
}
if (single) {
fprintf(stderr, "%s\n", msg);
}
#if 0
/* i wouldnt have frickin turned on debugging if i didnt want to see the data */
if (priority == LOG_DEBUG)
return;
#endif
if (priority == LOG_ERR)
syslog(priority, "Error %s", msg);
else
syslog(priority, "%s", msg);
}
/* format a hex dump for syslog */
void
report_hex(int priority, u_char *p, int len)
{
char buf[256];
char digit[10];
int buflen;
int i;
if (len <= 0)
return;
buf[0] = '\0';
buflen = 0;
for (i = 0; i < len && i < 255; i++, p++) {
sprintf(digit, "0x%x ", *p);
strcat(buf, digit);
buflen += strlen(digit);
if (buflen > 75) {
report(priority, "%s", buf);
buf[0] = '\0';
buflen = 0;
}
}
if (buf[0]) {
report(priority, "%s", buf);
}
return;
}
/* format a non-null terminated string for syslog */
void
report_string(int priority, u_char *p, int len)
{
char buf[256];
char *bufp = buf;
int i;
if (len <= 0)
return;
if(len > 255) len = 255;
for (i = 0; i < len; ) {
if (32 <= *p && *p <= 126) {
*bufp++ = *p++;
i++;
} else {
int n = snprintf(bufp, len-i, " 0x%x ", *p);
bufp += n;
i += n;
p++;
}
}
*bufp = '\0';
report(priority, "%s", buf);
}
void
regerror(char *s)
{
report(LOG_ERR, "in regular expression %s", s);
}
syntax highlighted by Code2HTML, v. 0.9.1