]> jfr.im git - irc/evilnet/x3.git/blobdiff - src/log.c
fixing small memory leak
[irc/evilnet/x3.git] / src / log.c
index 5c51923e343583d0252a169ba818d821c97973b9..ef531ee4363bd2020cebdd17564ebbd90cc5eb92 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -1,9 +1,9 @@
 /* log.c - Diagnostic and error logging
  * Copyright 2000-2004 srvx Development Team
  *
- * This file is part of srvx.
+ * This file is part of x3.
  *
- * srvx is free software; you can redistribute it and/or modify
+ * x3 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
  * (at your option) any later version.
 
 #include "conf.h"
 #include "log.h"
+#include "modcmd.h"
 #include "helpfile.h" /* send_message, message_register, etc */
 #include "nickserv.h"
 
+#define Block  4096
+#define MAXLOGSEARCHLENGTH 10000
+
+struct userNode *chanserv;
 struct logDestination;
 
 struct logDest_vtable {
@@ -78,6 +83,15 @@ static void log_format_audit(struct logEntry *entry);
 static const struct message_entry msgtab[] = {
     { "MSG_INVALID_FACILITY", "$b%s$b is an invalid log facility." },
     { "MSG_INVALID_SEVERITY", "$b%s$b is an invalid severity level." },
+
+    { "LAST_RESULTS",     "$b%s$b] %s %s $b%s$b %s" },
+    { "LAST_ERROR",       "%s:%s" },
+    { "LAST_COMMAND_LOG", "Channel Events for %s" },
+    { "LAST_LINE",        "----------------------------------------" },
+    { "LAST_STOPPING_AT", "--------- Stopping at %d lines ---------" },
+    { "LAST_MAX_AGE",     "-------- Data age limit reached --------" },
+    { "LAST_END_OF_LOG",  "---------- Found %d Matches ------------" },
+
     { NULL, NULL }
 };
 
@@ -527,7 +541,7 @@ log_audit(struct log_type *type, enum log_severity sev, struct userNode *user, s
     /* remove old elements from the linked list */
     while (type->log_count > type->max_count)
         log_type_free_oldest(type);
-    while (type->log_oldest && (type->log_oldest->time + type->max_age < (unsigned long)now))
+    while (type->log_oldest && (type->log_oldest->time + (time_t)type->max_age < now))
         log_type_free_oldest(type);
     if (type->log_oldest)
         type->log_oldest->prev = 0;
@@ -588,7 +602,7 @@ log_module(struct log_type *type, enum log_severity sev, const char *format, ...
         fprintf(stderr, "%s: %s\n", log_severity_names[sev], msgbuf);
     }
     if (sev == LOG_FATAL) {
-        assert(0 && "fatal message logged");
+        //assert(0 && "fatal message logged");
         _exit(1);
     }
 }
@@ -955,14 +969,17 @@ ldIrc_close(struct logDestination *self_) {
     free(self);
 }
 
+/* 
+ * ldIrc_audit and ldIrc_module send log messages targetted to an IRC channel, to the channel
+ */
 static void
 ldIrc_audit(struct logDestination *self_, UNUSED_ARG(struct log_type *type), struct logEntry *entry) {
     struct logDest_irc *self = (struct logDest_irc*)self_;
 
     if (entry->channel_name) {
-        send_target_message(4, self->target, entry->bot, "(%s", strchr(strchr(entry->default_desc, ' '), ':')+1);
+        send_target_message(5, self->target, entry->bot, "(%s", strchr(strchr(entry->default_desc, ' '), ':')+1);
     } else {
-        send_target_message(4, self->target, entry->bot, "%s", strchr(entry->default_desc, ')')+2);
+        send_target_message(5, self->target, entry->bot, "%s", strchr(entry->default_desc, ')')+2);
     }
 }
 
@@ -971,7 +988,7 @@ ldIrc_module(struct logDestination *self_, struct log_type *type, enum log_sever
     struct logDest_irc *self = (struct logDest_irc*)self_;
     extern struct userNode *opserv;
 
-    send_target_message(4, self->target, opserv, "%s %s: %s\n", type->name, log_severity_names[sev], message);
+    send_target_message(5, self->target, opserv, "%s %s: %s\n", type->name, log_severity_names[sev], message);
 }
 
 static struct logDest_vtable ldIrc_vtbl = {
@@ -1029,3 +1046,210 @@ void SyncLog(char *fmt,...)
   }
 
 }
