Logo Search packages:      
Sourcecode: aime version File versions  Download package

logs.cpp

/**********************************************************************
 ** Logs class: Maintains all logs, is the superclass of those logs
 **
 **
 **
 ** Last reviewed: version 0.14
 **
 **
 ** Copyright (C) 2000 George Noel (Slate)
 **
 **   This program is free software; you can redistribute it and/or modify
 **   it under the terms of the GNU General Public License as
 **   published by the Free Software Foundation; either version 2 of the 
 **   License, or any later version. 
 **
 **   This program is distributed in the hope that it will be useful, but 
 **   WITHOUT ANY WARRANTY; without even the implied warranty of 
 **   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 **   General Public License for more details. 
 ** 
 **   You should have received a copy of the GNU General Public License 
 **   along with this program (in the docs dir); if not, write to the Free
 **   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 **
 **********************************************************************/

#ifndef LOGS_C
#define LOGS_C

#include "config.h"
#include "sysdep.h"
#include "mudtypes.h"
#include "logs.h"
#include "pager.h"
#include "global.h"
#include "utils.h"
#include "newfuncts.h"
#include "memchk.h"
#include "dirread.h"

/***********************************************************************
 ** Logs (constructor) - Opens the log connection
 **
 ** Parameters: None
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

Logs::Logs()
{
}

/***********************************************************************
 ** open_log - opens a log for appending to 
 **
 ** Parameters: filename - the name of the log file to open 
 **
 ** Returns: 1 if success, -1 if error
 **
 ***********************************************************************/

int Logs::open_log(char *filename)
{
   Strings full_filename;

   if (filename == NULL)
      return -1;

   /* load the filename into the object */
   strncpy(logname, filename, MAXFILENAMELEN);

   full_filename.sprintf("%s%s%s", the_config.basedir.str_show(), DSEP, filename);  
   /* open the filename for business */
   if ((the_log = xfopen(full_filename.str_show(), "a", "log")) == NULL)
   {
      return -1;
   }
   return 1;
}


/***********************************************************************
 ** ~Logs (destructor) - closes the log
 **
 ** Parameters: None
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

Logs::~Logs()
{ 
   xfclose(the_log, "log");
}


/***********************************************************************
 ** display_log - displays entries in the log based on certain criteria
 **
 ** Parameters: the_user - the connection to send stuff to
 **             filename - the filename of the log to check
 **             num_lines - the number of lines to display
 **             keywords - array of keywords to search for
 **             num_keywords - the number of keywords in the array
 **             all - search archived logs as well? 1 - yes, 0 - no
 **             pager_lines - number of lines to display at a shot
 **
 ** Returns: lines displayed for success, -1 for failure
 **
 ***********************************************************************/

