]> jfr.im git - irc/rqf/shadowircd.git/blame - modules/m_set.c
Update TODO
[irc/rqf/shadowircd.git] / modules / m_set.c
CommitLineData
212380e3 1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * m_set.c: Sets a server parameter.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
23 *
f4ed5745 24 * $Id: m_set.c 3406 2007-04-13 19:06:53Z jilles $
212380e3 25 */
26
27/* rewritten by jdc */
28
29#include "stdinc.h"
30#include "client.h"
13ae2f4b 31#include "match.h"
212380e3 32#include "ircd.h"
33#include "numeric.h"
212380e3 34#include "s_serv.h"
35#include "send.h"
36#include "common.h"
37#include "channel.h"
38#include "s_conf.h"
39#include "s_newconf.h"
40#include "msg.h"
41#include "parse.h"
42#include "modules.h"
43
44static int mo_set(struct Client *, struct Client *, int, const char **);
45
46struct Message set_msgtab = {
47 "SET", 0, 0, 0, MFLG_SLOW,
48 {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_set, 0}}
49};
50
51mapi_clist_av1 set_clist[] = { &set_msgtab, NULL };
f4ed5745 52DECLARE_MODULE_AV1(set, NULL, NULL, set_clist, NULL, NULL, "$Revision: 3406 $");
212380e3 53
54/* Structure used for the SET table itself */
55struct SetStruct
56{
57 const char *name;
4cb8529c 58 void (*handler)(struct Client *source_p, const char *chararg, int intarg);
212380e3 59 int wants_char; /* 1 if it expects (char *, [int]) */
60 int wants_int; /* 1 if it expects ([char *], int) */
61
62 /* eg: 0, 1 == only an int arg
63 * eg: 1, 1 == char and int args */
64};
65
66
4cb8529c 67static void quote_adminstring(struct Client *, const char *, int);
6d18bf1a 68static void quote_autoconn(struct Client *, const char *, int);
4cb8529c
JT
69static void quote_autoconnall(struct Client *, const char *, int);
70static void quote_floodcount(struct Client *, const char *, int);
71static void quote_identtimeout(struct Client *, const char *, int);
72static void quote_max(struct Client *, const char *, int);
73static void quote_operstring(struct Client *, const char *, int);
74static void quote_spamnum(struct Client *, const char *, int);
75static void quote_spamtime(struct Client *, const char *, int);
76static void quote_splitmode(struct Client *, const char *, int);
77static void quote_splitnum(struct Client *, const char *, int);
78static void quote_splitusers(struct Client *, const char *, int);
79
212380e3 80static void list_quote_commands(struct Client *);
81
82
83/*
84 * If this ever needs to be expanded to more than one arg of each
85 * type, want_char/want_int could be the count of the arguments,
86 * instead of just a boolean flag...
87 *
88 * -davidt
89 */
90
91static struct SetStruct set_cmd_table[] = {
92 /* name function string arg int arg */
93 /* -------------------------------------------------------- */
94 {"ADMINSTRING", quote_adminstring, 1, 0 },
95 {"AUTOCONN", quote_autoconn, 1, 1 },
96 {"AUTOCONNALL", quote_autoconnall, 0, 1 },
97 {"FLOODCOUNT", quote_floodcount, 0, 1 },
98 {"IDENTTIMEOUT", quote_identtimeout, 0, 1 },
212380e3 99 {"MAX", quote_max, 0, 1 },
100 {"MAXCLIENTS", quote_max, 0, 1 },
101 {"OPERSTRING", quote_operstring, 1, 0 },
102 {"SPAMNUM", quote_spamnum, 0, 1 },
103 {"SPAMTIME", quote_spamtime, 0, 1 },
104 {"SPLITMODE", quote_splitmode, 1, 0 },
105 {"SPLITNUM", quote_splitnum, 0, 1 },
106 {"SPLITUSERS", quote_splitusers, 0, 1 },
107 /* -------------------------------------------------------- */
4cb8529c 108 {(char *) 0, (void (*)(struct Client *, const char *, int)) 0, 0, 0}
212380e3 109};
110
111
112/*
113 * list_quote_commands() sends the client all the available commands.
114 * Four to a line for now.
115 */
116static void
117list_quote_commands(struct Client *source_p)
118{
119 int i;
120 int j = 0;
121 const char *names[4];
122
5366977b 123 sendto_one_notice(source_p, ":Available QUOTE SET commands:");
212380e3 124
125 names[0] = names[1] = names[2] = names[3] = "";
126
127 for (i = 0; set_cmd_table[i].handler; i++)
128 {
129 names[j++] = set_cmd_table[i].name;
130
131 if(j > 3)
132 {
5366977b 133 sendto_one_notice(source_p, ":%s %s %s %s",
134 names[0], names[1], names[2], names[3]);
212380e3 135 j = 0;
136 names[0] = names[1] = names[2] = names[3] = "";
137 }
138
139 }
140 if(j)
5366977b 141 sendto_one_notice(source_p, ":%s %s %s %s",
142 names[0], names[1], names[2], names[3]);
212380e3 143}
144
145/* SET AUTOCONN */
146static void
6d18bf1a 147quote_autoconn(struct Client *source_p, const char *arg, int newval)
212380e3 148{
149 set_server_conf_autoconn(source_p, arg, newval);
150}
151
152/* SET AUTOCONNALL */
153static void
4cb8529c 154quote_autoconnall(struct Client *source_p, const char *arg, int newval)
212380e3 155{
156 if(newval >= 0)
157 {
158 sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has changed AUTOCONNALL to %i",
159 source_p->name, newval);
160
161 GlobalSetOptions.autoconn = newval;
162 }
163 else
164 {
5366977b 165 sendto_one_notice(source_p, ":AUTOCONNALL is currently %i",
166 GlobalSetOptions.autoconn);
212380e3 167 }
168}
169
170
171/* SET FLOODCOUNT */
172static void
4cb8529c 173quote_floodcount(struct Client *source_p, const char *arg, int newval)
212380e3 174{
175 if(newval >= 0)
176 {
177 GlobalSetOptions.floodcount = newval;
178 sendto_realops_snomask(SNO_GENERAL, L_ALL,
179 "%s has changed FLOODCOUNT to %i", source_p->name,
180 GlobalSetOptions.floodcount);
181 }
182 else
183 {
5366977b 184 sendto_one_notice(source_p, ":FLOODCOUNT is currently %i",
185 GlobalSetOptions.floodcount);
212380e3 186 }
187}
188
189/* SET IDENTTIMEOUT */
190static void
4cb8529c 191quote_identtimeout(struct Client *source_p, const char *arg, int newval)
212380e3 192{
193 if(!IsOperAdmin(source_p))
194 {
195 sendto_one(source_p, form_str(ERR_NOPRIVS),
196 me.name, source_p->name, "admin");
197 return;
198 }
199
200 if(newval > 0)
201 {
202 sendto_realops_snomask(SNO_GENERAL, L_ALL,
203 "%s has changed IDENTTIMEOUT to %d",
204 get_oper_name(source_p), newval);
205 GlobalSetOptions.ident_timeout = newval;
206 }
207 else
5366977b 208 sendto_one_notice(source_p, ":IDENTTIMEOUT is currently %d",
209 GlobalSetOptions.ident_timeout);
212380e3 210}
211
212380e3 212/* SET MAX */
213static void
4cb8529c 214quote_max(struct Client *source_p, const char *arg, int newval)
212380e3 215{
216 if(newval > 0)
217 {
b717a466
JT
218 if(newval > maxconnections - MAX_BUFFER)
219 {
220 sendto_one_notice(source_p,
221 ":You cannot set MAXCLIENTS to > %d",
222 maxconnections - MAX_BUFFER);
223 return;
6c70c576 224 }
225
212380e3 226 if(newval < 32)
227 {
3fe90825
VY
228 sendto_one_notice(source_p, ":You cannot set MAXCLIENTS to < 32 (%d:%d)",
229 GlobalSetOptions.maxclients, rb_getmaxconnect());
212380e3 230 return;
231 }
232
233 GlobalSetOptions.maxclients = newval;
234
235 sendto_realops_snomask(SNO_GENERAL, L_ALL,
236 "%s!%s@%s set new MAXCLIENTS to %d (%lu current)",
237 source_p->name, source_p->username, source_p->host,
238 GlobalSetOptions.maxclients,
08d11e34 239 rb_dlink_list_length(&lclient_list));
212380e3 240
241 return;
242 }
243 else
244 {
5366977b 245 sendto_one_notice(source_p, ":Current Maxclients = %d (%lu)",
08d11e34 246 GlobalSetOptions.maxclients, rb_dlink_list_length(&lclient_list));
212380e3 247 }
248}
249
250/* SET OPERSTRING */
251static void
4cb8529c 252quote_operstring(struct Client *source_p, const char *arg, int newval)
212380e3 253{
254 if(EmptyString(arg))
255 {
5366977b 256 sendto_one_notice(source_p, ":OPERSTRING is currently '%s'", GlobalSetOptions.operstring);
212380e3 257 }
258 else
259 {
907468c4 260 rb_strlcpy(GlobalSetOptions.operstring, arg,
212380e3 261 sizeof(GlobalSetOptions.operstring));
262
263 sendto_realops_snomask(SNO_GENERAL, L_ALL,
264 "%s has changed OPERSTRING to '%s'",
265 get_oper_name(source_p), arg);
266 }
267}
268
269/* SET ADMINSTRING */
270static void
4cb8529c 271quote_adminstring(struct Client *source_p, const char *arg, int newval)
212380e3 272{
273 if(EmptyString(arg))
274 {
5366977b 275 sendto_one_notice(source_p, ":ADMINSTRING is currently '%s'", GlobalSetOptions.adminstring);
212380e3 276 }
277 else
278 {
907468c4 279 rb_strlcpy(GlobalSetOptions.adminstring, arg,
212380e3 280 sizeof(GlobalSetOptions.adminstring));
281
282 sendto_realops_snomask(SNO_GENERAL, L_ALL,
283 "%s has changed ADMINSTRING to '%s'",
284 get_oper_name(source_p), arg);
285 }
286}
287
288/* SET SPAMNUM */
289static void
4cb8529c 290quote_spamnum(struct Client *source_p, const char *arg, int newval)
212380e3 291{
292 if(newval > 0)
293 {
294 if(newval == 0)
295 {
296 sendto_realops_snomask(SNO_GENERAL, L_ALL,
297 "%s has disabled ANTI_SPAMBOT", source_p->name);
298 GlobalSetOptions.spam_num = newval;
299 return;
300 }
301 if(newval < MIN_SPAM_NUM)
302 {
303 GlobalSetOptions.spam_num = MIN_SPAM_NUM;
304 }
305 else /* if (newval < MIN_SPAM_NUM) */
306 {
307 GlobalSetOptions.spam_num = newval;
308 }
309 sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has changed SPAMNUM to %i",
310 source_p->name, GlobalSetOptions.spam_num);
311 }
312 else
313 {
5366977b 314 sendto_one_notice(source_p, ":SPAMNUM is currently %i", GlobalSetOptions.spam_num);
212380e3 315 }
316}
317
318/* SET SPAMTIME */
319static void
4cb8529c 320quote_spamtime(struct Client *source_p, const char *arg, int newval)
212380e3 321{
322 if(newval > 0)
323 {
324 if(newval < MIN_SPAM_TIME)
325 {
326 GlobalSetOptions.spam_time = MIN_SPAM_TIME;
327 }
328 else /* if (newval < MIN_SPAM_TIME) */
329 {
330 GlobalSetOptions.spam_time = newval;
331 }
332 sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has changed SPAMTIME to %i",
333 source_p->name, GlobalSetOptions.spam_time);
334 }
335 else
336 {
5366977b 337 sendto_one_notice(source_p, ":SPAMTIME is currently %i", GlobalSetOptions.spam_time);
212380e3 338 }
339}
340
341/* this table is what splitmode may be set to */
342static const char *splitmode_values[] = {
343 "OFF",
344 "ON",
345 "AUTO",
346 NULL
347};
348
349/* this table is what splitmode may be */
350static const char *splitmode_status[] = {
351 "OFF",
352 "AUTO (OFF)",
353 "ON",
354 "AUTO (ON)",
355 NULL
356};
357
358/* SET SPLITMODE */
359static void
4cb8529c 360quote_splitmode(struct Client *source_p, const char *charval, int intval)
212380e3 361{
362 if(charval)
363 {
364 int newval;
365
366 for (newval = 0; splitmode_values[newval]; newval++)
367 {
368 if(!irccmp(splitmode_values[newval], charval))
369 break;
370 }
371
372 /* OFF */
373 if(newval == 0)
374 {
375 sendto_realops_snomask(SNO_GENERAL, L_ALL,
376 "%s is disabling splitmode", get_oper_name(source_p));
377
378 splitmode = 0;
379 splitchecking = 0;
380
ccfe0e97 381 rb_event_delete(check_splitmode_ev);
0ae330b4 382 check_splitmode_ev = NULL;
212380e3 383 }
384 /* ON */
385 else if(newval == 1)
386 {
387 sendto_realops_snomask(SNO_GENERAL, L_ALL,
388 "%s is enabling and activating splitmode",
389 get_oper_name(source_p));
390
391 splitmode = 1;
392 splitchecking = 0;
393
394 /* we might be deactivating an automatic splitmode, so pull the event */
ccfe0e97 395 rb_event_delete(check_splitmode_ev);
0ae330b4 396 check_splitmode_ev = NULL;
212380e3 397 }
398 /* AUTO */
399 else if(newval == 2)
400 {
401 sendto_realops_snomask(SNO_GENERAL, L_ALL,
402 "%s is enabling automatic splitmode",
403 get_oper_name(source_p));
404
405 splitchecking = 1;
406 check_splitmode(NULL);
407 }
408 }
409 else
410 /* if we add splitchecking to splitmode*2 we get a unique table to
411 * pull values back out of, splitmode can be four states - but you can
412 * only set to three, which means we cant use the same table --fl_
413 */
5366977b 414 sendto_one_notice(source_p, ":SPLITMODE is currently %s",
212380e3 415 splitmode_status[(splitchecking + (splitmode * 2))]);
416}
417
418/* SET SPLITNUM */
419static void
4cb8529c 420quote_splitnum(struct Client *source_p, const char *arg, int newval)
212380e3 421{
422 if(newval >= 0)
423 {
424 sendto_realops_snomask(SNO_GENERAL, L_ALL,
425 "%s has changed SPLITNUM to %i", source_p->name, newval);
426 split_servers = newval;
427
428 if(splitchecking)
429 check_splitmode(NULL);
430 }
431 else
5366977b 432 sendto_one_notice(source_p, ":SPLITNUM is currently %i", split_servers);
212380e3 433}
434
435/* SET SPLITUSERS */
436static void
4cb8529c 437quote_splitusers(struct Client *source_p, const char *arg, int newval)
212380e3 438{
439 if(newval >= 0)
440 {
441 sendto_realops_snomask(SNO_GENERAL, L_ALL,
442 "%s has changed SPLITUSERS to %i", source_p->name, newval);
443 split_users = newval;
444
445 if(splitchecking)
446 check_splitmode(NULL);
447 }
448 else
5366977b 449 sendto_one_notice(source_p, ":SPLITUSERS is currently %i", split_users);
212380e3 450}
451
452/*
453 * mo_set - SET command handler
454 * set options while running
455 */
456static int
457mo_set(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
458{
459 int newval;
460 int i, n;
461 const char *arg = NULL;
462 const char *intarg = NULL;
463
464 if(parc > 1)
465 {
466 /*
467 * Go through all the commands in set_cmd_table, until one is
468 * matched. I realize strcmp() is more intensive than a numeric
469 * lookup, but at least it's better than a big-ass switch/case
470 * statement.
471 */
472 for (i = 0; set_cmd_table[i].handler; i++)
473 {
474 if(!irccmp(set_cmd_table[i].name, parv[1]))
475 {
476 /*
477 * Command found; now execute the code
478 */
479 n = 2;
480
481 if(set_cmd_table[i].wants_char)
482 {
483 arg = parv[n++];
484 }
485
486 if(set_cmd_table[i].wants_int)
487 {
488 intarg = parv[n++];
489 }
490
491 if((n - 1) > parc)
492 {
5366977b 493 sendto_one_notice(source_p,
494 ":SET %s expects (\"%s%s\") args",
212380e3 495 set_cmd_table[i].name,
496 (set_cmd_table[i].
497 wants_char ? "string, " : ""),
498 (set_cmd_table[i].
499 wants_char ? "int" : ""));
500 return 0;
501 }
502
503 if(parc <= 2)
504 {
505 arg = NULL;
506 intarg = NULL;
507 }
508
509 if(set_cmd_table[i].wants_int && (parc > 2))
510 {
511 if(intarg)
512 {
513 if(!irccmp(intarg, "yes") || !irccmp(intarg, "on"))
514 newval = 1;
515 else if(!irccmp(intarg, "no")
516 || !irccmp(intarg, "off"))
517 newval = 0;
518 else
519 newval = atoi(intarg);
520 }
521 else
522 {
523 newval = -1;
524 }
525
526 if(newval < 0)
527 {
5366977b 528 sendto_one_notice(source_p,
529 ":Value less than 0 illegal for %s",
212380e3 530 set_cmd_table[i].name);
531
532 return 0;
533 }
534 }
535 else
536 newval = -1;
537
4cb8529c
JT
538 set_cmd_table[i].handler(source_p, arg, newval);
539 return 0;
212380e3 540 }
541 }
542
543 /*
544 * Code here will be executed when a /QUOTE SET command is not
545 * found within set_cmd_table.
546 */
5366977b 547 sendto_one_notice(source_p, ":Variable not found.");
212380e3 548 return 0;
549 }
550
551 list_quote_commands(source_p);
552
553 return 0;
554}