/
Crimson2/alias/
Crimson2/area.tmp/
Crimson2/area.tmp/AnomalySpaceDock/
Crimson2/area.tmp/AnomalyStation/
Crimson2/area.tmp/AntHill/
Crimson2/area.tmp/ArcticTerrarium/
Crimson2/area.tmp/BuilderCity/
Crimson2/area.tmp/Dungeon/
Crimson2/area.tmp/MiningDock/
Crimson2/area.tmp/PipeSystem/
Crimson2/area.tmp/RattArea/
Crimson2/area.tmp/RobotFactory/
Crimson2/area.tmp/SilverDale/
Crimson2/area.tmp/StarshipFearless/
Crimson2/area.tmp/StationConduits/
Crimson2/area.tmp/TerrariumAlpha/
Crimson2/area.tmp/TerrariumBeta/
Crimson2/area.tmp/TestArea/
Crimson2/area.tmp/Void/
Crimson2/area/
Crimson2/area/AnomalySpaceDock/
Crimson2/area/AnomalyStation/
Crimson2/area/MiningDock/
Crimson2/area/PipeSystem/
Crimson2/area/SilverDale/
Crimson2/area/StationConduits/
Crimson2/area/Void/
Crimson2/board/
Crimson2/clone/
Crimson2/lib/
Crimson2/mole/
Crimson2/mole/mole_src/HELP/
Crimson2/player/
Crimson2/util/
Crimson2/wldedit/
Crimson2/wldedit/res/
/* Crimson2 Mud Server
 * All source written/copyright Ryan Haksi 1995 *
 * This source code is proprietary. Use in whole or in part without
 * explicity permission by the author is strictly prohibited
 *
 * Current email address(es): cryogen@infoserve.net
 * Phone number: (604) 591-5295
 *
 * C4 Script Language written/copyright Cam Lesiuk 1995
 * Email: clesiuk@engr.uvic.ca
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <sys/types.h> /* for open/fcntl */
#include <sys/stat.h> /* for chmod */
#include <fcntl.h>  /* for fcntl */
#ifndef WIN32
  #include <unistd.h> /* for unlink */
#else
  #include <io.h>
#endif
#include <assert.h>
#include <time.h> /* for time, local time etc */


#include "crimson2.h"
#include "log.h"
#include "macro.h"
#include "mem.h"
#include "queue.h"
#include "str.h"
#include "extra.h"
#include "thing.h"
#include "index.h"
#include "edit.h"
#include "history.h"
#include "socket.h"
#include "send.h"

/*  filename, channel name, echo to console, used to store file descriptor */
LOGF logF[] = {
#ifdef WIN32
  {"log\\port.log"  ,"PRT", TRUE,  0, SP_CHANPORT   },
  {"log\\error.log" ,"ERR", TRUE,  0, SP_CHANERROR  },
  {"log\\boot.log"  ,"BT!", TRUE,  0, 0             },
  {"log\\usage.log", "SYS", TRUE,  0, SP_CHANUSAGE },
  {"log\\god.log"   ,"GOD", TRUE,  0, SP_CHANGOD    },
  {"log\\area.log"  ,"AREA",TRUE,  0, SP_CHANAREA   },
#else
  {"log/port.log"   ,"PRT", TRUE,  0, SP_CHANPORT   },
  {"log/error.log"  ,"ERR", TRUE,  0, SP_CHANERROR  },
  {"log/boot.log"   ,"BT!", TRUE,  0, 0             },
  {"log/usage.log"  ,"SYS", TRUE,  0, SP_CHANUSAGE },
  {"log/god.log"    ,"GOD", TRUE,  0, SP_CHANGOD    },
  {"log/area.log"   ,"AREA",TRUE,  0, SP_CHANAREA   },
#endif
  {""               ,""   , FALSE, 0, 0             }
};
WORD logFMax = 5;

BYTE logStrScreen = TRUE;

/* turf the old boot log */
void LogInit(void) {
  LWORD       i;
  struct stat s;
  BYTE        buf[256];

  printf("Deleting old boot log\n");
  unlink(logF[LOG_BOOT].logFile);

  /* make sure they dont get too big */
  for (i=0; *logF[i].logFile; i++) {

    /* Check if statistics are valid: */
    if( !(stat( logF[i].logFile, &s )) ) {
      if (s.st_size > LOG_SIZE_MAX) {
        #ifdef WIN32
          unlink(logF[i].logFile);
          sprintf(buf, "rename %s %s", logF[i].logFile, logF[i].logFile);
        #else
          sprintf(buf, "mv %s %s", logF[i].logFile, logF[i].logFile);
        #endif
        buf[strlen(buf)-3] = 'o';
        buf[strlen(buf)-2] = 'l';
        buf[strlen(buf)-1] = 'd';
        system(buf);
      }
    }
  }
}

void LogInitDone(void) {
  Log(LOG_BOOT, "Server initialization complete, closing log/boot.log\n");
  if (logF[LOG_BOOT].logDesc) {
    fclose(logF[LOG_BOOT].logDesc);
    logF[LOG_BOOT].logDesc = NULL;
  }
}

