]> jfr.im git - irc/quakenet/newserv.git/blobdiff - whowas/whowas.c
whowas: Keep track of nick changes.
[irc/quakenet/newserv.git] / whowas / whowas.c
index 2132e90f7a5048a0aa0812e89ecadf5487febb25..8679503836ee5c207e4c2d2c174f44fd53abaf00 100644 (file)
 #include "../control/control.h"
 #include "../irc/irc.h"
 #include "../lib/irc_string.h"
+#include "../lib/version.h"
 #include "whowas.h"
 
-static whowas *wwhead, *wwtail;
-static int wwcount;
+MODULE_VERSION("");
 
-int ww_cmdwhowas(void *source, int cargc, char **cargv) {
-  nick *np = source;
-  char *pattern;
+whowas *whowas_head = NULL, *whowas_tail = NULL;
+int whowas_count = 0;
+
+whowas *whowas_fromnick(nick *np) {
   whowas *ww;
-  char hostmask[WW_MASKLEN+1];
-  char timebuf[30];
-  int matches = 0, limit = 500;
 
-  if(cargc<1)
-    return CMD_USAGE;
+  /* Create a new record. */
+  ww = malloc(sizeof(whowas));
+  memset(ww, 0, sizeof(whowas));
+  strncpy(ww->nick, np->nick, NICKLEN);
+  strncpy(ww->ident, np->ident, USERLEN);
+  strncpy(ww->host, np->host->name->content, HOSTLEN);
+  strncpy(ww->realname, np->realname->name->content, REALLEN);
+  ww->seen = getnettime();
+
+  return ww;
+}
 
-  pattern = cargv[0];
+void whowas_linkrecord(whowas *ww) {
+  if (whowas_head)
+    whowas_head->prev = ww;
 
-  if(cargc>1)
-    limit = strtol(cargv[1], NULL, 10);
+  ww->next = whowas_head;
+  whowas_head = ww;
 
-  for(ww=wwhead;ww;ww=ww->next) {
-    snprintf(hostmask, sizeof(hostmask), "%s!%s@%s", ww->nick, ww->ident, ww->host);
+  ww->prev = NULL;
 
-    if (match2strings(pattern, hostmask)) {
-      matches++;
+  if (!whowas_tail)
+    whowas_tail = ww;
 
-      if(matches<=limit) {
-        strftime(timebuf, 30, "%d/%m/%y %H:%M:%S", localtime(&(ww->seen)));
+  whowas_count++;
+}
 
-        controlreply(np, "[%s] %s (%s): %s", timebuf, hostmask, ww->realname, ww->reason->content);
-      } else if(matches==limit+1) {
-        controlreply(np, "--- More than %d matches, skipping the rest", limit);
-      }
-    }
-  }
+void whowas_unlinkrecord(whowas *ww) {
+  if (!ww->next)
+    whowas_tail = ww->prev;
 
-  controlreply(np, "--- Found %d entries.", matches);
+  if (ww->prev)
+    ww->prev->next = NULL;
+  else
+    whowas_head = ww->prev;
 
-  return CMD_OK;
+  whowas_count--;
 }
 
-void ww_handlequitorkill(int hooknum, void *arg) {
-  void **args=arg;
-  nick *np=args[0];
-  char *reason=args[1];
-  char *rreason;
-  char resbuf[512];
-  whowas *ww;
+static void whowas_cleanup(void) {
   time_t now;
 
   time(&now);
 
   /* Clean up old records. */
-  while((ww = wwtail) && (ww->seen < now - WW_MAXAGE || wwcount >= WW_MAXENTRIES)) {
-    wwtail = ww->prev;
+  while (whowas_tail && (whowas_tail->seen < now - WW_MAXAGE || whowas_count >= WW_MAXENTRIES)) {
+    whowas_unlinkrecord(whowas_tail);
+    free(whowas_tail);
+  }
+}
 
-    if (ww->prev)
-      ww->prev->next = NULL;
-    else
-      wwhead = ww->prev;
+static void whowas_handlequitorkill(int hooknum, void *arg) {
+  void **args = arg;
+  nick *np = args[0];
+  char *reason = args[1];
+  char *rreason;
+  char resbuf[512];
+  whowas *ww;
 
-    wwcount--;
-    free(ww);
-  }
+  whowas_cleanup();
 
   /* Create a new record. */
-  ww = malloc(sizeof(whowas));
-  strncpy(ww->nick, np->nick, NICKLEN);
-  strncpy(ww->ident, np->ident, USERLEN);
-  strncpy(ww->host, np->host->name->content, HOSTLEN);
-  strncpy(ww->realname, np->realname->name->content, REALLEN);
-  ww->seen = getnettime();
+  ww = whowas_fromnick(np);
 
-  if(hooknum==HOOK_NICK_KILL && (rreason=strchr(reason,' '))) {
-    sprintf(resbuf,"Killed%s",rreason);
-    reason=resbuf;
-  }
+  if (hooknum == HOOK_NICK_KILL) {
+    if ((rreason = strchr(reason, ' '))) {
+      sprintf(resbuf, "Killed%s", rreason);
+      reason = resbuf;
+    }
+
+    ww->type = WHOWAS_KILL;
+  } else
+    ww->type = WHOWAS_QUIT;
 
   ww->reason = getsstring(reason, WW_REASONLEN);
 
-  if(wwhead)
-    wwhead->prev = ww;
+  whowas_linkrecord(ww);
+}
 
-  ww->next = wwhead;
-  wwhead = ww;
+static void whowas_handlerename(int hooknum, void *arg) {
+  void **args = arg;
+  nick *np = args[0];
+  char *oldnick = args[1];
+  whowas *ww;
 
-  ww->prev = NULL;
+  whowas_cleanup();
 
-  if(!wwtail)
-    wwtail = ww;
+  ww = whowas_fromnick(np);
+  ww->type = WHOWAS_RENAME;
+  ww->newnick = getsstring(ww->nick, NICKLEN);
+  strncpy(ww->nick, oldnick, NICKLEN);
+  ww->nick[NICKLEN] = '\0';
 
-  wwcount++;
+  whowas_linkrecord(ww);
 }
 
 void _init(void) {
-  registerhook(HOOK_NICK_QUIT, ww_handlequitorkill);
-  registerhook(HOOK_NICK_KILL, ww_handlequitorkill);
-
-  registercontrolhelpcmd("whowas", NO_OPER, 2, &ww_cmdwhowas, "Usage: whowas <mask> ?limit?\nLooks up information about recently disconnected users.");
+  registerhook(HOOK_NICK_QUIT, whowas_handlequitorkill);
+  registerhook(HOOK_NICK_KILL, whowas_handlequitorkill);
+  registerhook(HOOK_NICK_RENAME, whowas_handlerename);
 }
 
 void _fini(void) {
-  whowas *ww;
-
-  deregisterhook(HOOK_NICK_QUIT, ww_handlequitorkill);
-  deregisterhook(HOOK_NICK_KILL, ww_handlequitorkill);
+  deregisterhook(HOOK_NICK_QUIT, whowas_handlequitorkill);
+  deregisterhook(HOOK_NICK_KILL, whowas_handlequitorkill);
+  deregisterhook(HOOK_NICK_RENAME, whowas_handlerename);
 
-  deregistercontrolcmd("whowas", &ww_cmdwhowas);
-
-  while((ww = wwhead)) {
-    wwhead = ww->next;
-    free(ww);
-  }
+  while (whowas_head)
+    whowas_unlinkrecord(whowas_head);
 }