]> jfr.im git - irc/quakenet/newserv.git/blobdiff - whowas/whowas.c
whowas: Treat glines as kills.
[irc/quakenet/newserv.git] / whowas / whowas.c
index 06949beafa4776bdafe72f43cd74b84c15813fe4..af38da29bca567b8ad8bb73fac106ffe5f574a79 100644 (file)
@@ -1,5 +1,5 @@
-#include <stdio.h>
 #include <string.h>
+#include <stdio.h>
 #include "../core/hooks.h"
 #include "../control/control.h"
 #include "../irc/irc.h"
@@ -14,16 +14,50 @@ int whowas_count = 0;
 
 whowas *whowas_fromnick(nick *np) {
   whowas *ww;
+  nick *wnp;
+  struct irc_in_addr ipaddress_canonical;
 
   /* 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);
-  memcpy(&ww->ip, &np->p_ipaddr, sizeof(struct irc_in_addr));
-  strncpy(ww->realname, np->realname->name->content, REALLEN);
-  ww->seen = getnettime();
+
+  wnp = newnick();
+  memset(wnp, 0, sizeof(nick));
+  strncpy(wnp->nick, np->nick, NICKLEN + 1);
+  wnp->numeric = np->numeric;
+  strncpy(wnp->ident, np->ident, USERLEN + 1);
+
+  wnp->host = newhost();
+  memset(wnp->host, 0, sizeof(host));
+  wnp->host->name = getsstring(np->host->name->content, HOSTLEN);
+
+  wnp->realname = newrealname();
+  memset(wnp->realname, 0, sizeof(realname));
+  wnp->realname->name = getsstring(np->realname->name->content, REALLEN);
+  wnp->shident = np->shident ? getsstring(np->shident->content, 512) : NULL;
+  wnp->sethost = np->sethost ? getsstring(np->sethost->content, 512) : NULL;
+  wnp->opername = np->opername ? getsstring(np->opername->content, 512) : NULL;
+  wnp->umodes = np->umodes;
+  if (np->auth) {
+    wnp->auth = newauthname();
+    memset(wnp->auth, 0, sizeof(authname));
+    wnp->auth->userid = np->auth->userid;
+    strncpy(wnp->auth->name, np->auth->name, ACCOUNTLEN + 1);
+    wnp->authname = wnp->auth->name;
+  }
+  wnp->timestamp = np->timestamp;
+  wnp->accountts = np->accountts;
+  wnp->away = np->away ? getsstring(np->away->content, 512) : NULL;
+
+  memcpy(&wnp->ipaddress, &np->ipaddress, sizeof(struct irc_in_addr));
+
+  ip_canonicalize_tunnel(&ipaddress_canonical, &np->ipaddress);
+  wnp->ipnode = refnode(iptree, &ipaddress_canonical, PATRICIA_MAXBITS);
+
+  wnp->next = (nick *)ww; /* Yuck. */
+
+  ww->nick = wnp;
+  ww->timestamp = getnettime();
 
   return ww;
 }
@@ -56,9 +90,23 @@ void whowas_unlinkrecord(whowas *ww) {
 }
 
 void whowas_free(whowas *ww) {
+  nick *np;
+
   if (!ww)
     return;
 
+  np = ww->nick;
+
+  freesstring(np->host->name);
+  freehost(np->host);
+  freesstring(np->realname->name);
+  freerealname(np->realname);
+  freesstring(np->shident);
+  freesstring(np->sethost);
+  freesstring(np->opername);
+  freeauthname(np->auth);
+  freesstring(np->away);
+  freenick(np);
   freesstring(ww->reason);
   free(ww);
 }
