]> jfr.im git - irc/rqf/shadowircd.git/blame - modules/m_set.c
Do not install ban .conf files (like kline.conf, rsv.conf, etc) as they aren't used...
[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 *
212380e3 24 */
25
26/* rewritten by jdc */
27
28#include "stdinc.h"
29#include "client.h"
13ae2f4b 30#include "match.h"
212380e3 31#include "ircd.h"
32#include "numeric.h"
212380e3 33#include "s_serv.h"
34#include "send.h"
35#include "common.h"
36#include "channel.h"
37#include "s_conf.h"
67537fef 38#include "s_user.h"
212380e3 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);
67537fef 74static void quote_operhost(struct Client *, const char *, int);
4cb8529c
JT
75static void quote_spamnum(struct Client *, const char *, int);
76static void quote_spamtime(struct Client *, const char *, int);
77static void quote_splitmode(struct Client *, const char *, int);
78static void quote_splitnum(struct Client *, const char *, int);
79static void quote_splitusers(struct Client *, const char *, int);
80
212380e3 81static void list_quote_commands(struct Client *);
82
83
84/*
85 * If this ever needs to be expanded to more than one arg of each
86 * type, want_char/want_int could be the count of the arguments,
87 * instead of just a boolean flag...
88 *
89 * -davidt
90 */
91
92static struct SetStruct set_cmd_table[] = {
93 /* name function string arg int arg */
94 /* -------------------------------------------------------- */
95 {"ADMINSTRING", quote_adminstring, 1, 0 },
96 {"AUTOCONN", quote_autoconn, 1, 1 },
97 {"AUTOCONNALL", quote_autoconnall, 0, 1 },
98 {"FLOODCOUNT", quote_floodcount, 0, 1 },
99 {"IDENTTIMEOUT", quote_identtimeout, 0, 1 },
212380e3 100 {"MAX", quote_max, 0, 1 },
101 {"MAXCLIENTS", quote_max, 0, 1 },
67537fef 102 {"OPERHOST", quote_operhost, 1, 0 },
212380e3 103 {"OPERSTRING", quote_operstring, 1, 0 },
104 {"SPAMNUM", quote_spamnum, 0, 1 },
105 {"SPAMTIME", quote_spamtime, 0, 1 },
106 {"SPLITMODE", quote_splitmode, 1, 0 },
107 {"SPLITNUM", quote_splitnum, 0, 1 },
108 {"SPLITUSERS", quote_splitusers, 0, 1 },
109 /* -------------------------------------------------------- */
4cb8529c 110 {(char *) 0, (void (*)(struct Client *, const char *, int)) 0, 0, 0}
212380e3 111};
112
113
114/*
115 * list_quote_commands() sends the client all the available commands.
116 * Four to a line for now.
117 */
118static void
119list_quote_commands(struct Client *source_p)
120{
121 int i;
122 int j = 0;
123 const char *names[4];
124
5366977b 125 sendto_one_notice(source_p, ":Available QUOTE SET commands:");
212380e3 126
127 names[0] = names[1] = names[2] = names[3] = "";
128
129 for (i = 0; set_cmd_table[i].handler; i++)
130 {
131 names[j++] = set_cmd_table[i].name;
132
133 if(j > 3)
134 {
5366977b 135 sendto_one_notice(source_p, ":%s %s %s %s",
136 names[0], names[1], names[2], names[3]);
212380e3 137 j = 0;
138 names[0] = names[1] = names[2] = names[3] = "";
139 }
140
141 }
142 if(j)
5366977b 143 sendto_one_notice(source_p, ":%s %s %s %s",
144 names[0], names[1], names[2], names[3]);
212380e3 145}
146
147/* SET AUTOCONN */
148static void
6d18bf1a 149quote_autoconn(struct Client *source_p, const char *arg, int newval)
212380e3 150{
151 set_server_conf_autoconn(source_p, arg, newval);
152}
153
154/* SET AUTOCONNALL */
155static void
4cb8529c 156quote_autoconnall(struct Client *source_p, const char *arg, int newval)
212380e3 157{
158 if(newval >= 0)
159 {
160 sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has changed AUTOCONNALL to %i",
161 source_p->name, newval);
162
163 GlobalSetOptions.autoconn = newval;
164 }
165 else
166 {
5366977b 167 sendto_one_notice(source_p, ":AUTOCONNALL is currently %i",
168 GlobalSetOptions.autoconn);
212380e3 169 }
170}
171
172
173/* SET FLOODCOUNT */
174static void
4cb8529c 175quote_floodcount(struct Client *source_p, const char *arg, int newval)
212380e3 176{
177 if(newval >= 0)
178 {
179 GlobalSetOptions.floodcount = newval;
180 sendto_realops_snomask(SNO_GENERAL, L_ALL,
181 "%s has changed FLOODCOUNT to %i", source_p->name,
182 GlobalSetOptions.floodcount);
183 }
184 else
185 {
5366977b 186 sendto_one_notice(source_p, ":FLOODCOUNT is currently %i",
187 GlobalSetOptions.floodcount);
212380e3 188 }
189}
190
191/* SET IDENTTIMEOUT */
192static void
4cb8529c 193quote_identtimeout(struct Client *source_p, const char *arg, int newval)
212380e3 194{
195 if(!IsOperAdmin(source_p))
196 {
197 sendto_one(source_p, form_str(ERR_NOPRIVS),
198 me.name, source_p->name, "admin");
199 return;
200 }
201
202 if(newval > 0)
203 {
204 sendto_realops_snomask(SNO_GENERAL, L_ALL,
205 "%s has changed IDENTTIMEOUT to %d",
206 get_oper_name(source_p), newval);
207 GlobalSetOptions.ident_timeout = newval;
208 }
209 else
5366977b 210 sendto_one_notice(source_p, ":IDENTTIMEOUT is currently %d",
211 GlobalSetOptions.ident_timeout);
212380e3 212}
213
212380e3 214/* SET MAX */
215static void
4cb8529c 216quote_max(struct Client *source_p, const char *arg, int newval)
212380e3 217{
218 if(newval > 0)
219 {
b717a466
JT
220 if(newval > maxconnections - MAX_BUFFER)
221 {
222 sendto_one_notice(source_p,
223 ":You cannot set MAXCLIENTS to > %d",
224 maxconnections - MAX_BUFFER);
225 return;
6c70c576 226 }
227
212380e3 228 if(newval < 32)
229 {
3fe90825
VY
230 sendto_one_notice(source_p, ":You cannot set MAXCLIENTS to < 32 (%d:%d)",
231 GlobalSetOptions.maxclients, rb_getmaxconnect());
212380e3 232 return;
233 }
234
235 GlobalSetOptions.maxclients = newval;
236
237 sendto_realops_snomask(SNO_GENERAL, L_ALL,
238 "%s!%s@%s set new MAXCLIENTS to %d (%lu current)",
239 source_p->name, source_p->username, source_p->host,
240 GlobalSetOptions.maxclients,
08d11e34 241 rb_dlink_list_length(&lclient_list));
212380e3 242
243 return;
244 }
245 else
246 {
5366977b 247 sendto_one_notice(source_p, ":Current Maxclients = %d (%lu)",
08d11e34 248 GlobalSetOptions.maxclients, rb_dlink_list_length(&lclient_list));
212380e3 249 }
250}
251
67537fef
G
252/* SET OPERHOST */
253static void
254quote_operhost(struct Client *source_p, const char *arg, int newval)
255{
256 if(EmptyString(arg))
257 {
258 sendto_one_notice(source_p, ":OPERHOST is currently '%s'", GlobalSetOptions.operhost);
259 }
260 else if(!valid_hostname(arg))
261 {
262 sendto_one_notice(source_p, "Invalid hostmask.");
263 }
264 else
265 {
266 rb_strlcpy(GlobalSetOptions.operhost, arg,
267 sizeof(GlobalSetOptions.operhost));
268
269 sendto_realops_snomask(SNO_GENERAL, L_ALL,
270 "%s has changed OPERHOST to '%s'",
271 get_oper_name(source_p), arg);
272 }
273}
274
212380e3 275/* SET OPERSTRING */
276static void
4cb8529c 277quote_operstring(struct Client *source_p, const char *arg, int newval)
212380e3 278{
279 if(EmptyString(arg))
280 {
5366977b 281 sendto_one_notice(source_p, ":OPERSTRING is currently '%s'", GlobalSetOptions.operstring);
212380e3 282 }
283 else
284 {
907468c4 285 rb_strlcpy(GlobalSetOptions.operstring, arg,
212380e3 286 sizeof(GlobalSetOptions.operstring));
287
288 sendto_realops_snomask(SNO_GENERAL, L_ALL,
289 "%s has changed OPERSTRING to '%s'",
290 get_oper_name(source_p), arg);
291 }
292}
293
294/* SET ADMINSTRING */
295static void
4cb8529c 296quote_adminstring(struct Client *source_p, const char *arg, int newval)
212380e3 297{
298 if(EmptyString(arg))
299 {
5366977b 300 sendto_one_notice(source_p, ":ADMINSTRING is currently '%s'", GlobalSetOptions.adminstring);
212380e3 301 }
302 else
303 {
907468c4 304 rb_strlcpy(GlobalSetOptions.adminstring, arg,
212380e3 305 sizeof(GlobalSetOptions.adminstring));
306
307 sendto_realops_snomask(SNO_GENERAL, L_ALL,
308 "%s has changed ADMINSTRING to '%s'",
309 get_oper_name(source_p), arg);
310 }
311}
312
313/* SET SPAMNUM */
314static void
4cb8529c 315quote_spamnum(struct Client *source_p, const char *arg, int newval)
212380e3 316{
317 if(newval > 0)
318 {
319 if(newval == 0)
320 {
321 sendto_realops_snomask(SNO_GENERAL, L_ALL,
322 "%s has disabled ANTI_SPAMBOT", source_p->name);
323 GlobalSetOptions.spam_num = newval;
324 return;
325 }
326 if(newval < MIN_SPAM_NUM)
327 {
328 GlobalSetOptions.spam_num = MIN_SPAM_NUM;
329 }
330 else /* if (newval < MIN_SPAM_NUM) */
331 {
332 GlobalSetOptions.spam_num = newval;
333 }
334 sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has changed SPAMNUM to %i",
335 source_p->name, GlobalSetOptions.spam_num);
336 }
337 else
338 {
5366977b 339 sendto_one_notice(source_p, ":SPAMNUM is currently %i", GlobalSetOptions.spam_num);
212380e3 340 }
341}
342
343/* SET SPAMTIME */
344static void
4cb8529c 345quote_spamtime(struct Client *source_p, const char *arg, int newval)
212380e3 346{
347 if(newval > 0)
348 {
349 if(newval < MIN_SPAM_TIME)
350 {
351 GlobalSetOptions.spam_time = MIN_SPAM_TIME;
352 }
353 else /* if (newval < MIN_SPAM_TIME) */
354 {
355 GlobalSetOptions.spam_time = newval;
356 }
357 sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has changed SPAMTIME to %i",
358 source_p->name, GlobalSetOptions.spam_time);
359 }
360 else
361 {
5366977b 362 sendto_one_notice(source_p, ":SPAMTIME is currently %i", GlobalSetOptions.spam_time);
212380e3 363 }
364}
365
366/* this table is what splitmode may be set to */
367static const char *splitmode_values[] = {
368 "OFF",
369 "ON",
370 "AUTO",
371 NULL
372};
373
374/* this table is what splitmode may be */
375static const char *splitmode_status[] = {
376 "OFF",
377 "AUTO (OFF)",
378 "ON",
379 "AUTO (ON)",
380 NULL
381};
382
383/* SET SPLITMODE */
384static void
4cb8529c 385quote_splitmode(struct Client *source_p, const char *charval, int intval)
212380e3 386{
387 if(charval)
388 {
389 int newval;
390
391 for (newval = 0; splitmode_values[newval]; newval++)
392 {
393 if(!irccmp(splitmode_values[newval], charval))
394 break;
395 }
396
397 /* OFF */
398 if(newval == 0)
399 {
400 sendto_realops_snomask(SNO_GENERAL, L_ALL,
401 "%s is disabling splitmode", get_oper_name(source_p));
402
403 splitmode = 0;
404 splitchecking = 0;
405
ccfe0e97 406 rb_event_delete(check_splitmode_ev);
0ae330b4 407 check_splitmode_ev = NULL;
212380e3 408 }
409 /* ON */
410 else if(newval == 1)
411 {
412 sendto_realops_snomask(SNO_GENERAL, L_ALL,
413 "%s is enabling and activating splitmode",
414 get_oper_name(source_p));
415
416 splitmode = 1;
417 splitchecking = 0;
418
419 /* we might be deactivating an automatic splitmode, so pull the event */
ccfe0e97 420 rb_event_delete(check_splitmode_ev);
0ae330b4 421 check_splitmode_ev = NULL;
212380e3 422 }
423 /* AUTO */
424 else if(newval == 2)
425 {
426 sendto_realops_snomask(SNO_GENERAL, L_ALL,
427 "%s is enabling automatic splitmode",
428 get_oper_name(source_p));
429
430 splitchecking = 1;
431 check_splitmode(NULL);
432 }
433 }
434 else
435 /* if we add splitchecking to splitmode*2 we get a unique table to
436 * pull values back out of, splitmode can be four states - but you can
437 * only set to three, which means we cant use the same table --fl_
438 */
5366977b 439 sendto_one_notice(source_p, ":SPLITMODE is currently %s",
212380e3 440 splitmode_status[(splitchecking + (splitmode * 2))]);
441}
442
443/* SET SPLITNUM */
444static void
4cb8529c 445quote_splitnum(struct Client *source_p, const char *arg, int newval)
212380e3 446{
447 if(newval >= 0)
448 {
449 sendto_realops_snomask(SNO_GENERAL, L_ALL,
450 "%s has changed SPLITNUM to %i", source_p->name, newval);
451 split_servers = newval;
452
453 if(splitchecking)
454 check_splitmode(NULL);
455 }
456 else
5366977b 457 sendto_one_notice(source_p, ":SPLITNUM is currently %i", split_servers);
212380e3 458}
459
460/* SET SPLITUSERS */
461static void
4cb8529c 462quote_splitusers(struct Client *source_p, const char *arg, int newval)
212380e3 463{
464 if(newval >= 0)
465 {
466 sendto_realops_snomask(SNO_GENERAL, L_ALL,
467 "%s has changed SPLITUSERS to %i", source_p->name, newval);
468 split_users = newval;
469
470 if(splitchecking)
471 check_splitmode(NULL);
472 }
473 else
5366977b 474 sendto_one_notice(source_p, ":SPLITUSERS is currently %i", split_users);
212380e3 475}
476
477/*
478 * mo_set - SET command handler
479 * set options while running
480 */
481static int
482mo_set(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
483{
484 int newval;
485 int i, n;
486 const char *arg = NULL;
487 const char *intarg = NULL;
488
489 if(parc > 1)
490 {
491 /*
492 * Go through all the commands in set_cmd_table, until one is
493 * matched. I realize strcmp() is more intensive than a numeric
494 * lookup, but at least it's better than a big-ass switch/case
495 * statement.
496 */
497 for (i = 0; set_cmd_table[i].handler; i++)
498 {
499 if(!irccmp(set_cmd_table[i].name, parv[1]))
500 {
501 /*
502 * Command found; now execute the code
503 */
504 n = 2;
505
506 if(set_cmd_table[i].wants_char)
507 {
508 arg = parv[n++];
509 }
510
511 if(set_cmd_table[i].wants_int)
512 {
513 intarg = parv[n++];
514 }
515
516 if((n - 1) > parc)
517 {
5366977b 518 sendto_one_notice(source_p,
519 ":SET %s expects (\"%s%s\") args",
212380e3 520 set_cmd_table[i].name,
521 (set_cmd_table[i].
522 wants_char ? "string, " : ""),
523 (set_cmd_table[i].
524 wants_char ? "int" : ""));
525 return 0;
526 }
527
528 if(parc <= 2)
529 {
530 arg = NULL;
531 intarg = NULL;
532 }
533
534 if(set_cmd_table[i].wants_int && (parc > 2))
535 {
536 if(intarg)
537 {
538 if(!irccmp(intarg, "yes") || !irccmp(intarg, "on"))
539 newval = 1;
540 else if(!irccmp(intarg, "no")
541 || !irccmp(intarg, "off"))
542 newval = 0;
543 else
544 newval = atoi(intarg);
545 }
546 else
547 {
548 newval = -1;
549 }
550
551 if(newval < 0)
552 {
5366977b 553 sendto_one_notice(source_p,
554 ":Value less than 0 illegal for %s",
212380e3 555 set_cmd_table[i].name);
556
557 return 0;
558 }
559 }
560 else
561 newval = -1;
562
4cb8529c
JT
563 set_cmd_table[i].handler(source_p, arg, newval);
564 return 0;
212380e3 565 }
566 }
567
568 /*
569 * Code here will be executed when a /QUOTE SET command is not
570 * found within set_cmd_table.
571 */
5366977b 572 sendto_one_notice(source_p, ":Variable not found.");
212380e3 573 return 0;
574 }
575
576 list_quote_commands(source_p);
577
578 return 0;
579}