]> jfr.im git - solanum.git/blob - bandb/bandb.c
Terminate last line in setfilter help
[solanum.git] / bandb / bandb.c
1 /* bandb/bandb.c
2 *
3 * Copyright (C) 2006 Lee Hardy <lee -at- leeh.co.uk>
4 * Copyright (C) 2006-2008 ircd-ratbox development team
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * 1.Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2.Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3.The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30 #include "setup.h"
31 #include <rb_lib.h>
32 #include <stdio.h>
33 #include "rsdb.h"
34 #include "ircd_defs.h"
35
36
37 #define MAXPARA 10
38
39 #define COMMIT_INTERVAL 3 /* seconds */
40
41 typedef enum
42 {
43 BANDB_KLINE,
44 BANDB_DLINE,
45 BANDB_XLINE,
46 BANDB_RESV,
47 LAST_BANDB_TYPE
48 } bandb_type;
49
50 static char bandb_letter[LAST_BANDB_TYPE] = {
51 'K', 'D', 'X', 'R'
52 };
53
54 static const char *bandb_table[LAST_BANDB_TYPE] = {
55 "kline", "dline", "xline", "resv"
56 };
57
58
59 static rb_helper *bandb_helper;
60 static int in_transaction;
61
62 static void check_schema(void);
63
64 static void
65 bandb_commit(void *unused)
66 {
67 rsdb_transaction(RSDB_TRANS_END);
68 in_transaction = 0;
69 }
70
71 static void
72 parse_ban(bandb_type type, char *parv[], int parc)
73 {
74 const char *mask1 = NULL;
75 const char *mask2 = NULL;
76 const char *oper = NULL;
77 const char *curtime = NULL;
78 const char *reason = NULL;
79 const char *perm = NULL;
80 int para = 1;
81
82 if(type == BANDB_KLINE)
83 {
84 if(parc != 7)
85 return;
86 }
87 else if(parc != 6)
88 return;
89
90 mask1 = parv[para++];
91
92 if(type == BANDB_KLINE)
93 mask2 = parv[para++];
94
95 oper = parv[para++];
96 curtime = parv[para++];
97 perm = parv[para++];
98 reason = parv[para++];
99
100 if(!in_transaction)
101 {
102 rsdb_transaction(RSDB_TRANS_START);
103 in_transaction = 1;
104 rb_event_addonce("bandb_commit", bandb_commit, NULL,
105 COMMIT_INTERVAL);
106 }
107
108 rsdb_exec(NULL,
109 "INSERT INTO %s (mask1, mask2, oper, time, perm, reason) VALUES('%Q', '%Q', '%Q', %s, %s, '%Q')",
110 bandb_table[type], mask1, mask2 ? mask2 : "", oper, curtime, perm, reason);
111 }
112
113 static void
114 parse_unban(bandb_type type, char *parv[], int parc)
115 {
116 const char *mask1 = NULL;
117 const char *mask2 = NULL;
118
119 if(type == BANDB_KLINE)
120 {
121 if(parc != 3)
122 return;
123 }
124 else if(parc != 2)
125 return;
126
127 mask1 = parv[1];
128
129 if(type == BANDB_KLINE)
130 mask2 = parv[2];
131
132 if(!in_transaction)
133 {
134 rsdb_transaction(RSDB_TRANS_START);
135 in_transaction = 1;
136 rb_event_addonce("bandb_commit", bandb_commit, NULL,
137 COMMIT_INTERVAL);
138 }
139
140 rsdb_exec(NULL, "DELETE FROM %s WHERE mask1='%Q' AND mask2='%Q'",
141 bandb_table[type], mask1, mask2 ? mask2 : "");
142 }
143
144 static void
145 list_bans(void)
146 {
147 static char buf[512];
148 struct rsdb_table table;
149 int i, j;
150
151 /* schedule a clear of anything already pending */
152 rb_helper_write_queue(bandb_helper, "C");
153
154 for(i = 0; i < LAST_BANDB_TYPE; i++)
155 {
156 rsdb_exec_fetch(&table, "SELECT mask1,mask2,oper,reason FROM %s WHERE 1",
157 bandb_table[i]);
158
159 for(j = 0; j < table.row_count; j++)
160 {
161 if(i == BANDB_KLINE)
162 snprintf(buf, sizeof(buf), "%c %s %s %s :%s",
163 bandb_letter[i], table.row[j][0],
164 table.row[j][1], table.row[j][2], table.row[j][3]);
165 else
166 snprintf(buf, sizeof(buf), "%c %s %s :%s",
167 bandb_letter[i], table.row[j][0],
168 table.row[j][2], table.row[j][3]);
169
170 rb_helper_write_queue(bandb_helper, "%s", buf);
171 }
172
173 rsdb_exec_fetch_end(&table);
174 }
175
176 rb_helper_write(bandb_helper, "F");
177 }
178
179 static void
180 parse_request(rb_helper *helper)
181 {
182 static char *parv[MAXPARA + 1];
183 static char readbuf[READBUF_SIZE];
184 int parc;
185 int len;
186
187
188 while((len = rb_helper_read(helper, readbuf, sizeof(readbuf))) > 0)
189 {
190 parc = rb_string_to_array(readbuf, parv, MAXPARA);
191
192 if(parc < 1)
193 continue;
194
195 switch (parv[0][0])
196 {
197 case 'K':
198 parse_ban(BANDB_KLINE, parv, parc);
199 break;
200
201 case 'D':
202 parse_ban(BANDB_DLINE, parv, parc);
203 break;
204
205 case 'X':
206 parse_ban(BANDB_XLINE, parv, parc);
207 break;
208
209 case 'R':
210 parse_ban(BANDB_RESV, parv, parc);
211 break;
212
213 case 'k':
214 parse_unban(BANDB_KLINE, parv, parc);
215 break;
216
217 case 'd':
218 parse_unban(BANDB_DLINE, parv, parc);
219 break;
220
221 case 'x':
222 parse_unban(BANDB_XLINE, parv, parc);
223 break;
224
225 case 'r':
226 parse_unban(BANDB_RESV, parv, parc);
227 break;
228
229 case 'L':
230 list_bans();
231 break;
232 default:
233 break;
234 }
235 }
236 }
237
238
239 static void
240 error_cb(rb_helper *helper) __attribute__((noreturn));
241
242 static void
243 error_cb(rb_helper *helper)
244 {
245 if(in_transaction)
246 rsdb_transaction(RSDB_TRANS_END);
247 exit(1);
248 }
249
250 static void
251 dummy_handler(int sig)
252 {
253 return;
254 }
255
256 static void
257 setup_signals(void)
258 {
259 struct sigaction act;
260
261 act.sa_flags = 0;
262 act.sa_handler = SIG_IGN;
263 sigemptyset(&act.sa_mask);
264 sigaddset(&act.sa_mask, SIGPIPE);
265 sigaddset(&act.sa_mask, SIGALRM);
266 #ifdef SIGTRAP
267 sigaddset(&act.sa_mask, SIGTRAP);
268 #endif
269
270 #ifdef SIGWINCH
271 sigaddset(&act.sa_mask, SIGWINCH);
272 sigaction(SIGWINCH, &act, 0);
273 #endif
274 sigaction(SIGPIPE, &act, 0);
275 #ifdef SIGTRAP
276 sigaction(SIGTRAP, &act, 0);
277 #endif
278
279 act.sa_handler = dummy_handler;
280 sigaction(SIGALRM, &act, 0);
281 }
282
283
284 static void
285 db_error_cb(const char *errstr) __attribute__((noreturn));
286
287 static void
288 db_error_cb(const char *errstr)
289 {
290 char buf[256];
291 snprintf(buf, sizeof(buf), "! :%s", errstr);
292 rb_helper_write(bandb_helper, "%s", buf);
293 rb_sleep(1 << 30, 0);
294 exit(1);
295 }
296
297 int
298 main(int argc, char *argv[])
299 {
300 setup_signals();
301 bandb_helper = rb_helper_child(parse_request, error_cb, NULL, NULL, NULL, 256, 256, 256); /* XXX fix me */
302 if(bandb_helper == NULL)
303 {
304 fprintf(stderr,
305 "This is the solanum bandb for internal ircd use.\n");
306 fprintf(stderr,
307 "You aren't supposed to run me directly (did you want solanum-bantool?). Exiting.\n");
308 exit(1);
309 }
310 rsdb_init(db_error_cb);
311 check_schema();
312 rb_helper_loop(bandb_helper, 0);
313
314 return 0;
315 }
316
317 static void
318 check_schema(void)
319 {
320 struct rsdb_table table;
321 int i;
322
323 for(i = 0; i < LAST_BANDB_TYPE; i++)
324 {
325 rsdb_exec_fetch(&table,
326 "SELECT name FROM sqlite_master WHERE type='table' AND name='%s'",
327 bandb_table[i]);
328
329 rsdb_exec_fetch_end(&table);
330
331 if(!table.row_count)
332 rsdb_exec(NULL,
333 "CREATE TABLE %s (mask1 TEXT, mask2 TEXT, oper TEXT, time INTEGER, perm INTEGER, reason TEXT)",
334 bandb_table[i]);
335 }
336 }