/* two log procedures should use non-blocking writes */
void Log(WORD logType, BYTE *logStr) {
  BYTE  buf[128];
  time_t theTime;
  struct tm *theTm;

  logType = BOUNDV(0,logType,logFMax);
  if (logF[logType].logDesc == 0) {
    #ifdef WIN32
      _chmod(logF[logType].logFile, _S_IREAD | _S_IWRITE);
    #endif
    #ifndef WIN32
      chmod(logF[logType].logFile,
        S_IRUSR |
        S_IWUSR |
        S_IRGRP |
        S_IWGRP |
        S_IROTH |
        S_IWOTH
      );
    #endif
    logF[logType].logDesc = fopen(logF[logType].logFile, "a");
    if (logF[logType].logDesc == NULL) {
      PERROR("Log: Failed to Open/Create file");
      exit(ERROR_LOG);
    }
  }
  theTime = time(0);
  theTm = localtime(&theTime);
  sprintf(buf, "%02d/%02d(%02d:%02d) ", theTm->tm_mon+1, theTm->tm_mday, theTm->tm_hour, theTm->tm_min);
  if (buf[6]==' ') buf[6]='0';
  if (buf[9]==' ') buf[9]='0'; /* convert ' 1: 4' to '01:04' */
  fprintf(logF[logType].logDesc, "%s", buf);
  fprintf(logF[logType].logDesc, "%s", logStr);
 
  if(  (logType == LOG_BOOT 
     ||!logF[LOG_BOOT].logDesc)
   && logF[logType].logScreen)
    printf("%s: %s", logF[logType].logChannel, logStr);
  sprintf(buf, "%s: ", logF[logType].logChannel);
  SendChannel(buf, NULL, logF[logType].logChannelFlag);
  SendChannel(logStr, NULL, logF[logType].logChannelFlag);

  /* close the log file */
  if (logType != LOG_BOOT) {
    fclose(logF[logType].logDesc);
    logF[logType].logDesc = NULL;
  }

  if(logType != LOG_BOOT && logF[LOG_BOOT].logDesc)
    Log(LOG_BOOT, logStr);
}

void LogPrintf(WORD logType, BYTE *logStr) {
  logType = BOUNDV(0,logType,logFMax);
  if (logF[logType].logDesc == NULL) {
    #ifdef WIN32
      _chmod(logF[logType].logFile, _S_IREAD | _S_IWRITE);
    #endif
    #ifndef WIN32
      chmod(logF[logType].logFile,
        S_IRUSR |
        S_IWUSR |
        S_IRGRP |
        S_IWGRP |
        S_IROTH |
        S_IWOTH
      );
    #endif
    logF[logType].logDesc = fopen(logF[logType].logFile, "a");
    if (logF[logType].logDesc == NULL) {
      PERROR("LogPrintf");
      exit(ERROR_LOG);
    }
  }
  fprintf(logF[logType].logDesc, "%s", logStr);

  if(  (logType == LOG_BOOT 
     ||!logF[LOG_BOOT].logDesc)
   && logF[logType].logScreen)
    printf("%s", logStr);
  SendChannel(logStr, NULL, logF[logType].logChannelFlag);

  /* close the log file */
  if (logType != LOG_BOOT) {
    fclose(logF[logType].logDesc);
    logF[logType].logDesc = NULL;
  }

  if(logType != LOG_BOOT && logF[LOG_BOOT].logDesc)
    LogPrintf(LOG_BOOT, logStr);
}


void LogStr(BYTE *logName, BYTE *logStr) {
  FILE  *logFile;
  BYTE   buf[128];
  BYTE   fileName[256];
  time_t theTime;
  struct tm *theTm;

  if (logStrScreen)
    printf("%s: %s", logName, logStr);
  sprintf(fileName, "log/%s.log", logName);
  sprintf(buf, "%s: ", logName);
  SendChannel(buf, NULL, SP_CHANSPY);
  SendChannel(logStr, NULL, SP_CHANSPY);
  logFile = fopen(fileName, "a");
  if (logFile) {
    theTime = time(0);
    theTm = localtime(&theTime);
    sprintf(buf, "%02d/%02d(%02d:%02d) ", theTm->tm_mon+1, theTm->tm_mday, theTm->tm_hour, theTm->tm_min);
    if (buf[6]==' ') buf[6]='0';
    if (buf[9]==' ') buf[9]='0'; /* convert ' 1: 4' to '01:04' */
    fprintf(logFile, "%s: %s", buf, logStr);
    fclose(logFile);
  }
}

void LogStrPrintf(BYTE *logName, BYTE *logStr) {
  FILE *logFile;
  BYTE  fileName[256];

  if (logStrScreen)
    printf("%s", logStr);
  SendChannel(logStr, NULL, SP_CHANSPY);
  sprintf(fileName, "log/%s.log", logName);
  logFile = fopen(fileName, "a");
  if (logFile) {
    fprintf(logFile, "%s", logStr);
    fclose(logFile);
  }
}