int Logs::display_log(Connection *the_user, char *filename, int num_lines,
                         Strings *keyword_str, int all, int pager_lines)
{
   Strings dir_filename;
   int     temp_file_use = 0;
   FILE    *tmp_file = NULL;
   FILE    *writefile = NULL;
   char    *tmp_filename[2] = {LOGTEMPNAME1, LOGTEMPNAME2};
   char    *tmp_str;
   Strings actual_filename;
   char    *tmp_char;
   char    strholder[200];
   Strings *keywords[5];
   Strings holder;
   Strings line_input;
   Strings full_filename;
   DirRead *dirptr = NULL;
   int     num_keywords = 0;
   int     total_lines = 0;
   int     i;

   i = 0;
   keywords[0] = NULL;

   full_filename.sprintf("%s/%s", the_config.basedir.str_show(), filename);  

   /* extract the keywords submitted by the user into an array */
   while ((i<5) &&
          (holder.assign_word(keyword_str->str_show(), i+1) != -1))
   {
      keywords[i] = new Strings(holder.str_show());
      i++;
   }
   num_keywords = i;

   /* if no keywords were found and no lines specified */
   if (((keywords[0] == NULL) || (keywords[0]->str_len() == 0)) &&
        (num_lines == 0))
   {

     /* if this is a suggestions, bug, or typo log, do 20 lines */
      if ((!STRCASECMP(filename, SUGGESTLOGNAME)) ||
          (!STRCASECMP(filename, BUGLOGNAME)) ||
          (!STRCASECMP(filename, TYPOLOGNAME)))
      {
         num_lines = 20;
      }

      /* else do today's entries */
      else
      {
         keywords[0] = new Strings(get_time_str());
         keywords[0]->truncate(7);
       num_keywords = 1;
      }
   }

   /* first if they want archives searched, they must use keywords */   
   if ((all) && ((keywords[0] == NULL) || 
             (keywords[0]->str_len() == 0)))
   {
      the_user->
       send_to_socket("You must supply keywords when searching all logs.\n");
      for (i=0; i<num_keywords; i++)
      delete keywords[i];
      return -1;
   }

   /* if they want archives searched, get a list of archives */
   if (all)
   {
      /* first get just the filename of the logs (no path) */
      tmp_char = filename;
      tmp_str = filename;
      while (*tmp_char)
      {
         if (*tmp_char == '/')
               tmp_str = tmp_char+1;
            tmp_char++; 
      }

      actual_filename = tmp_str;
      tmp_str = actual_filename.str_show();
      while ((*tmp_str) && (*tmp_str != '.'))
      tmp_str++;

      if (*tmp_str)
      *tmp_str = '\0';

      /* now create a list of archived logs to read */
      dir_filename.sprintf("%s%s%s", the_config.basedir.str_show(), DSEP, 
                   LOGARCHIVE);

      dirptr = new DirRead(dir_filename.str_show());

      if (!dirptr->is_valid())
      {
         mainstruct->log_error("Can't read list of archived logs", 
                                                   "display_log");
         for (i=0; i<num_keywords; i++)
         delete keywords[i];
         return -1;
      }
   }          

   /* in all cases, open the current log for reading */
   xfclose(the_log, "log");
   if ((the_log = xfopen(full_filename.str_show(), "r", "the_log")) == NULL)
   {
     holder.sprintf("Can't read %s log", logname);
     if (STRCASECMP(filename, ERRLOGNAME))
        mainstruct->log_error(holder.str_show(), "display_log");
     for (i=0; i<num_keywords; i++)
       delete keywords[i];
     return -1;
   }

   if ((writefile = xfopen(tmp_filename[0], "w", "tmpfile")) == NULL)
   {
      if (STRCASECMP(filename, ERRLOGNAME))
        mainstruct->log_error("Can't open temporary file to write to", 
                                                             "display_log");
      for (i=0; i<num_keywords; i++)
      delete keywords[i];
      return -1;
   }

   total_lines = generate_tempfile(dirptr, writefile, keywords, num_keywords);

   for (i=0; i<num_keywords; i++)
     delete keywords[i];

   /* clean up now and prepare for reading results */
   if (all)
      delete dirptr;
   xfclose(writefile, "tmpfile");
   xfclose(the_log, "the_log");
   if ((tmp_file = xfopen(tmp_filename[0], "r", "tmplog")) == NULL)
   {
     if (STRCASECMP(filename, ERRLOGNAME))
       mainstruct->log_error("Can't read results of search", 
                                                   "display_log");
     return -1;
   }

   if (all)
   {
      dir_filename.sprintf("list.txt");
      unlink(dir_filename.str_show());
   }

   /* find the line we want to start displaying */ 
   if (num_lines != 0)
     for (i=0; i<total_lines - num_lines; i++)
       fgets(strholder, 200, tmp_file);

   /* now we display it via pager */
   the_user->start_paging();
   while ((fgets(strholder, 200, tmp_file)) != NULL)
   {
      line_input = strholder;
      line_input.remove_returns();
      the_user->send_to_socket(line_input.str_show());  
   }
   the_user->end_paging(NULL);

   xfclose(tmp_file, "tmplog");
   dir_filename.sprintf("%s", tmp_filename[0]);
   unlink(dir_filename.str_show());

   /* finally, reopen the log for logging */
   if ((the_log = xfopen(full_filename.str_show(), "a", "log")) == NULL)
   {
      return -1;
   }

   return i;
}


/***********************************************************************
 ** archive_log - archives the current log and opens a new log
 **
 ** Parameters: None
 **
 ** Returns: Nothing
 **
 ***********************************************************************/

