]> jfr.im git - irc/quakenet/newserv.git/blame - whowas/whowas.c
Implement nick chasing for the block command.
[irc/quakenet/newserv.git] / whowas / whowas.c
CommitLineData
fa6819a7
GB
1#include <stdio.h>
2#include <string.h>
3#include "../core/hooks.h"
4#include "../control/control.h"
5#include "../irc/irc.h"
6#include "../lib/irc_string.h"
363e3ed0 7#include "../lib/version.h"
fa6819a7
GB
8#include "whowas.h"
9
363e3ed0 10MODULE_VERSION("");
fa6819a7 11
363e3ed0
GB
12whowas *whowas_head = NULL, *whowas_tail = NULL;
13int whowas_count = 0;
d6385de2 14
4030a47e 15whowas *whowas_fromnick(nick *np) {
fa6819a7 16 whowas *ww;
fa6819a7
GB
17
18 /* Create a new record. */
19 ww = malloc(sizeof(whowas));
4030a47e 20 memset(ww, 0, sizeof(whowas));
fa6819a7
GB
21 strncpy(ww->nick, np->nick, NICKLEN);
22 strncpy(ww->ident, np->ident, USERLEN);
23 strncpy(ww->host, np->host->name->content, HOSTLEN);
9306ee25 24 memcpy(&ww->ip, &np->p_ipaddr, sizeof(struct irc_in_addr));
fa6819a7
GB
25 strncpy(ww->realname, np->realname->name->content, REALLEN);
26 ww->seen = getnettime();
27
4030a47e
GB
28 return ww;
29}
d6385de2 30
4030a47e 31void whowas_linkrecord(whowas *ww) {
363e3ed0
GB
32 if (whowas_head)
33 whowas_head->prev = ww;
d6385de2 34
363e3ed0
GB
35 ww->next = whowas_head;
36 whowas_head = ww;
d6385de2
GB
37
38 ww->prev = NULL;
39
363e3ed0
GB
40 if (!whowas_tail)
41 whowas_tail = ww;
fa6819a7 42
363e3ed0 43 whowas_count++;
fa6819a7
GB
44}
45
4030a47e
GB
46void whowas_unlinkrecord(whowas *ww) {
47 if (!ww->next)
48 whowas_tail = ww->prev;
49
50 if (ww->prev)
51 ww->prev->next = NULL;
52 else
53 whowas_head = ww->prev;
54
55 whowas_count--;
fa6819a7
GB
56}
57
accce086
GB
58void whowas_free(whowas *ww) {
59 if (!ww)
60 return;
61
62 freesstring(ww->reason);
63 free(ww);
64}
65
4030a47e
GB
66static void whowas_cleanup(void) {
67 time_t now;
accce086 68 whowas *ww;
fa6819a7 69
4030a47e 70 time(&now);
fa6819a7 71
4030a47e
GB
72 /* Clean up old records. */
73 while (whowas_tail && (whowas_tail->seen < now - WW_MAXAGE || whowas_count >= WW_MAXENTRIES)) {
accce086
GB
74 ww = whowas_tail;
75 whowas_unlinkrecord(ww);
76 whowas_free(ww);
fa6819a7
GB
77 }
78}
4030a47e
GB
79
80static void whowas_handlequitorkill(int hooknum, void *arg) {
81 void **args = arg;
82 nick *np = args[0];
83 char *reason = args[1];
84 char *rreason;
85 char resbuf[512];
86 whowas *ww;
87
88 whowas_cleanup();
89
90 /* Create a new record. */
91 ww = whowas_fromnick(np);
92
93 if (hooknum == HOOK_NICK_KILL) {
94 if ((rreason = strchr(reason, ' '))) {
95 sprintf(resbuf, "Killed%s", rreason);
96 reason = resbuf;
97 }
98
99 ww->type = WHOWAS_KILL;
100 } else
101 ww->type = WHOWAS_QUIT;
102
103 ww->reason = getsstring(reason, WW_REASONLEN);
104
105 whowas_linkrecord(ww);
106}
107
108static void whowas_handlerename(int hooknum, void *arg) {
109 void **args = arg;
110 nick *np = args[0];
111 char *oldnick = args[1];
112 whowas *ww;
113
114 whowas_cleanup();
115
116 ww = whowas_fromnick(np);
117 ww->type = WHOWAS_RENAME;
118 ww->newnick = getsstring(ww->nick, NICKLEN);
119 strncpy(ww->nick, oldnick, NICKLEN);
120 ww->nick[NICKLEN] = '\0';
121
122 whowas_linkrecord(ww);
123}
124
56cab147
GB
125whowas *whowas_chase(const char *nick, int maxage) {
126 whowas *ww;
127 time_t now;
128
129 now = getnettime();
130
131 for (ww = whowas_head; ww; ww = ww->next) {
132 if (ww->seen < now - maxage)
133 break; /* records are in timestamp order, we're done */
134
135 if (ircd_strcmp(ww->nick, nick) == 0)
136 return ww;
137 }
138
139 return NULL;
140}
141
accce086
GB
142void whowas_spew(whowas *ww, nick *np) {
143 char timebuf[30];
144 char hostmask[WW_MASKLEN + 1];
145
146 snprintf(hostmask, sizeof(hostmask), "%s!%s@%s [%s]", ww->nick, ww->ident, ww->host, IPtostr(ww->ip));
147 strftime(timebuf, 30, "%d/%m/%y %H:%M:%S", localtime(&(ww->seen)));
148
149 if (ww->type == WHOWAS_RENAME)
150 controlreply(np, "[%s] NICK %s (%s) -> %s", timebuf, hostmask, ww->realname, ww->newnick->content);
151 else
152 controlreply(np, "[%s] %s %s (%s): %s", timebuf, (ww->type == WHOWAS_QUIT) ? "QUIT" : "KILL", hostmask, ww->realname, ww->reason->content);
153}
154
4030a47e
GB
155void _init(void) {
156 registerhook(HOOK_NICK_QUIT, whowas_handlequitorkill);
157 registerhook(HOOK_NICK_KILL, whowas_handlequitorkill);
158 registerhook(HOOK_NICK_RENAME, whowas_handlerename);
159}
160
161void _fini(void) {
162 deregisterhook(HOOK_NICK_QUIT, whowas_handlequitorkill);
163 deregisterhook(HOOK_NICK_KILL, whowas_handlequitorkill);
164 deregisterhook(HOOK_NICK_RENAME, whowas_handlerename);
165
166 while (whowas_head)
167 whowas_unlinkrecord(whowas_head);
168}