-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathseentree.c
213 lines (187 loc) · 5.79 KB
/
seentree.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/*
* Copyright (C) 2000,2001 Florian Sander
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
static struct generic_binary_tree seentree;
static void seentree_init();
static int seentree_expmem();
static void seentree_free();
static int compareseens(void *, void *);
static int expmemseen(void *);
static void add_seen(int, char *, char *, char *, char *,
time_t, int);
static void freeseen(void *);
static seendat *findseen(char *);
static void wildmatch_seens(char *, char *, int);
static void process_wildmatch_seens(void *);
static void write_seen_tree(void *);
static void purge_seen_tree(void *);
static int count_seens();
static void _count_seens(void *);
static void seentree_init()
{
seentree.root = NULL;
seentree.comparedata = compareseens;
seentree.expmemdata = expmemseen;
seentree.freedata = freeseen;
}
static int seentree_expmem()
{
return btree_expmem(&seentree);
}
static void seentree_free()
{
btree_freetree(&seentree);
seentree.root = NULL;
}
static int compareseens(void *first, void *second)
{
return rfc_casecmp(((seendat *) first)->nick, ((seendat *) second)->nick);
}
// add another entry to the tree
static void add_seen(int type, char *nick, char *host, char *chan, char *msg,
time_t when, int spent)
{
seendat *newseen;
newseen = nmalloc(sizeof(seendat));
newseen->type = type;
newseen->nick = nmalloc(strlen(nick) + 1);
strcpy(newseen->nick, nick);
newseen->host = nmalloc(strlen(host) + 1);
strcpy(newseen->host, host);
newseen->chan = nmalloc(strlen(chan) + 1);
strcpy(newseen->chan, chan);
newseen->msg = nmalloc(strlen(msg) + 1);
strcpy(newseen->msg, msg);
newseen->when = when;
newseen->spent = spent;
btree_add(&seentree, newseen);
}
static void freeseen(void *what)
{
seendat *s = (seendat *) what;
Assert(s);
Assert(s->nick);
Assert(s->host);
Assert(s->chan);
Assert(s->msg);
nfree(s->nick);
nfree(s->host);
nfree(s->chan);
nfree(s->msg);
nfree(s);
}
static int expmemseen(void *what)
{
int size = 0;
seendat *d = (seendat *) what;
size += sizeof(seendat);
size += strlen(d->nick) + 1;
size += strlen(d->host) + 1;
size += strlen(d->chan) + 1;
size += strlen(d->msg) + 1;
return size;
}
// finds a seen entry in the tree
seendat findseen_temp;
static seendat *findseen(char *nick)
{
findseen_temp.nick = nick;
return btree_get(&seentree, &findseen_temp);
}
// function to find all nicks that match a host
// (calls btree_getall() which calls a target function for each item)
// host: user's hostmask (used if search query doesn't contain any wildcards)
// mask: search mask
// wild: defines if we want to use the mask, or host for the search
static char *wildmatch_host, *wildmatch_mask;
int wildmatch_wild;
static void wildmatch_seens(char *host, char *mask, int wild)
{
wildmatch_host = host;
wildmatch_mask = mask;
wildmatch_wild = wild;
btree_getall(&seentree, process_wildmatch_seens);
}
/* process_wildmatch_seens():
* gets called from the binary tree for each existing item.
*/
static void process_wildmatch_seens(void *data)
{
seendat *s = (seendat *) data;
if ((numresults > max_matches) && (max_matches > 0)) // Don't return too many
return; // matches...
if (!wildmatch_wild) {
if (wild_match(wildmatch_host, s->host))
add_seenresult(s);
} else {
temp_wildmatch_host = my_realloc(temp_wildmatch_host, strlen(s->nick) + 1 + strlen(s->host) + 1);
strcpy(temp_wildmatch_host, s->nick);
strcat(temp_wildmatch_host, "!");
strcat(temp_wildmatch_host, s->host);
if (wild_match(wildmatch_mask, s->nick) || wild_match(wildmatch_mask, temp_wildmatch_host))
add_seenresult(s);
}
}
// write seendata in the datafile
FILE *write_seen_tree_target;
static void write_seen_tree(void *data)
{
seendat *node = (seendat *) data;
/* format: "! nick host chan type when spent msg" */
fprintf(write_seen_tree_target, "! %s %s %s %d %lu %d %s\n", node->nick,
node->host, node->chan, node->type, node->when, node->spent,
node->msg);
}
// recursive function to remove old data
// QUESTION: What happens if one of the nodes get moved by killseen()?
// Possible bug/crash?
// I think it should not be a problem. When killseen() is called the
// first time, recursion already reached its end and no pointers
// are accessed anymore. But I'm not sure... maybe I'm wrong.
static void purge_seen_tree(void *data)
{
seendat *node = (seendat *) data;
if ((now - node->when) > (expire_seens * 86400)) {
debug1("seen data for %s has expired.", node->nick);
btree_remove(&seentree, node);
}
}
// counts the number of nicks in the database
static int count_seens_temp;
static int count_seens()
{
count_seens_temp = 0;
btree_getall(&seentree, _count_seens);
return count_seens_temp;
}
static void _count_seens(void *node)
{
count_seens_temp++;
}
static int tcl_killseen STDVAR
{
Context;
BADARGS(2, 2, " nick");
findseen_temp.nick = argv[1];
btree_remove(&seentree, &findseen_temp);
return TCL_OK;
}
static tcl_cmds seendebugtcls[] =
{
{"killseen", tcl_killseen},
{0, 0}
};