/* 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 #include #include #include #ifdef HAVE_FCNTL_H #include #endif #include #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYSLOG_H #include #endif #ifdef HAVE_SYS_SYSLOG_H #include #endif #include "report.h" #include "utils.h" #include "main.h" /* Configurable: */ #define LOGFILE_DEFAULT "/var/log/tac_plus.log" FILE *ostream = NULL; char *logfile = LOGFILE_DEFAULT; /* 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. */ void report TAC_ARGS((int priority, const char *fmt, ...)) G_GNUC_PRINTF(2, 3); #ifdef __STDC__ #include /* ANSI C, variable length args */ void report(int priority, const char *fmt,...) #else /* __STDC__ */ #include /* has 'vararg' definitions */ /* VARARGS2 */ void report(priority, fmt, va_alist) int priority; const char *fmt; va_dcl /* no terminating semi-colon */ #endif /* __STDC__ */ { char msg[255]; /* temporary string */ const char *fp; char *bufp, *charp = NULL /* GCC paranoia */; int len, m = 0 /* GCC paranoia */, i, n; char digits[16]; va_list ap; #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; default: syslog(LOG_ERR, "Unknown format character '%c', ignoring it", *fp); continue; } 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) { extern int errno; 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, 0640); 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, (int) 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 (priority == LOG_DEBUG) return; if (priority == LOG_ERR) syslog(priority, "Error %s", msg); else syslog(priority, "%s", msg); } void report_hex TAC_ARGS((int priority, u_char *p, int len)); /* format a hex dump for syslog */ void report_hex(priority, p, len) 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); } } void report_string TAC_ARGS((int priority, u_char *p, int len)); /* format a non-null terminated string for syslog */ void report_string(priority, p, len) u_char *p; int len; { char buf[256]; char *bufp = buf; int i; if (len <= 0) return; for (i = 0; i < len && i < 255; i++) { if (32 <= *p && *p <= 126) { *bufp++ = *p++; } else { sprintf(bufp, " 0x%x ", *p); bufp += strlen(bufp); p++; } } *bufp = '\0'; report(priority, "%s", buf); } void tac_regerror TAC_ARGS((const char *s)); void tac_regerror(s) const char *s; { report(LOG_ERR, "in regular expression %s", s); }