]>
Commit | Line | Data |
---|---|---|
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 | 10 | MODULE_VERSION(""); |
fa6819a7 | 11 | |
363e3ed0 GB |
12 | whowas *whowas_head = NULL, *whowas_tail = NULL; |
13 | int whowas_count = 0; | |
d6385de2 | 14 | |
4030a47e | 15 | whowas *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 | 31 | void 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 |
46 | void 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 |
58 | void whowas_free(whowas *ww) { |
59 | if (!ww) | |
60 | return; | |
61 | ||
62 | freesstring(ww->reason); | |
63 | free(ww); | |
64 | } | |
65 | ||
4030a47e GB |
66 | static 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 | |
80 | static 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 | ||
108 | static 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 |
125 | whowas *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 |
142 | void 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 |
155 | void _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 | ||
161 | void _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 | } |