]> jfr.im git - irc/quakenet/newserv.git/blame - whowas/whowas_channels.c
CHANSERV: better batcher error handling for expired accounts/accounts with no email.
[irc/quakenet/newserv.git] / whowas / whowas_channels.c
CommitLineData
dd33b9ca
GB
1#include <string.h>
2#include <assert.h>
01897a81 3#include "../lib/version.h"
dd33b9ca
GB
4#include "../nick/nick.h"
5#include "../chanindex/chanindex.h"
6#include "../channel/channel.h"
7#include "../core/hooks.h"
8#include "whowas.h"
9
01897a81
GB
10MODULE_VERSION("");
11
dd33b9ca
GB
12static int wwcnext, wwccext;
13
14static void wwc_refchannel(chanindex *cip) {
15 uintptr_t *refcount = (uintptr_t *)&cip->exts[wwccext];
16 (*refcount)++;
17}
18
19static void wwc_derefchannel(chanindex *cip) {
20 uintptr_t *refcount = (uintptr_t *)&cip->exts[wwccext];
21 (*refcount)--;
22
dd33b9ca
GB
23 if (*refcount == 0)
24 releasechanindex(cip);
25}
26
27static void wwc_hook_joincreate(int hooknum, void *arg) {
28 void **args = arg;
29 channel *cp = args[0];
30 nick *np = args[1];
31 chanindex **wchans = np->exts[wwcnext];
32
33 if (!wchans) {
34 wchans = calloc(sizeof(chanindex *), WW_MAXCHANNELS);
35 np->exts[wwcnext] = wchans;
36 }
37
38 wwc_refchannel(cp->index);
39
40 memmove(&wchans[1], &wchans[0], sizeof(chanindex *) * (WW_MAXCHANNELS - 1));
41 wchans[0] = cp->index;
42}
43
44static void wwc_hook_lostnick(int hooknum, void *arg) {
45 nick *np = arg;
46 chanindex **wchans = np->exts[wwcnext];
47 int i;
48
49 if (!wchans)
50 return;
51
52 for (i = 0; i < WW_MAXCHANNELS; i++) {
53 if (!wchans[i])
54 break;
55
56 wwc_derefchannel(wchans[i]);
57 }
58
59 free(wchans);
84751a9d 60 np->exts[wwcnext] = NULL;
dd33b9ca
GB
61}
62
63static void wwc_hook_newrecord(int hooknum, void *arg) {
64 void **args = arg;
65 whowas *ww = args[0];
66 nick *np = args[1];
67 chanindex **wchans = np->exts[wwcnext];
68 int i;
69
70 memset(ww->channels, 0, sizeof(ww->channels));
71
72 if (!wchans)
73 return;
74
75 for (i = 0; i < WW_MAXCHANNELS; i++) {
76 if (!wchans[i])
77 break;
78
79 wwc_refchannel(wchans[i]);
80 ww->channels[i] = wchans[i];
81 }
82}
83
84static void wwc_hook_lostrecord(int hooknum, void *arg) {
85 whowas *ww = arg;
86 int i;
87
88 for (i = 0; i < WW_MAXCHANNELS; i++) {
89 if (!ww->channels[i])
90 break;
91
92 wwc_derefchannel(ww->channels[i]);
93 }
94}
95
96void _init(void) {
97 wwcnext = registernickext("whowas_channels");
98 wwccext = registerchanext("whowas_channels");
99
100 registerhook(HOOK_CHANNEL_JOIN, &wwc_hook_joincreate);
101 registerhook(HOOK_CHANNEL_CREATE, &wwc_hook_joincreate);
102 registerhook(HOOK_NICK_LOSTNICK, &wwc_hook_lostnick);
103 registerhook(HOOK_WHOWAS_NEWRECORD, &wwc_hook_newrecord);
104 registerhook(HOOK_WHOWAS_LOSTRECORD, &wwc_hook_lostrecord);
105}
106
107void _fini(void) {
108 releasenickext(wwcnext);
109 releasechanext(wwccext);
110
111 deregisterhook(HOOK_CHANNEL_JOIN, &wwc_hook_joincreate);
112 deregisterhook(HOOK_CHANNEL_CREATE, &wwc_hook_joincreate);
113 deregisterhook(HOOK_NICK_LOSTNICK, &wwc_hook_lostnick);
114 deregisterhook(HOOK_WHOWAS_NEWRECORD, &wwc_hook_newrecord);
115 deregisterhook(HOOK_WHOWAS_LOSTRECORD, &wwc_hook_lostrecord);
116}