int Logs::archive_log(char *filename)
{
   Strings cur_date;
   Strings new_filename;
   Strings sys_com;
   Strings number;
   Strings fromfile;
   Strings tofile;
   char *actual_filename;
   Strings archive_filename;
   int  offset = 0;
   char *str_ptr;
   char modified_date[10];
   int  mod_pos = 0;  
   int  found_opening = 0;
   int  tries = 0;
   FILE *tmp_file = NULL;

   
   str_ptr = filename;
   actual_filename = filename;
   while (*str_ptr)
   {
#ifdef WIN32
     if (*str_ptr == '\\')
#else
     if (*str_ptr == '/')
#endif
        actual_filename = str_ptr + 1;
     str_ptr++;
   }
   
   cur_date = get_time_str();

#ifdef WIN32
   cur_date.truncate(9);
#else
   cur_date.truncate(9);
#endif

   str_ptr = cur_date.str_show();
   str_ptr += 4;

   while (*str_ptr)
   {
      if (*str_ptr != ' ')
      {
         modified_date[mod_pos] = *str_ptr;
         mod_pos++;
      }
      str_ptr++;
   }
   modified_date[mod_pos] = '\0';

   archive_filename = actual_filename;
   actual_filename = archive_filename.str_show();

   while ((*actual_filename) && (*actual_filename != '.'))
     actual_filename++;

   if (!(*actual_filename))
     return -1;

   *actual_filename = '\0';

   if (offset != 0)
     number.sprintf("_%d", offset);
  

   while (!found_opening)
   {
      tries++;

      archive_filename.str_cat(modified_date);

      new_filename.sprintf("%s%s%s%s_%d.txt", the_config.basedir.str_show(),
                 DSEP, LOGARCHIVE, archive_filename.str_show(), tries);

      if ((tmp_file = xfopen(new_filename.str_show(), "r", 
                                               "log_opening_hunter")) == NULL)
         found_opening = 1;
      else
         xfclose(tmp_file, "log_opening_hunter");

      if (tries > 9)
      {
         mainstruct->log_error("Could not archive log after 10 tries.", 
                                                         "archive_log");
         return -1;
      }
   }
   number.sprintf("_%d", tries);
   archive_filename.str_cat(number.str_show());
   archive_filename.str_cat(".txt");

   if (the_log != NULL) 
      xfclose(the_log, "log");

   fromfile.sprintf("%s%s%s", the_config.basedir.str_show(), DSEP, 
                filename);
   tofile.sprintf("%s%s%s%s", the_config.basedir.str_show(), DSEP,
              LOGARCHIVE, archive_filename.str_show(), tries);
#ifdef WIN32
   rename(fromfile.str_show(), tofile.str_show());

#else
   link(fromfile.str_show(), tofile.str_show());
   unlink(fromfile.str_show());
#endif
   return 1;   
}

/***********************************************************************
 ** generate_tempfile - creates a temporary file with the results of the
 **                     search
 **
 ** Parameters: the_dir - the directory to search
 **             writefile - the file to write the results to
 **             keywords - array of keywords to search for
 **             num_keywords - the number of keywords in the array
 **             all - search archived logs as well? 1 - yes, 0 - no
 **
 ** Returns: number of lines in the file for success, -1 for failure
 **
 ***********************************************************************/

int Logs::generate_tempfile(DirRead *the_dir, FILE *writefile, 
                      Strings *keywords[], int num_keywords)
{
  Strings read_filename;
  Strings holder;
  FILE    *logfile = NULL;
  char    logname[129];
  char    *charptr;
  int     total_sum = 0;

  if (the_dir != NULL)
  {
    while ((charptr = the_dir->get_next(".txt")) != NULL)
    {
      /* format the string to a correct filename */
      strncpy(logname, charptr, 128);
      charptr = &logname[0];
      while ((*charptr) && ((*charptr != '\n') && (*charptr != '\0')))
      {
         charptr++;
      }
      if (*charptr)
         *charptr = '\0';
 
      holder.sprintf("%s%s%s%s", the_config.basedir.str_show(),
                 DSEP, LOGARCHIVE, logname); 
                 
      /* open the area file for reading */
      if ((logfile = xfopen(holder.str_show(), "r", "archive_file")) == NULL)
      {
         holder.sprintf("Error - could not open archive log %s file.\n", logname);
         mainstruct->log_error(holder.str_show(), "generate_tempfile");
       return -1;
      }
      
      total_sum += search_logfile(logfile, writefile, keywords, num_keywords);
      xfclose(logfile, "archive_file");
    }
  }
  total_sum += search_logfile(the_log, writefile, keywords, num_keywords);
  return total_sum;
}

/***********************************************************************
 ** search_logfile - searches the logfile for specified keywords or if none
 **                  are specified, just returns the entire file
 **
 ** Parameters: readfile - the filename of the log to check
 **             writefile - the file to write the results to
 **             keywords - array of keywords to search for
 **             num_keywords - the number of keywords in the array
 **
 ** Returns: number of lines in the file for success, -1 for failure
 **
 ***********************************************************************/

int Logs::search_logfile(FILE *readfile, FILE *writefile, Strings *keywords[], 
                   int num_keywords)
{
  char logstr[200];
  int  counter = 0;

  if ((readfile == NULL) || (writefile == NULL))
    return 0;

  while (fgets(logstr, 200, readfile) != NULL)
  {
    if (num_keywords != 0)
    {
      for (int i=0; i<num_keywords; i++)
      {
      if (strstr(logstr, keywords[i]->str_show()) != NULL)
      {
        i = num_keywords;
        fprintf(writefile, "%s", logstr);
        counter++;
      }
      }
    }
    else
    {
      counter++;
      fprintf(writefile, "%s", logstr);
    }
  }
  return counter;
}

/***********************************************************************
 ** is_valid - is the log valid (no errors opening, etc) 
 **
 ** Returns: 1 for valid, 0 for not
 **
 ***********************************************************************/

int Logs::is_valid()
{
  return valid;
}

#endif



Generated by  Doxygen 1.6.0   Back to index