pennmush/game/
pennmush/game/data/
pennmush/game/log/
pennmush/game/save/
pennmush/game/txt/evt/
pennmush/game/txt/nws/
pennmush/os2/
/* log.c */

#include "copyrite.h"
#include "config.h"

#include <stdio.h>
#ifdef I_STRING
#include <string.h>
#else
#include <strings.h>
#endif
#ifdef I_STDARG
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#ifdef I_SYS_TIME
#include <sys/time.h>
#else
#include <time.h>
#endif
#ifdef I_SYS_TYPES
#include <sys/types.h>
#endif

#include "conf.h"
#include "externs.h"
#include "intrface.h"
#include "confmagic.h"

char *quick_unparse _((dbref object));
void start_log _((FILE ** fp, const char *filename));
void end_log _((FILE * fp));
void do_rawlog _((int logtype, const char *fmt,...));


char *
quick_unparse(object)
    dbref object;
{
  static char buff[BUFFER_LEN];

  switch (object) {
  case NOTHING:
    sprintf(buff, "*NOTHING*");
    break;
  case AMBIGUOUS:
    sprintf(buff, "*VARIABLE*");
    break;
  case HOME:
    sprintf(buff, "*HOME*");
    break;
  default:
    sprintf(buff, "%s(#%d%s)",
	    Name(object), object, unparse_flags(object, GOD));
  }

  return buff;
}

void
start_log(fp, filename)
    FILE **fp;
    const char *filename;
{
  *fp = fopen(filename, "a");
  if (*fp == NULL) {
    fprintf(stderr, "WARNING: cannot open log %s\n", filename);
    *fp = stderr;
  }
  fprintf(*fp, "START OF LOG.\n");
  fflush(*fp);
}

void
end_log(fp)
    FILE *fp;
{
  if (fp != stderr) {
    fprintf(fp, "END OF LOG.\n");
    fflush(fp);
    fclose(fp);
  }
}

#ifdef I_STDARG
void
do_rawlog(int logtype, const char *fmt,...)
#else
void
do_rawlog(logtype, va_alist)
    int logtype;
    va_dcl
#endif
{
  /* take a log type and format list and args, write to appropriate logfile.
   * log types are defined in mushdb.h
   */

  time_t tt;
  struct tm *ttm;
  char timebuf[16];
  char tbuf1[BUFFER_LEN + 50];
  va_list args;
  FILE *f = NULL;
#ifndef I_STDARG
  char *fmt;

  va_start(args);
  fmt = va_arg(args, char *);
#else
  va_start(args, fmt);
#endif
  (void) vsprintf(tbuf1, fmt, args);
  va_end(args);

  time(&tt);
  ttm = localtime(&tt);
  sprintf(timebuf, "%d%d/%d%d %d%d:%d%d:%d%d",
	  (((ttm->tm_mon) + 1) / 10), (((ttm->tm_mon) + 1) % 10),
	  (ttm->tm_mday / 10), (ttm->tm_mday % 10),
	  (ttm->tm_hour / 10), (ttm->tm_hour % 10),
	  (ttm->tm_min / 10), (ttm->tm_min % 10),
	  (ttm->tm_sec / 10), (ttm->tm_sec % 10));

  switch (logtype) {
  case LT_ERR:
    f = stderr;
    break;
  case LT_CMD:
    f = cmdlog_fp;
    break;
  case LT_WIZ:
    f = wizlog_fp;
    break;
  case LT_CONN:
    f = connlog_fp;
    break;
  case LT_TRACE:
    f = tracelog_fp;
    break;
  case LT_RPAGE:
    break;
  case LT_CHECK:
    f = checklog_fp;
    break;
  case LT_HUH:
    f = cmdlog_fp;
    break;
  default:
    f = stderr;
    break;
  }
  fprintf(f, "%s  %s\n", timebuf, tbuf1);
  fflush(f);
}

#ifdef I_STDARG
void
do_log(int logtype, dbref player, dbref object, const char *fmt,...)
#else
void
do_log(logtype, player, object, va_alist)
    int logtype;
    dbref player;
    dbref object;
    va_dcl
