/* log.c - logging routines */
/* $Id: log.c,v 1.27 2003/01/31 03:17:40 rmg Exp $ */
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include "alloc.h" /* required by mudconf */
#include "flags.h" /* required by mudconf */
#include "htab.h" /* required by mudconf */
#include "mudconf.h" /* required by code */
#include "db.h" /* required by externs */
#include "externs.h" /* required by code */
#include "ansi.h" /* required by code */
FILE *mainlog_fp;
static FILE *log_fp = NULL;
/* *INDENT-OFF* */
NAMETAB logdata_nametab[] = {
{(char *)"flags", 1, 0, LOGOPT_FLAGS},
{(char *)"location", 1, 0, LOGOPT_LOC},
{(char *)"owner", 1, 0, LOGOPT_OWNER},
{(char *)"timestamp", 1, 0, LOGOPT_TIMESTAMP},
{ NULL, 0, 0, 0}};
NAMETAB logoptions_nametab[] = {
{(char *)"accounting", 2, 0, LOG_ACCOUNTING},
{(char *)"all_commands", 2, 0, LOG_ALLCOMMANDS},
{(char *)"bad_commands", 2, 0, LOG_BADCOMMANDS},
{(char *)"buffer_alloc", 3, 0, LOG_ALLOCATE},
{(char *)"bugs", 3, 0, LOG_BUGS},
{(char *)"checkpoints", 2, 0, LOG_DBSAVES},
{(char *)"config_changes", 2, 0, LOG_CONFIGMODS},
{(char *)"create", 2, 0, LOG_PCREATES},
{(char *)"keyboard_commands", 2, 0, LOG_KBCOMMANDS},
{(char *)"killing", 1, 0, LOG_KILLS},
{(char *)"local", 3, 0, LOG_LOCAL},
{(char *)"logins", 3, 0, LOG_LOGIN},
{(char *)"network", 1, 0, LOG_NET},
{(char *)"problems", 1, 0, LOG_PROBLEMS},
{(char *)"security", 2, 0, LOG_SECURITY},
{(char *)"shouts", 2, 0, LOG_SHOUTS},
{(char *)"startup", 2, 0, LOG_STARTUP},
{(char *)"suspect_commands", 2, 0, LOG_SUSPECTCMDS},
{(char *)"time_usage", 1, 0, LOG_TIMEUSE},
{(char *)"wizard", 1, 0, LOG_WIZARD},
{ NULL, 0, 0, 0}};
LOGFILETAB logfds_table[] = {
{ LOG_ACCOUNTING, NULL, NULL},
{ LOG_ALLCOMMANDS, NULL, NULL},
{ LOG_BADCOMMANDS, NULL, NULL},
{ LOG_ALLOCATE, NULL, NULL},
{ LOG_BUGS, NULL, NULL},
{ LOG_DBSAVES, NULL, NULL},
{ LOG_CONFIGMODS, NULL, NULL},
{ LOG_PCREATES, NULL, NULL},
{ LOG_KBCOMMANDS, NULL, NULL},
{ LOG_KILLS, NULL, NULL},
{ LOG_LOCAL, NULL, NULL},
{ LOG_LOGIN, NULL, NULL},
{ LOG_NET, NULL, NULL},
{ LOG_PROBLEMS, NULL, NULL},
{ LOG_SECURITY, NULL, NULL},
{ LOG_SHOUTS, NULL, NULL},
{ LOG_STARTUP, NULL, NULL},
{ LOG_SUSPECTCMDS, NULL, NULL},
{ LOG_TIMEUSE, NULL, NULL},
{ LOG_WIZARD, NULL, NULL},
{ 0, NULL, NULL}};
/* *INDENT-ON* */
/* ---------------------------------------------------------------------------
* logfile_init: Initialize the main logfile.
*/
void logfile_init(filename)
char *filename;
{
if (!filename) {
mainlog_fp = stderr;
return;
}
mainlog_fp = fopen(filename, "w");
if (!mainlog_fp) {
fprintf(stderr, "Could not open logfile %s for writing.\n",
filename);
mainlog_fp = stderr;
return;
}
setbuf(mainlog_fp, NULL); /* unbuffered */
}
/* ---------------------------------------------------------------------------
* start_log: see if it is OK to log something, and if so, start writing the
* log entry.
*/
int start_log(primary, secondary, key)
const char *primary, *secondary;
int key;
{
struct tm *tp;
time_t now;
LOGFILETAB *lp;
static int last_key = 0;
if (!mudstate.standalone) {
if (mudconf.log_diversion & key) {
if (key != last_key) {
/* Try to save ourselves some lookups */
last_key = key;
for (lp = logfds_table; lp->log_flag; lp++) {
/* Though keys can be OR'd, use the first one
* matched
*/
if (lp->log_flag & key) {
log_fp = lp->fileptr;
break;
}
}
if (!log_fp)
log_fp = mainlog_fp;
}
} else {
last_key = key;
log_fp = mainlog_fp;
}
} else {
log_fp = mainlog_fp;
}
mudstate.logging++;
switch (mudstate.logging) {
case 1:
case 2:
if (!mudstate.standalone) {
/* Format the timestamp */
if ((mudconf.log_info & LOGOPT_TIMESTAMP) != 0) {
time((time_t *) (&now));
tp = localtime((time_t *) (&now));
fprintf(log_fp, "%02d%02d%02d.%02d%02d%02d ",
(tp->tm_year % 100), tp->tm_mon + 1,
tp->tm_mday, tp->tm_hour,
tp->tm_min, tp->tm_sec);
}
/* Write the header to the log */
if (secondary && *secondary)
fprintf(log_fp, "%s %3s/%-5s: ",
mudconf.mud_name, primary, secondary);
else
fprintf(log_fp, "%s %-9s: ",
mudconf.mud_name, primary);
}
/* If a recursive call, log it and return indicating no log */
if (mudstate.logging == 1)
return 1;
fprintf(mainlog_fp, "Recursive logging request.\r\n");
default:
mudstate.logging--;
}
return 0;
}
/* ---------------------------------------------------------------------------
* end_log: Finish up writing a log entry
*/
void NDECL(end_log)
{
fprintf(log_fp, "\n");
fflush(log_fp);
mudstate.logging--;
}
/* ---------------------------------------------------------------------------
* log_perror: Write perror message to the log
*/
void log_perror(primary, secondary, extra, failing_object)
const char *primary, *secondary, *extra, *failing_object;
{
int my_errno = errno;
start_log(primary, secondary, LOG_ALWAYS);
if (extra && *extra) {
log_printf("(%s) ", extra);
}
log_printf("%s: %s", failing_object, strerror(my_errno));
end_log();
}
/* ---------------------------------------------------------------------------
* log_printf: Format text and print to the log file.
*/
#if defined(__STDC__) && defined(STDC_HEADERS)
void log_printf(const char *format,...)
#else
void log_printf(va_alist)
va_dcl
#endif
{
va_list ap;
#if defined(__STDC__) && defined(STDC_HEADERS)
va_start(ap, format);
#else
char *format;
va_start(ap);
format = va_arg(ap, char *);
#endif
vfprintf(log_fp, format, ap);
va_end(ap);
}
void log_vprintf(format, ap)
const char *format;
va_list ap;
{
vfprintf(log_fp, format, ap);
}
/* ---------------------------------------------------------------------------
* log_name: write the name, db number, and flags of an object to the log.
* If the object does not own itself, append the name, db number, and flags
* of the owner.
*/
void log_name(target)
dbref target;
{
char *tp;
if (mudstate.standalone) {
fprintf(stderr, "%s(#%d)", Name(target), target);
return;
}
if ((mudconf.log_info & LOGOPT_FLAGS) != 0)
tp = unparse_object((dbref) GOD, target, 0);
else
tp = unparse_object_numonly(target);
fprintf(log_fp, "%s", strip_ansi(tp));
free_lbuf(tp);
if (((mudconf.log_info & LOGOPT_OWNER) != 0) &&
(target != Owner(target))) {
if ((mudconf.log_info & LOGOPT_FLAGS) != 0)
tp = unparse_object((dbref) GOD, Owner(target), 0);
else
tp = unparse_object_numonly(Owner(target));
fprintf(log_fp, "[%s]", strip_ansi(tp));
free_lbuf(tp);
}
return;
}
/* ---------------------------------------------------------------------------
* log_name_and_loc: Log both the name and location of an object
*/
void log_name_and_loc(player)
dbref player;
{
log_name(player);
if ((mudconf.log_info & LOGOPT_LOC) && Has_location(player)) {
log_printf(" in ");
log_name(Location(player));
}
}
char *OBJTYP(thing)
dbref thing;
{
if (!Good_dbref(thing)) {
return (char *)"??OUT-OF-RANGE??";
}
switch (Typeof(thing)) {
case TYPE_PLAYER:
return (char *)"PLAYER";
case TYPE_THING:
return (char *)"THING";
case TYPE_ROOM:
return (char *)"ROOM";
case TYPE_EXIT:
return (char *)"EXIT";
case TYPE_GARBAGE:
return (char *)"GARBAGE";
default:
return (char *)"??ILLEGAL??";
}
}
void log_type_and_name(thing)
dbref thing;
{
log_printf("%s ", OBJTYP(thing));
log_name(thing);
}