#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);
}