+
+int parselog(char *LogLine, struct userNode *user, struct chanNode *cptr, char *chan, char *nuh, char *command, char *rest)
+{
+   struct svccmd *svccmd;
+   struct svccmd *cmd;
+   struct service *service;
+   const  char *info;
+   char   serv[NICKLEN+1];
+   char   buf[MAXLEN];
+   char   myservc[MAXLEN];
+   char*  mychan;
+   char*  mynuh;
+   char* mycommand;
+   char*  myrest;
+   char*  datestr;
+   char*  mywho;
+   char *myserv;
+   char* myserva;
+   char*  mychana;
+   unsigned int pos;
+   int p = 0;
+
+   datestr =   (char *) mysep(&LogLine, "]");
+   mywho =     (char *) mysep(&LogLine, " ");
+   mynuh =     (char *) mysep(&LogLine, " ");
+   mycommand = (char *) mysep(&LogLine, " ");
+   myrest =    (char *) mysep(&LogLine, "\0");
+   myserva =   (char *) mysep(&mywho, ":");
+   mychana =   (char *) mysep(&mywho, ":");
+   myserv =    (char *) mysep(&myserva, "(");
+   mychan =    (char *) mysep(&mychana, ")");
+
+   if(!mycommand)
+       return 0;
+
+   if(cptr)
+      chan = cptr->name;
+
+   if (!mychan)
+     mychan = "";
+
+   if(!chan)
+     chan = "";
+
+   if(!nuh)
+      nuh = "";
+   if(!command)
+      command = "";
+   if(!rest)
+      rest = "";
+   if(*chan && strcasecmp(mychan, chan))
+        return 0;
+   if(!myrest)
+      myrest = "";
+
+   info = conf_get_data("services/opserv/nick", RECDB_QSTRING);
+
+   if (!myserv)
+      myserv = "";
+   else
+     strcpy(myservc, myserv);
+
+
+   if (!strcmp(myserv, info)) {
+      if (!IsOper(user))
+        return 0;
+      else {
+        if ((service = service_find(myserv))) {
+          if (!(cmd = dict_find(service->commands, mycommand, NULL)))
+            return 0;
+
+          if (!(svccmd = svccmd_resolve_name(cmd, mycommand)))
+            return 0;
+
+          pos = snprintf(buf, sizeof(buf), "%s.%s", svccmd->command->parent->name, svccmd->command->name);
+
+          if (svccmd->alias.used) {
+              buf[pos++] = ' ';
+              unsplit_string((char**)svccmd->alias.list+1, svccmd->alias.used-1, buf+pos);
+          }
+        }
+      }
+
+      if (!(strcmp(buf+0, "OpServ.OP")))
+         p = 1;
+      if (!(strcmp(buf+0, "OpServ.DEOP")))
+         p = 1;
+      if (!(strcmp(buf+0, "OpServ.VOICE")))
+         p = 1;
+      if (!(strcmp(buf+0, "OpServ.DEVOICE")))
+         p = 1;
+      if (!(strcmp(buf+0, "OpServ.KICK")))
+         p = 1;
+      if (!(strcmp(buf+0, "OpServ.KICKBAN")))
+         p = 1;
+
+      if (!(strcmp(buf+0, "OpServ.OPALL")))
+         p = 1;
+      if (!(strcmp(buf+0, "OpServ.DEOPALL")))
+         p = 1;
+      if (!(strcmp(buf+0, "OpServ.VOICEALL")))
+         p = 1;
+      if (!(strcmp(buf+0, "OpServ.DEVOICEALL")))
+         p = 1;
+      if (!(strcmp(buf+0, "OpServ.KICKALL")))
+         p = 1;
+      if (!(strcmp(buf+0, "OpServ.KICKBANALL")))
+         p = 1;
+
+
+      if (!(strcmp(buf+0, "OpServ.INVITE")))
+         p = 1;
+      if (!(strcmp(buf+0, "OpServ.INVITEME")))
+         p = 1;
+      if (!(strcmp(buf+0, "OpServ.CLEARBANS")))
+         p = 1;
+      if (!(strcmp(buf+0, "OpServ.CLEARMODES")))
+         p = 1;
+
+      if (p == 1)
+        send_message(user, chanserv, "LAST_RESULTS", datestr, myserv, mynuh, mycommand, myrest);
+
+      p = 0;
+    } else {
+      sprintf(serv, "%s", "");
+      send_message(user, chanserv, "LAST_RESULTS", datestr, serv, mynuh, mycommand, myrest);
+    }
+
+   return 1;
+
+}
+
+int ShowLog(struct userNode *user, struct chanNode *cptr, char *chan, char *nuh, char *command, char *rest, int maxlines)
+{
+   FILE *TheFile;
+   int i, s, Last = 0, filelen, first;
+   int line = 0, searchline = 0;
+   int FilePosition;
+
+   char Buff[Block+1] = "", PrevBuff[Block+1] = "";
+   char LogLine[(Block+1)*2] = ""; /* To hold our exported results. */
+
+   if(!(TheFile = fopen(AccountingLog, "r")))
+   {
+       send_message(user, chanserv, "LAST_ERROR", AccountingLog, strerror(errno));
+       return 0;
+   }
+   s = fseek(TheFile, 0, SEEK_END); /* Start at the end. */
+   filelen = ftell(TheFile); /* Find out the length. */
+   FilePosition = 0; /* (from the bottom) */
+   send_message(user, chanserv, "LAST_COMMAND_LOG", cptr->name);
+   send_message(user, chanserv, "LAST_LINE");
+   while(Last == 0)
+   {
+       FilePosition += Block;
+       if(FilePosition > filelen)
+       {
+          FilePosition = filelen;
+          Last = 1;
+       }
+       if((s = fseek(TheFile, filelen-FilePosition, SEEK_SET)) < 0)
+       {
+          send_message(user, chanserv, "LAST_ERROR", AccountingLog, strerror(errno));
+          fclose(TheFile);
+          return 0;
+       }
+       s = fread(Buff, 1, Block, TheFile);
+       Buff[Block] = '\0';
+       if(ferror(TheFile))
+       {
+           send_message(user, chanserv, "LAST_ERROR", AccountingLog, strerror(errno));
+           fclose(TheFile);
+           return 0;
+       }
+       first = 1;
+       for(i = s-1; i >= 0; i--)
+       {
+            if(Buff[i] == '\n')
+            {
+               Buff[i] = '\0';
+               strcpy(LogLine, &Buff[i+1]);
+               if(first)
+                  strcat(LogLine, PrevBuff);
+               first = 0;
+               searchline++;
+               if(parselog(LogLine, user, cptr, chan, nuh, command, rest))
+                 line++;
+               if(line >= maxlines)
+               {
+                  send_message(user, chanserv, "LAST_STOPPING_AT", maxlines);
+                  return 1;
+               }
+               if( searchline >= MAXLOGSEARCHLENGTH )
+               {
+                   send_message(user, chanserv, "LAST_MAX_AGE");
+                   fclose(TheFile);
+                   return 1;
+               }
+
+            }
+       }
+       strcpy(PrevBuff, Buff); /* Save the remaining bit. */
+   }
+   send_message(user, chanserv, "LAST_END_OF_LOG", line);
+   fclose(TheFile);
+   return 1;
+}