#endif
{
  /* take a log type and format list and args, write to appropriate logfile.
   * log types are defined in mushdb.h
   */

  /* tbuf1 had 50 extra chars because we might pass this function
   * both a label string and a command which could be up to BUFFER_LEN
   * in length - for example, when logging @forces
   */
  char tbuf1[BUFFER_LEN + 50];
  va_list args;
  char unp1[BUFFER_LEN], unp2[BUFFER_LEN];
#ifndef I_STDARG
  char *fmt;

  va_start(args);
  fmt = va_arg(args, char *);
#else
  va_start(args, fmt);
#endif
  (void) vsprintf(tbuf1, fmt, args);
  va_end(args);

  switch (logtype) {
  case LT_ERR:
    do_rawlog(logtype, "RPT: %s", tbuf1);
    break;
  case LT_CMD:
    if (options.log_commands) {
      strcpy(unp1, quick_unparse(player));
      strcpy(unp2, quick_unparse(Location(player)));
      if (Suspect(player))
	do_rawlog(logtype, "CMD: SUSPECT %s in %s: %s", unp1, unp2, tbuf1);
      else
	do_rawlog(logtype, "CMD: %s in %s: %s", unp1, unp2, tbuf1);
    } else {
      if (Suspect(player)) {
	strcpy(unp1, quick_unparse(player));
	strcpy(unp2, quick_unparse(Location(player)));
	do_rawlog(logtype, "CMD: SUSPECT %s in %s: %s", unp1, unp2, tbuf1);
      }
    }
    break;
  case LT_WIZ:
    strcpy(unp1, quick_unparse(player));
    if (GoodObject(object)) {
      strcpy(unp2, quick_unparse(object));
      do_rawlog(logtype, "WIZ: %s --> %s: %s", unp1, unp2, tbuf1);
    } else {
      do_rawlog(logtype, "WIZ: %s: %s", unp1, tbuf1);
    }
    break;
  case LT_CONN:
    do_rawlog(logtype, "NET: %s", tbuf1);
    break;
  case LT_TRACE:
    break;
  case LT_RPAGE:
    break;
  case LT_CHECK:
    do_rawlog(logtype, "%s", tbuf1);
    break;
  case LT_HUH:
    if (!controls(player, Location(player))) {
      strcpy(unp1, quick_unparse(player));
      strcpy(unp2, quick_unparse(Location(player)));
      do_rawlog(logtype, "HUH: %s in %s [%s]: %s",
		unp1, unp2,
	 (GoodObject(Location(player))) ? Name(Owner(Location(player))) :
		"bad object", tbuf1);
    }
    break;
  default:
    do_rawlog(LT_ERR, "ERR: %s", tbuf1);
  }
}

#ifdef LOG_WIPES_OKAY
void
do_logwipe(player, log_name, str)
    dbref player;
    char *log_name;
    char *str;
{
  /* Wipe out a game log. This is intended for those emergencies where
   * the log has grown out of bounds, overflowing the disk quota, etc.
   * Because someone with the god password can use this command to wipe
   * out 'intrusion' traces, we also require the log_wipe_passwd given
   * in mush.cnf
   */

  if (!God(player)) {
    notify(player, "Permission denied.");
    return;
  }
  if (strcmp(str, LOG_WIPE_PASSWD)) {
    do_log(LT_WIZ, player, NOTHING,
	   "Invalid attempt to wipe log %s, password %s");
    return;
  }
  if (!strcasecmp(log_name, "connect")) {
    end_log(connlog_fp);
    unlink(CONNLOG);
    start_log(&connlog_fp, CONNLOG);
  } else if (!strcasecmp(log_name, "checkpoint")) {
    end_log(checklog_fp);
    unlink(CHECKLOG);
    start_log(&checklog_fp, CHECKLOG);
  } else if (!strcasecmp(log_name, "command")) {
    end_log(cmdlog_fp);
    unlink(CMDLOG);
    start_log(&cmdlog_fp, CMDLOG);
  } else if (!strcasecmp(log_name, "trace")) {
    end_log(tracelog_fp);
    unlink(TRACELOG);
    start_log(&tracelog_fp, TRACELOG);
  } else if (!strcasecmp(log_name, "wizard")) {
    endlog(wizlog_fp);
    unlink(WIZLOG);
    start_log(&wizlog_fp, WIZLOG);
  } else {
    notify(player, "That is not a valid log.");
    return;
  }
  do_log(LT_ERR, player, NOTHING, "Log wiped: %s", log_name);
  notify(player, "Log wiped.");
}
#endif				/* LOG_WIPES_OKAY */