]> jfr.im git - irc/quakenet/newserv.git/blob - whowas/whowas.c
439caea9b76c29e7354260954b2d7f620289bc1d
[irc/quakenet/newserv.git] / whowas / whowas.c
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"
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
18 /* Create a new record. */
19 ww = malloc(sizeof(whowas));
20 memset(ww, 0, sizeof(whowas));
21 strncpy(ww->nick, np->nick, NICKLEN);
22 strncpy(ww->ident, np->ident, USERLEN);
23 strncpy(ww->host, np->host->name->content, HOSTLEN);
24 memcpy(&ww->ip, &np->p_ipaddr, sizeof(struct irc_in_addr));
25 strncpy(ww->realname, np->realname->name->content, REALLEN);
26 ww->seen = getnettime();
27
28 return ww;
29 }
30
31 void whowas_linkrecord(whowas *ww) {
32 if (whowas_head)
33 whowas_head->prev = ww;
34
35 ww->next = whowas_head;
36 whowas_head = ww;
37
38 ww->prev = NULL;
39
40 if (!whowas_tail)
41 whowas_tail = ww;
42
43 whowas_count++;
44 }
45
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--;
56 }
57
58 static void whowas_cleanup(void) {
59 time_t now;
60
61 time(&now);
62
63 /* Clean up old records. */
64 while (whowas_tail && (whowas_tail->seen < now - WW_MAXAGE || whowas_count >= WW_MAXENTRIES)) {
65 whowas_unlinkrecord(whowas_tail);
66 free(whowas_tail);
67 }
68 }
69
70 static void whowas_handlequitorkill(int hooknum, void *arg) {
71 void **args = arg;
72 nick *np = args[0];
73 char *reason = args[1];
74 char *rreason;
75 char resbuf[512];
76 whowas *ww;
77
78 whowas_cleanup();
79
80 /* Create a new record. */
81 ww = whowas_fromnick(np);
82
83 if (hooknum == HOOK_NICK_KILL) {
84 if ((rreason = strchr(reason, ' '))) {
85 sprintf(resbuf, "Killed%s", rreason);
86 reason = resbuf;
87 }
88
89 ww->type = WHOWAS_KILL;
90 } else
91 ww->type = WHOWAS_QUIT;
92
93 ww->reason = getsstring(reason, WW_REASONLEN);
94
95 whowas_linkrecord(ww);
96 }
97
98 static void whowas_handlerename(int hooknum, void *arg) {
99 void **args = arg;
100 nick *np = args[0];
101 char *oldnick = args[1];
102 whowas *ww;
103
104 whowas_cleanup();
105
106 ww = whowas_fromnick(np);
107 ww->type = WHOWAS_RENAME;
108 ww->newnick = getsstring(ww->nick, NICKLEN);
109 strncpy(ww->nick, oldnick, NICKLEN);
110 ww->nick[NICKLEN] = '\0';
111
112 whowas_linkrecord(ww);
113 }
114
115 whowas *whowas_chase(const char *nick, int maxage) {
116 whowas *ww;
117 time_t now;
118
119 now = getnettime();
120
121 for (ww = whowas_head; ww; ww = ww->next) {
122 if (ww->seen < now - maxage)
123 break; /* records are in timestamp order, we're done */
124
125 if (ircd_strcmp(ww->nick, nick) == 0)
126 return ww;
127 }
128
129 return NULL;
130 }
131
132 void _init(void) {
133 registerhook(HOOK_NICK_QUIT, whowas_handlequitorkill);
134 registerhook(HOOK_NICK_KILL, whowas_handlequitorkill);
135 registerhook(HOOK_NICK_RENAME, whowas_handlerename);
136 }
137
138 void _fini(void) {
139 deregisterhook(HOOK_NICK_QUIT, whowas_handlequitorkill);
140 deregisterhook(HOOK_NICK_KILL, whowas_handlequitorkill);
141 deregisterhook(HOOK_NICK_RENAME, whowas_handlerename);
142
143 while (whowas_head)
144 whowas_unlinkrecord(whowas_head);
145 }