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