@@ -70,7 +118,7 @@ static void whowas_cleanup(void) {
   time(&now);
 
   /* Clean up old records. */
-  while (whowas_tail && (whowas_tail->seen < now - WW_MAXAGE || whowas_count >= WW_MAXENTRIES)) {
+  while (whowas_tail && (whowas_tail->timestamp < now - WW_MAXAGE || whowas_count >= WW_MAXENTRIES)) {
     ww = whowas_tail;
     whowas_unlinkrecord(ww);
     whowas_free(ww);
@@ -97,8 +145,12 @@ static void whowas_handlequitorkill(int hooknum, void *arg) {
     }
 
     ww->type = WHOWAS_KILL;
-  } else
-    ww->type = WHOWAS_QUIT;
+  } else {
+    if (strncmp(reason, "G-lined", 7) == 0)
+      ww->type = WHOWAS_KILL;
+    else
+      ww->type = WHOWAS_QUIT;
+  }
 
   ww->reason = getsstring(reason, WW_REASONLEN);
 
@@ -110,14 +162,15 @@ static void whowas_handlerename(int hooknum, void *arg) {
   nick *np = args[0];
   char *oldnick = args[1];
   whowas *ww;
+  nick *wnp;
 
   whowas_cleanup();
 
   ww = whowas_fromnick(np);
   ww->type = WHOWAS_RENAME;
-  ww->newnick = getsstring(ww->nick, NICKLEN);
-  strncpy(ww->nick, oldnick, NICKLEN);
-  ww->nick[NICKLEN] = '\0';
+  wnp = ww->nick;
+  ww->newnick = getsstring(wnp->nick, NICKLEN);
+  strncpy(wnp->nick, oldnick, NICKLEN + 1);
 
   whowas_linkrecord(ww);
 }
@@ -129,27 +182,51 @@ whowas *whowas_chase(const char *nick, int maxage) {
   now = getnettime();
 
   for (ww = whowas_head; ww; ww = ww->next) {
-    if (ww->seen < now - maxage)
+    if (ww->timestamp < now - maxage)
       break; /* records are in timestamp order, we're done */
 
-    if (ircd_strcmp(ww->nick, nick) == 0)
+    if (ircd_strcmp(ww->nick->nick, nick) == 0)
       return ww;
   }
 
   return NULL;
 }
 
-void whowas_spew(whowas *ww, nick *np) {
+const char *whowas_format(whowas *ww) {
+  nick *np = ww->nick;
+  static char buf[512];
   char timebuf[30];
-  char hostmask[WW_MASKLEN + 1];
+  char hostmask[512];
 
-  snprintf(hostmask, sizeof(hostmask), "%s!%s@%s [%s]", ww->nick, ww->ident, ww->host, IPtostr(ww->ip));
-  strftime(timebuf, 30, "%d/%m/%y %H:%M:%S", localtime(&(ww->seen)));
+  snprintf(hostmask, sizeof(hostmask), "%s!%s@%s%s%s [%s] (%s)",
+           np->nick, np->ident, np->host->name->content,
+           np->auth ? "/" : "", np->auth ? np->authname : "",
+           IPtostr(np->p_ipaddr),
+           printflags(np->umodes, umodeflags));
+  strftime(timebuf, sizeof(timebuf), "%d/%m/%y %H:%M:%S", localtime(&(ww->timestamp)));
 
   if (ww->type == WHOWAS_RENAME)
-    controlreply(np, "[%s] NICK %s (%s) -> %s", timebuf, hostmask, ww->realname, ww->newnick->content);
+    snprintf(buf, sizeof(buf), "[%s] NICK %s r(%s) -> %s", timebuf, hostmask, np->realname->name->content, ww->newnick->content);
   else
-    controlreply(np, "[%s] %s %s (%s): %s", timebuf, (ww->type == WHOWAS_QUIT) ? "QUIT" : "KILL", hostmask, ww->realname, ww->reason->content);
+    snprintf(buf, sizeof(buf), "[%s] %s %s r(%s): %s", timebuf, (ww->type == WHOWAS_QUIT) ? "QUIT" : "KILL", hostmask, np->realname->name->content, ww->reason->content);
+
+  return buf;
+}
+
+unsigned int nextwhowasmarker() {
+  whowas *ww;
+  static unsigned int whowasmarker=0;
+
+  whowasmarker++;
+
+  if (!whowasmarker) {
+    /* If we wrapped to zero, zap the marker on all records */
+    for (ww = whowas_head; ww; ww = ww->next)
+        ww->marker=0;
+    whowasmarker++;
+  }
+
+  return whowasmarker;
 }
 
 void _init(void) {