socketmud/doc/
socketmud/help/
/*
 * This file handles input/output to files (including log)
 */
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>  
#include <sys/stat.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <stdlib.h>

/* include main header file */
#include "mud.h"

extern FILE *stderr;
time_t current_time;

/*
 * Nifty little extendable logfunction,
 * if it wasn't for Erwins social editor,
 * I would never have known about the
 * va_ functions.
 */
void log_string(const char *txt, ...)
{
  FILE *fp;
  char logfile[MAX_BUFFER];
  char buf[MAX_BUFFER];
  char *strtime = get_time();
  va_list args;

  va_start(args, txt);
  vsprintf(buf, txt, args);
  va_end(args);

  /* point to the correct logfile */
  sprintf(logfile, "../log/%6.6s.log", strtime);

  /* try to open logfile */
  if ((fp = fopen(logfile, "a")) == NULL)
  {
    communicate(NULL, "log: cannot open logfile", COMM_LOG);
    return;
  }

  fprintf(fp, "%s: %s\n", strtime, buf);
  fclose(fp);

  communicate(NULL, buf, COMM_LOG);
}

/*
 * Nifty little extendable bugfunction,
 * if it wasn't for Erwins social editor,
 * I would never have known about the
 * va_ functions.
 */
void bug(const char *txt, ...)
{
  FILE *fp;
  char buf[MAX_BUFFER];
  va_list args;
  char *strtime = get_time();

  va_start(args, txt);
  vsprintf(buf, txt, args);
  va_end(args);

  /* try to open logfile */
  if ((fp = fopen("../log/bugs.txt", "a")) == NULL)
  {
    communicate(NULL, "bug: cannot open bugfile", COMM_LOG);
    return;
  }

  fprintf(fp, "%s: %s\n", strtime, buf);
  fclose(fp);

  communicate(NULL, buf, COMM_LOG);
}

/*
 * This function will return the time of
 * the last modification made to helpfile.
 */
time_t last_modified(char *helpfile)
{
  char fHelp[256];
  struct stat sBuf;
  time_t mTime = 0;

  sprintf(fHelp, "../help/%s", helpfile);
  if (stat(fHelp, &sBuf) >= 0)
    mTime = sBuf.st_mtime;

  return mTime;
}

char *read_help_entry(const char *helpfile)
{
  FILE *fp;
  static char entry[MAX_HELP_ENTRY];
  char fHelp[256];
  int c, ptr = 0;

  /* location of the help file */
  sprintf(fHelp, "../help/%s", helpfile);

  /* if there is no help file, return NULL */
  if ((fp = fopen(fHelp, "r")) == NULL)
    return NULL;

  /* just to have something to work with */
  c = getc(fp);

  /* read the file in the buffer */
  while (c != EOF)
  {
    if (c == '\n')
      entry[ptr++] = '\r';
    entry[ptr] = c;
    if (++ptr > MAX_BUFFER - 2)
    {
      bug("Read_help_entry: String to long.");
      abort();
    }
    c = getc(fp);
  }
  entry[ptr] = '\0';

  fclose(fp);

  /* return a pointer to the static buffer */
  return entry;
}

/*
 * Reads one line from a file, and returns a
 * pointer to a _static array_ holding the line.
 */
char *fread_line(FILE *fp)
{
  static char line[MAX_BUFFER];
  int c, entry = 0;

  /* read one line from the file */
  c = getc(fp);
  while (c != EOF && c != '\n')
  {
    line[entry] = c;
    if (++entry > MAX_BUFFER - 1)
    {
      bug("Fread_line: Line to long.");
      abort();
    }
    c = getc(fp);
  }
  line[entry] = '\0';

  /* did we actually read anything ? */
  if (entry == 0) return NULL;

  /* return a pointer to the static buffer */
  return line;
}

/*
 * Reads one number from a file, returning
 * the value as an integer, a leading '-' will
 * be intepreted as a negative value, and this
 * is the only non-digit that the function
 * will not choke and die upon reading.
 */
int fread_number(FILE *fp)
{
  int c, number = 0;
  bool negative = FALSE;

  /* initial read */
  c = getc(fp);

  /* speed through leading spaces */
  while (c != EOF && (c == ' ' || c == '\n'))
    c = getc(fp);

  /* so what did we get ? */
  if (c == EOF)
  {
    bug("Fread_number: EOF encountered.");
    abort();
  }
  else if (c == '-')
    negative = TRUE;
  else if (!isdigit(c))
  {
    bug("Fread_number: Not a number.");
    abort();
  }
  else
    number = c - '0';

  /* keep counting up */
  while (isdigit(c = getc(fp)))
    number = number * 10 + c - '0';

  /* push back the non-digit */
  ungetc(c, fp);

  /* we have a number */
  return (negative ? (0 - number) : number);
}

/*
 * Reads one full block of text, which ends with a
 * '~' (tilde). The result will be copied into an
 * allocated buffer and a pointer to that buffer
 * will be returned. Remember to free the memory when
 * you are done using it.
 */
char *fread_string(FILE *fp)
{
  char buf[4 * MAX_BUFFER];
  int c, count = 0;

  /* initial read */
  c = getc(fp);

  /* speed through leading spaces */
  while (c != EOF && (c == ' ' || c == '\n'))
    c = getc(fp);

  /* better not have reached the end of the file */
  if (c == EOF)
  {
    bug("Fread_string: EOF encountered.");
    abort();
  }

  /* and keep reading */
  while (c != EOF && c != '~')
  {
    if (c == '\n')
    {
      buf[count++] = '\r';
      buf[count] = '\n';
    }
    else if (c == '\r')
    {
      c = getc(fp);
      continue;
    }
    else buf[count] = c;
    if (++count > (4 * MAX_BUFFER - 2))
    {
      bug("Fread_string: String to long.");
      abort();
    }
    c = getc(fp);
  }
  buf[count] = '\0';

  if (c == EOF)
    bug("Fread_string: Non-fatal error, encountered EOF instead of ~.");

  return strdup(buf);
}

/*
 * Reads one single word, ending with the first
 * encountered space ' '. Any leading spaces will
 * be ignored, and the result will be copied into
 * a static buffer, and a pointer to that buffer
 * will be returned.
 */
char *fread_word(FILE *fp)
{
  static char buf[MAX_BUFFER];
  int c, count = 0;

  /* initial read */
  c = getc(fp); 

  /* speed through leading spaces and linebreaks */
  while (c != EOF && (c == ' ' || c == '\n'))
    c = getc(fp);

  /* better not have reached the end of the file */
  if (c == EOF)
  {
    bug("Fread_word: EOF encountered.");
    abort();
  }

  /* and keep reading */
  while (c != EOF && c != ' ' && c != '\n')
  {
    buf[count] = c;
    if (++count > MAX_BUFFER - 1)
    {
      bug("Fread_word: Word to long.");
      abort();
    }
    c = getc(fp);
  }
  buf[count] = '\0';

  /* push back the last read if it was EOF */
  if (c == EOF) ungetc(c, fp);

  return buf;
}