]> jfr.im git - solanum.git/blame - modules/m_set.c
extensions/umode_hide_idle_time: mask times for hidden sources (#373)
[solanum.git] / modules / m_set.c
CommitLineData
212380e3
AC
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
212380e3
AC
23 */
24
25/* rewritten by jdc */
26
27#include "stdinc.h"
28#include "client.h"
4562c604 29#include "match.h"
212380e3
AC
30#include "ircd.h"
31#include "numeric.h"
212380e3
AC
32#include "s_serv.h"
33#include "send.h"
212380e3
AC
34#include "channel.h"
35#include "s_conf.h"
36#include "s_newconf.h"
37#include "msg.h"
38#include "parse.h"
39#include "modules.h"
40
3abc337f 41static const char set_desc[] = "Provides the SET command to change server parameters";
212380e3 42
3c7d6fcc 43static void mo_set(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
eeabf33a 44
212380e3 45struct Message set_msgtab = {
7baa37a9 46 "SET", 0, 0, 0, 0,
212380e3
AC
47 {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_set, 0}}
48};
49
50mapi_clist_av1 set_clist[] = { &set_msgtab, NULL };
3abc337f 51DECLARE_MODULE_AV2(set, NULL, NULL, set_clist, NULL, NULL, NULL, NULL, set_desc);
212380e3
AC
52
53/* Structure used for the SET table itself */
54struct SetStruct
55{
56 const char *name;
21dc257c 57 void (*handler)(struct Client *source_p, const char *chararg, int intarg);
e34368b1
EM
58 bool wants_char; /* true if it expects (char *, [int]) */
59 bool wants_int; /* true if it expects ([char *], int) */
212380e3 60
e34368b1
EM
61 /* eg: false, true == only an int arg
62 * eg: true, true == char and int args */
212380e3
AC
63};
64
65
21dc257c 66static void quote_adminstring(struct Client *, const char *, int);
a3143c9b 67static void quote_autoconn(struct Client *, const char *, int);
21dc257c
JT
68static void quote_autoconnall(struct Client *, const char *, int);
69static void quote_floodcount(struct Client *, const char *, int);
70static void quote_identtimeout(struct Client *, const char *, int);
71static void quote_max(struct Client *, const char *, int);
72static void quote_operstring(struct Client *, const char *, int);
73static void quote_spamnum(struct Client *, const char *, int);
74static void quote_spamtime(struct Client *, const char *, int);
75static void quote_splitmode(struct Client *, const char *, int);
76static void quote_splitnum(struct Client *, const char *, int);
77static void quote_splitusers(struct Client *, const char *, int);
78
212380e3
AC
79static void list_quote_commands(struct Client *);
80
81
55abcbb2 82/*
212380e3
AC
83 * If this ever needs to be expanded to more than one arg of each
84 * type, want_char/want_int could be the count of the arguments,
85 * instead of just a boolean flag...
86 *
87 * -davidt
88 */
89
90static struct SetStruct set_cmd_table[] = {
e34368b1 91 /* name function string arg bool arg */
212380e3 92 /* -------------------------------------------------------- */
e34368b1
EM
93 {"ADMINSTRING", quote_adminstring, true, false },
94 {"AUTOCONN", quote_autoconn, true, true },
95 {"AUTOCONNALL", quote_autoconnall, false, true },
96 {"FLOODCOUNT", quote_floodcount, false, true },
97 {"IDENTTIMEOUT", quote_identtimeout, false, true },
98 {"MAX", quote_max, false, true },
99 {"MAXCLIENTS", quote_max, false, true },
100 {"OPERSTRING", quote_operstring, true, false },
101 {"SPAMNUM", quote_spamnum, false, true },
102 {"SPAMTIME", quote_spamtime, false, true },
103 {"SPLITMODE", quote_splitmode, true, false },
104 {"SPLITNUM", quote_splitnum, false, true },
105 {"SPLITUSERS", quote_splitusers, false, true },
212380e3 106 /* -------------------------------------------------------- */
e34368b1 107 {NULL, NULL, false, false },
212380e3
AC
108};
109
110
111/*
112 * list_quote_commands() sends the client all the available commands.
113 * Four to a line for now.
114 */
115static void
116list_quote_commands(struct Client *source_p)
117{
118 int i;
119 int j = 0;
120 const char *names[4];
121
5366977b 122 sendto_one_notice(source_p, ":Available QUOTE SET commands:");
212380e3
AC
123
124 names[0] = names[1] = names[2] = names[3] = "";
125
126 for (i = 0; set_cmd_table[i].handler; i++)
127 {
128 names[j++] = set_cmd_table[i].name;
129
130 if(j > 3)
131 {
5366977b
AC
132 sendto_one_notice(source_p, ":%s %s %s %s",
133 names[0], names[1], names[2], names[3]);
212380e3
AC
134 j = 0;
135 names[0] = names[1] = names[2] = names[3] = "";
136 }
137
138 }
139 if(j)
5366977b
AC
140 sendto_one_notice(source_p, ":%s %s %s %s",
141 names[0], names[1], names[2], names[3]);
212380e3
AC
142}
143
144/* SET AUTOCONN */
145static void
a3143c9b 146quote_autoconn(struct Client *source_p, const char *arg, int newval)
212380e3
AC
147{
148 set_server_conf_autoconn(source_p, arg, newval);
149}
150
151/* SET AUTOCONNALL */
152static void
21dc257c 153quote_autoconnall(struct Client *source_p, const char *arg, int newval)
212380e3
AC
154{
155 if(newval >= 0)
156 {
a9227555 157 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s has changed AUTOCONNALL to %i",
212380e3
AC
158 source_p->name, newval);
159
160 GlobalSetOptions.autoconn = newval;
161 }
162 else
163 {
5366977b
AC
164 sendto_one_notice(source_p, ":AUTOCONNALL is currently %i",
165 GlobalSetOptions.autoconn);
212380e3
AC
166 }
167}
168
169
170/* SET FLOODCOUNT */
171static void
21dc257c 172quote_floodcount(struct Client *source_p, const char *arg, int newval)
212380e3
AC
173{
174 if(newval >= 0)
175 {
176 GlobalSetOptions.floodcount = newval;
a9227555 177 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
212380e3
AC
178 "%s has changed FLOODCOUNT to %i", source_p->name,
179 GlobalSetOptions.floodcount);
180 }
181 else
182 {
5366977b
AC
183 sendto_one_notice(source_p, ":FLOODCOUNT is currently %i",
184 GlobalSetOptions.floodcount);
212380e3
AC
185 }
186}
187
188/* SET IDENTTIMEOUT */
189static void
21dc257c 190quote_identtimeout(struct Client *source_p, const char *arg, int newval)
212380e3
AC
191{
192 if(!IsOperAdmin(source_p))
193 {
194 sendto_one(source_p, form_str(ERR_NOPRIVS),
195 me.name, source_p->name, "admin");
196 return;
197 }
198
199 if(newval > 0)
200 {
a9227555 201 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
212380e3
AC
202 "%s has changed IDENTTIMEOUT to %d",
203 get_oper_name(source_p), newval);
204 GlobalSetOptions.ident_timeout = newval;
d3f6b808 205 set_authd_timeout("ident_timeout", newval);
212380e3
AC
206 }
207 else
5366977b
AC
208 sendto_one_notice(source_p, ":IDENTTIMEOUT is currently %d",
209 GlobalSetOptions.ident_timeout);
212380e3
AC
210}
211
212380e3
AC
212/* SET MAX */
213static void
21dc257c 214quote_max(struct Client *source_p, const char *arg, int newval)
212380e3
AC
215{
216 if(newval > 0)
217 {
8bd5767b
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
JT
224 }
225
212380e3
AC
226 if(newval < 32)
227 {
101db4c4
VY
228 sendto_one_notice(source_p, ":You cannot set MAXCLIENTS to < 32 (%d:%d)",
229 GlobalSetOptions.maxclients, rb_getmaxconnect());
212380e3
AC
230 return;
231 }
232
233 GlobalSetOptions.maxclients = newval;
234
a9227555 235 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
212380e3
AC
236 "%s!%s@%s set new MAXCLIENTS to %d (%lu current)",
237 source_p->name, source_p->username, source_p->host,
55abcbb2 238 GlobalSetOptions.maxclients,
5b96d9a6 239 rb_dlink_list_length(&lclient_list));
212380e3
AC
240
241 return;
242 }
243 else
244 {
5366977b 245 sendto_one_notice(source_p, ":Current Maxclients = %d (%lu)",
5b96d9a6 246 GlobalSetOptions.maxclients, rb_dlink_list_length(&lclient_list));
212380e3
AC
247 }
248}
249
250/* SET OPERSTRING */
251static void
21dc257c 252quote_operstring(struct Client *source_p, const char *arg, int newval)
212380e3
AC
253{
254 if(EmptyString(arg))
255 {
5366977b 256 sendto_one_notice(source_p, ":OPERSTRING is currently '%s'", GlobalSetOptions.operstring);
212380e3
AC
257 }
258 else
259 {
f427c8b0 260 rb_strlcpy(GlobalSetOptions.operstring, arg,
212380e3 261 sizeof(GlobalSetOptions.operstring));
55abcbb2 262
a9227555 263 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
212380e3
AC
264 "%s has changed OPERSTRING to '%s'",
265 get_oper_name(source_p), arg);
266 }
267}
268
269/* SET ADMINSTRING */
270static void
21dc257c 271quote_adminstring(struct Client *source_p, const char *arg, int newval)
212380e3
AC
272{
273 if(EmptyString(arg))
274 {
5366977b 275 sendto_one_notice(source_p, ":ADMINSTRING is currently '%s'", GlobalSetOptions.adminstring);
212380e3
AC
276 }
277 else
278 {
f427c8b0 279 rb_strlcpy(GlobalSetOptions.adminstring, arg,
212380e3 280 sizeof(GlobalSetOptions.adminstring));
55abcbb2 281
a9227555 282 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
212380e3
AC
283 "%s has changed ADMINSTRING to '%s'",
284 get_oper_name(source_p), arg);
285 }
286}
287
288/* SET SPAMNUM */
289static void
21dc257c 290quote_spamnum(struct Client *source_p, const char *arg, int newval)
212380e3
AC
291{
292 if(newval > 0)
293 {
294 if(newval == 0)
295 {
a9227555 296 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
212380e3
AC
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 }
a9227555 309 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s has changed SPAMNUM to %i",
212380e3
AC
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
AC
315 }
316}
317
318/* SET SPAMTIME */
319static void
21dc257c 320quote_spamtime(struct Client *source_p, const char *arg, int newval)
212380e3
AC
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 }
a9227555 332 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s has changed SPAMTIME to %i",
212380e3
AC
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
AC
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
21dc257c 360quote_splitmode(struct Client *source_p, const char *charval, int intval)
212380e3
AC
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 {
a9227555 375 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
212380e3
AC
376 "%s is disabling splitmode", get_oper_name(source_p));
377
e34368b1
EM
378 splitmode = false;
379 splitchecking = false;
212380e3 380
fa832850 381 rb_event_delete(check_splitmode_ev);
6a309903 382 check_splitmode_ev = NULL;
212380e3
AC
383 }
384 /* ON */
385 else if(newval == 1)
386 {
a9227555 387 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
212380e3
AC
388 "%s is enabling and activating splitmode",
389 get_oper_name(source_p));
390
e34368b1
EM
391 splitmode = true;
392 splitchecking = false;
212380e3
AC
393
394 /* we might be deactivating an automatic splitmode, so pull the event */
fa832850 395 rb_event_delete(check_splitmode_ev);
6a309903 396 check_splitmode_ev = NULL;
212380e3
AC
397 }
398 /* AUTO */
399 else if(newval == 2)
400 {
a9227555 401 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
212380e3
AC
402 "%s is enabling automatic splitmode",
403 get_oper_name(source_p));
404
e34368b1 405 splitchecking = true;
212380e3
AC
406 check_splitmode(NULL);
407 }
408 }
409 else
55abcbb2 410 /* if we add splitchecking to splitmode*2 we get a unique table to
212380e3
AC
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
AC
415 splitmode_status[(splitchecking + (splitmode * 2))]);
416}
417
418/* SET SPLITNUM */
419static void
21dc257c 420quote_splitnum(struct Client *source_p, const char *arg, int newval)
212380e3
AC
421{
422 if(newval >= 0)
423 {
a9227555 424 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
212380e3
AC
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
AC
433}
434
435/* SET SPLITUSERS */
436static void
21dc257c 437quote_splitusers(struct Client *source_p, const char *arg, int newval)
212380e3
AC
438{
439 if(newval >= 0)
440 {
a9227555 441 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
212380e3
AC
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
AC
450}
451
452/*
453 * mo_set - SET command handler
454 * set options while running
455 */
3c7d6fcc 456static void
428ca87b 457mo_set(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3
AC
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
AC
493 sendto_one_notice(source_p,
494 ":SET %s expects (\"%s%s\") args",
212380e3
AC
495 set_cmd_table[i].name,
496 (set_cmd_table[i].
497 wants_char ? "string, " : ""),
498 (set_cmd_table[i].
499 wants_char ? "int" : ""));
3c7d6fcc 500 return;
212380e3
AC
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
AC
528 sendto_one_notice(source_p,
529 ":Value less than 0 illegal for %s",
212380e3
AC
530 set_cmd_table[i].name);
531
3c7d6fcc 532 return;
212380e3
AC
533 }
534 }
535 else
536 newval = -1;
537
21dc257c 538 set_cmd_table[i].handler(source_p, arg, newval);
3c7d6fcc 539 return;
212380e3
AC
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.");
3c7d6fcc 548 return;
212380e3
AC
549 }
550
551 list_quote_commands(source_p);
212380e3 552}