]> jfr.im git - irc/quakenet/newserv.git/blob - whowas/whowas.c
whowas: Treat glines as kills.
[irc/quakenet/newserv.git] / whowas / whowas.c
1 #include <string.h>
2 #include <stdio.h>
3 #include "../core/hooks.h"
4 #include "../control/control.h"
5 #include "../irc/irc.h"
6 #include "../lib/irc_string.h"
7 #include "../lib/version.h"
8 #include "whowas.h"
9
10 MODULE_VERSION("");
11
12 whowas *whowas_head = NULL, *whowas_tail = NULL;
13 int whowas_count = 0;
14
15 whowas *whowas_fromnick(nick *np) {
16 whowas *ww;
17 nick *wnp;
18 struct irc_in_addr ipaddress_canonical;
19
20 /* Create a new record. */
21 ww = malloc(sizeof(whowas));
22 memset(ww, 0, sizeof(whowas));
23
24 wnp = newnick();
25 memset(wnp, 0, sizeof(nick));
26 strncpy(wnp->nick, np->nick, NICKLEN + 1);
27 wnp->numeric = np->numeric;
28 strncpy(wnp->ident, np->ident, USERLEN + 1);
29
30 wnp->host = newhost();
31 memset(wnp->host, 0, sizeof(host));
32 wnp->host->name = getsstring(np->host->name->content, HOSTLEN);
33
34 wnp->realname = newrealname();
35 memset(wnp->realname, 0, sizeof(realname));
36 wnp->realname->name = getsstring(np->realname->name->content, REALLEN);
37 wnp->shident = np->shident ? getsstring(np->shident->content, 512) : NULL;
38 wnp->sethost = np->sethost ? getsstring(np->sethost->content, 512) : NULL;
39 wnp->opername = np->opername ? getsstring(np->opername->content, 512) : NULL;
40 wnp->umodes = np->umodes;
41 if (np->auth) {
42 wnp->auth = newauthname();
43 memset(wnp->auth, 0, sizeof(authname));
44 wnp->auth->userid = np->auth->userid;
45 strncpy(wnp->auth->name, np->auth->name, ACCOUNTLEN + 1);
46 wnp->authname = wnp->auth->name;
47 }
48 wnp->timestamp = np->timestamp;
49 wnp->accountts = np->accountts;
50 wnp->away = np->away ? getsstring(np->away->content, 512) : NULL;
51
52 memcpy(&wnp->ipaddress, &np->ipaddress, sizeof(struct irc_in_addr));
53
54 ip_canonicalize_tunnel(&ipaddress_canonical, &np->ipaddress);
55 wnp->ipnode = refnode(iptree, &ipaddress_canonical, PATRICIA_MAXBITS);
56
57 wnp->next = (nick *)ww; /* Yuck. */
58
59 ww->nick = wnp;
60 ww->timestamp = getnettime();
61
62 return ww;
63 }
64
65 void whowas_linkrecord(whowas *ww) {
66 if (whowas_head)
67 whowas_head->prev = ww;
68
69 ww->next = whowas_head;
70 whowas_head = ww;
71
72 ww->prev = NULL;
73
74 if (!whowas_tail)
75 whowas_tail = ww;
76
77 whowas_count++;
78 }
79
80 void whowas_unlinkrecord(whowas *ww) {
81 if (!ww->next)
82 whowas_tail = ww->prev;
83
84 if (ww->prev)
85 ww->prev->next = NULL;
86 else
87 whowas_head = ww->prev;
88
89 whowas_count--;
90 }
91
92 void whowas_free(whowas *ww) {
93 nick *np;
94
95 if (!ww)
96 return;
97
98 np = ww->nick;
99
100 freesstring(np->host->name);
101 freehost(np->host);
102 freesstring(np->realname->name);
103 freerealname(np->realname);
104 freesstring(np->shident);
105 freesstring(np->sethost);
106 freesstring(np->opername);
107 freeauthname(np->auth);
108 freesstring(np->away);
109 freenick(np);
110 freesstring(ww->reason);
111 free(ww);
112 }
113
114 static void whowas_cleanup(void) {
115 time_t now;
116 whowas *ww;
117
118 time(&now);
119
120 /* Clean up old records. */
121 while (whowas_tail && (whowas_tail->timestamp < now - WW_MAXAGE || whowas_count >= WW_MAXENTRIES)) {
122 ww = whowas_tail;
123 whowas_unlinkrecord(ww);
124 whowas_free(ww);
125 }
126 }
127
128 static void whowas_handlequitorkill(int hooknum, void *arg) {
129 void **args = arg;
130 nick *np = args[0];
131 char *reason = args[1];
132 char *rreason;
133 char resbuf[512];
134 whowas *ww;
135
136 whowas_cleanup();
137
138 /* Create a new record. */
139 ww = whowas_fromnick(np);
140
141 if (hooknum == HOOK_NICK_KILL) {
142 if ((rreason = strchr(reason, ' '))) {
143 sprintf(resbuf, "Killed%s", rreason);
144 reason = resbuf;
145 }
146
147 ww->type = WHOWAS_KILL;
148 } else {
149 if (strncmp(reason, "G-lined", 7) == 0)
150 ww->type = WHOWAS_KILL;
151 else
152 ww->type = WHOWAS_QUIT;
153 }
154
155 ww->reason = getsstring(reason, WW_REASONLEN);
156
157 whowas_linkrecord(ww);
158 }
159
160 static void whowas_handlerename(int hooknum, void *arg) {
161 void **args = arg;
162 nick *np = args[0];
163 char *oldnick = args[1];
164 whowas *ww;
165 nick *wnp;
166
167 whowas_cleanup();
168
169 ww = whowas_fromnick(np);
170 ww->type = WHOWAS_RENAME;
171 wnp = ww->nick;
172 ww->newnick = getsstring(wnp->nick, NICKLEN);
173 strncpy(wnp->nick, oldnick, NICKLEN + 1);
174
175 whowas_linkrecord(ww);
176 }
177
178 whowas *whowas_chase(const char *nick, int maxage) {
179 whowas *ww;
180 time_t now;
181
182 now = getnettime();
183
184 for (ww = whowas_head; ww; ww = ww->next) {
185 if (ww->timestamp < now - maxage)
186 break; /* records are in timestamp order, we're done */
187
188 if (ircd_strcmp(ww->nick->nick, nick) == 0)
189 return ww;
190 }
191
192 return NULL;
193 }
194
195 const char *whowas_format(whowas *ww) {
196 nick *np = ww->nick;
197 static char buf[512];
198 char timebuf[30];
199 char hostmask[512];
200
201 snprintf(hostmask, sizeof(hostmask), "%s!%s@%s%s%s [%s] (%s)",
202 np->nick, np->ident, np->host->name->content,
203 np->auth ? "/" : "", np->auth ? np->authname : "",
204 IPtostr(np->p_ipaddr),
205 printflags(np->umodes, umodeflags));
206 strftime(timebuf, sizeof(timebuf), "%d/%m/%y %H:%M:%S", localtime(&(ww->timestamp)));
207
208 if (ww->type == WHOWAS_RENAME)
209 snprintf(buf, sizeof(buf), "[%s] NICK %s r(%s) -> %s", timebuf, hostmask, np->realname->name->content, ww->newnick->content);
210 else
211 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);
212
213 return buf;
214 }
215
216 unsigned int nextwhowasmarker() {
217 whowas *ww;
218 static unsigned int whowasmarker=0;
219
220 whowasmarker++;
221
222 if (!whowasmarker) {
223 /* If we wrapped to zero, zap the marker on all records */
224 for (ww = whowas_head; ww; ww = ww->next)
225 ww->marker=0;
226 whowasmarker++;
227 }
228
229 return whowasmarker;
230 }
231
232 void _init(void) {
233 registerhook(HOOK_NICK_QUIT, whowas_handlequitorkill);
234 registerhook(HOOK_NICK_KILL, whowas_handlequitorkill);
235 registerhook(HOOK_NICK_RENAME, whowas_handlerename);
236 }
237
238 void _fini(void) {
239 deregisterhook(HOOK_NICK_QUIT, whowas_handlequitorkill);
240 deregisterhook(HOOK_NICK_KILL, whowas_handlequitorkill);
241 deregisterhook(HOOK_NICK_RENAME, whowas_handlerename);
242
243 while (whowas_head)
244 whowas_unlinkrecord(whowas_head);
245 }