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"
12 whowas
*whowas_head
= NULL
, *whowas_tail
= NULL
;
15 whowas
*whowas_fromnick(nick
*np
) {
18 struct irc_in_addr ipaddress_canonical
;
20 /* Create a new record. */
21 ww
= malloc(sizeof(whowas
));
22 memset(ww
, 0, sizeof(whowas
));
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);
30 wnp
->host
= newhost();
31 memset(wnp
->host
, 0, sizeof(host
));
32 wnp
->host
->name
= getsstring(np
->host
->name
->content
, HOSTLEN
);
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
;
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
;
48 wnp
->timestamp
= np
->timestamp
;
49 wnp
->accountts
= np
->accountts
;
50 wnp
->away
= np
->away
? getsstring(np
->away
->content
, 512) : NULL
;
52 memcpy(&wnp
->ipaddress
, &np
->ipaddress
, sizeof(struct irc_in_addr
));
54 ip_canonicalize_tunnel(&ipaddress_canonical
, &np
->ipaddress
);
55 wnp
->ipnode
= refnode(iptree
, &ipaddress_canonical
, PATRICIA_MAXBITS
);
57 wnp
->next
= (nick
*)ww
; /* Yuck. */
60 ww
->timestamp
= getnettime();
65 void whowas_linkrecord(whowas
*ww
) {
67 whowas_head
->prev
= ww
;
69 ww
->next
= whowas_head
;
80 void whowas_unlinkrecord(whowas
*ww
) {
82 whowas_tail
= ww
->prev
;
85 ww
->prev
->next
= NULL
;
87 whowas_head
= ww
->prev
;
92 void whowas_free(whowas
*ww
) {
100 freesstring(np
->host
->name
);
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
);
110 freesstring(ww
->reason
);
114 static void whowas_cleanup(void) {
120 /* Clean up old records. */
121 while (whowas_tail
&& (whowas_tail
->timestamp
< now
- WW_MAXAGE
|| whowas_count
>= WW_MAXENTRIES
)) {
123 whowas_unlinkrecord(ww
);
128 static void whowas_handlequitorkill(int hooknum
, void *arg
) {
131 char *reason
= args
[1];
138 /* Create a new record. */
139 ww
= whowas_fromnick(np
);
141 if (hooknum
== HOOK_NICK_KILL
) {
142 if ((rreason
= strchr(reason
, ' '))) {
143 sprintf(resbuf
, "Killed%s", rreason
);
147 ww
->type
= WHOWAS_KILL
;
149 if (strncmp(reason
, "G-lined", 7) == 0)
150 ww
->type
= WHOWAS_KILL
;
152 ww
->type
= WHOWAS_QUIT
;
155 ww
->reason
= getsstring(reason
, WW_REASONLEN
);
157 whowas_linkrecord(ww
);
160 static void whowas_handlerename(int hooknum
, void *arg
) {
163 char *oldnick
= args
[1];
169 ww
= whowas_fromnick(np
);
170 ww
->type
= WHOWAS_RENAME
;
172 ww
->newnick
= getsstring(wnp
->nick
, NICKLEN
);
173 strncpy(wnp
->nick
, oldnick
, NICKLEN
+ 1);
175 whowas_linkrecord(ww
);
178 whowas
*whowas_chase(const char *nick
, int maxage
) {
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 */
188 if (ircd_strcmp(ww
->nick
->nick
, nick
) == 0)
195 const char *whowas_format(whowas
*ww
) {
197 static char buf
[512];
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
)));
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
);
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
);
216 unsigned int nextwhowasmarker() {
218 static unsigned int whowasmarker
=0;
223 /* If we wrapped to zero, zap the marker on all records */
224 for (ww
= whowas_head
; ww
; ww
= ww
->next
)
233 registerhook(HOOK_NICK_QUIT
, whowas_handlequitorkill
);
234 registerhook(HOOK_NICK_KILL
, whowas_handlequitorkill
);
235 registerhook(HOOK_NICK_RENAME
, whowas_handlerename
);
239 deregisterhook(HOOK_NICK_QUIT
, whowas_handlequitorkill
);
240 deregisterhook(HOOK_NICK_KILL
, whowas_handlequitorkill
);
241 deregisterhook(HOOK_NICK_RENAME
, whowas_handlerename
);
244 whowas_unlinkrecord(whowas_head
);