Remove cruft left behind by removed stats_p_hook.
[seven-1.x.git] / modules / m_set.c
blob26d1ba13fe008cd7702fe4c82cc52f515b267b22
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * m_set.c: Sets a server parameter.
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
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.
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.
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
25 /* rewritten by jdc */
27 #include "stdinc.h"
28 #include "client.h"
29 #include "event.h"
30 #include "irc_string.h"
31 #include "sprintf_irc.h"
32 #include "ircd.h"
33 #include "numeric.h"
34 #include "commio.h"
35 #include "s_serv.h"
36 #include "send.h"
37 #include "common.h"
38 #include "channel.h"
39 #include "s_conf.h"
40 #include "s_newconf.h"
41 #include "msg.h"
42 #include "parse.h"
43 #include "modules.h"
45 static int mo_set(struct Client *, struct Client *, int, const char **);
47 struct Message set_msgtab = {
48 "SET", 0, 0, 0, MFLG_SLOW,
49 {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_set, 0}}
52 mapi_clist_av1 set_clist[] = { &set_msgtab, NULL };
53 DECLARE_MODULE_AV1(set, NULL, NULL, set_clist, NULL, NULL, "$Revision: 147 $");
55 /* Structure used for the SET table itself */
56 struct SetStruct
58 const char *name;
59 void (*handler) ();
60 int wants_char; /* 1 if it expects (char *, [int]) */
61 int wants_int; /* 1 if it expects ([char *], int) */
63 /* eg: 0, 1 == only an int arg
64 * eg: 1, 1 == char and int args */
68 static void quote_adminstring(struct Client *, const char *);
69 static void quote_autoconn(struct Client *, char *, int);
70 static void quote_autoconnall(struct Client *, int);
71 static void quote_floodcount(struct Client *, int);
72 static void quote_identtimeout(struct Client *, int);
73 static void quote_idletime(struct Client *, int);
74 static void quote_max(struct Client *, int);
75 static void quote_operstring(struct Client *, const char *);
76 static void quote_spamnum(struct Client *, int);
77 static void quote_spamtime(struct Client *, int);
78 static void quote_splitmode(struct Client *, char *);
79 static void quote_splitnum(struct Client *, int);
80 static void quote_splitusers(struct Client *, int);
81 static void list_quote_commands(struct Client *);
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...
89 * -davidt
92 static 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 },
100 {"IDLETIME", quote_idletime, 0, 1 },
101 {"MAX", quote_max, 0, 1 },
102 {"MAXCLIENTS", quote_max, 0, 1 },
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 /* -------------------------------------------------------- */
110 {(char *) 0, (void (*)()) 0, 0, 0}
115 * list_quote_commands() sends the client all the available commands.
116 * Four to a line for now.
118 static void
119 list_quote_commands(struct Client *source_p)
121 int i;
122 int j = 0;
123 const char *names[4];
125 sendto_one(source_p, ":%s NOTICE %s :Available QUOTE SET commands:",
126 me.name, source_p->name);
128 names[0] = names[1] = names[2] = names[3] = "";
130 for (i = 0; set_cmd_table[i].handler; i++)
132 names[j++] = set_cmd_table[i].name;
134 if(j > 3)
136 sendto_one(source_p, ":%s NOTICE %s :%s %s %s %s",
137 me.name, source_p->name, names[0], names[1], names[2], names[3]);
138 j = 0;
139 names[0] = names[1] = names[2] = names[3] = "";
143 if(j)
144 sendto_one(source_p, ":%s NOTICE %s :%s %s %s %s",
145 me.name, source_p->name, names[0], names[1], names[2], names[3]);
148 /* SET AUTOCONN */
149 static void
150 quote_autoconn(struct Client *source_p, char *arg, int newval)
152 set_server_conf_autoconn(source_p, arg, newval);
155 /* SET AUTOCONNALL */
156 static void
157 quote_autoconnall(struct Client *source_p, int newval)
159 if(newval >= 0)
161 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s has changed AUTOCONNALL to %i",
162 source_p->name, newval);
164 GlobalSetOptions.autoconn = newval;
166 else
168 sendto_one(source_p, ":%s NOTICE %s :AUTOCONNALL is currently %i",
169 me.name, source_p->name, GlobalSetOptions.autoconn);
174 /* SET FLOODCOUNT */
175 static void
176 quote_floodcount(struct Client *source_p, int newval)
178 if(newval >= 0)
180 GlobalSetOptions.floodcount = newval;
181 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
182 "%s has changed FLOODCOUNT to %i", source_p->name,
183 GlobalSetOptions.floodcount);
185 else
187 sendto_one(source_p, ":%s NOTICE %s :FLOODCOUNT is currently %i",
188 me.name, source_p->name, GlobalSetOptions.floodcount);
192 /* SET IDENTTIMEOUT */
193 static void
194 quote_identtimeout(struct Client *source_p, int newval)
196 if(!IsOperAdmin(source_p))
198 sendto_one(source_p, form_str(ERR_NOPRIVS),
199 me.name, source_p->name, "admin");
200 return;
203 if(newval > 0)
205 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
206 "%s has changed IDENTTIMEOUT to %d",
207 get_oper_name(source_p), newval);
208 GlobalSetOptions.ident_timeout = newval;
210 else
211 sendto_one(source_p, ":%s NOTICE %s :IDENTTIMEOUT is currently %d",
212 me.name, source_p->name, GlobalSetOptions.ident_timeout);
215 /* SET IDLETIME */
216 static void
217 quote_idletime(struct Client *source_p, int newval)
219 if(newval >= 0)
221 if(newval == 0)
223 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
224 "%s has disabled idletime checking", source_p->name);
225 GlobalSetOptions.idletime = 0;
227 else
229 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
230 "%s has changed IDLETIME to %i",
231 source_p->name, newval);
232 GlobalSetOptions.idletime = (newval * 60);
235 else
237 sendto_one(source_p, ":%s NOTICE %s :IDLETIME is currently %i",
238 me.name, source_p->name, GlobalSetOptions.idletime / 60);
242 /* SET MAX */
243 static void
244 quote_max(struct Client *source_p, int newval)
246 if(newval > 0)
248 if(newval > MASTER_MAX)
250 sendto_one(source_p,
251 ":%s NOTICE %s :You cannot set MAXCLIENTS to > MASTER_MAX (%d)",
252 me.name, source_p->name, MASTER_MAX);
253 return;
256 if(newval < 32)
258 sendto_one(source_p,
259 ":%s NOTICE %s :You cannot set MAXCLIENTS to < 32 (%d:%d)",
260 me.name, source_p->name, GlobalSetOptions.maxclients,
261 highest_fd);
262 return;
265 GlobalSetOptions.maxclients = newval;
267 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
268 "%s!%s@%s set new MAXCLIENTS to %d (%lu current)",
269 source_p->name, source_p->username, source_p->host,
270 GlobalSetOptions.maxclients,
271 dlink_list_length(&lclient_list));
273 return;
275 else
277 sendto_one(source_p, ":%s NOTICE %s :Current Maxclients = %d (%lu)",
278 me.name, source_p->name, GlobalSetOptions.maxclients,
279 dlink_list_length(&lclient_list));
283 /* SET OPERSTRING */
284 static void
285 quote_operstring(struct Client *source_p, const char *arg)
287 if(EmptyString(arg))
289 sendto_one(source_p, ":%s NOTICE %s :OPERSTRING is currently '%s'",
290 me.name, source_p->name, GlobalSetOptions.operstring);
292 else
294 strlcpy(GlobalSetOptions.operstring, arg,
295 sizeof(GlobalSetOptions.operstring));
297 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
298 "%s has changed OPERSTRING to '%s'",
299 get_oper_name(source_p), arg);
303 /* SET ADMINSTRING */
304 static void
305 quote_adminstring(struct Client *source_p, const char *arg)
307 if(EmptyString(arg))
309 sendto_one(source_p, ":%s NOTICE %s :ADMINSTRING is currently '%s'",
310 me.name, source_p->name, GlobalSetOptions.adminstring);
312 else
314 strlcpy(GlobalSetOptions.adminstring, arg,
315 sizeof(GlobalSetOptions.adminstring));
317 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
318 "%s has changed ADMINSTRING to '%s'",
319 get_oper_name(source_p), arg);
323 /* SET SPAMNUM */
324 static void
325 quote_spamnum(struct Client *source_p, int newval)
327 if(newval > 0)
329 if(newval == 0)
331 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
332 "%s has disabled ANTI_SPAMBOT", source_p->name);
333 GlobalSetOptions.spam_num = newval;
334 return;
336 if(newval < MIN_SPAM_NUM)
338 GlobalSetOptions.spam_num = MIN_SPAM_NUM;
340 else /* if (newval < MIN_SPAM_NUM) */
342 GlobalSetOptions.spam_num = newval;
344 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s has changed SPAMNUM to %i",
345 source_p->name, GlobalSetOptions.spam_num);
347 else
349 sendto_one(source_p, ":%s NOTICE %s :SPAMNUM is currently %i",
350 me.name, source_p->name, GlobalSetOptions.spam_num);
354 /* SET SPAMTIME */
355 static void
356 quote_spamtime(struct Client *source_p, int newval)
358 if(newval > 0)
360 if(newval < MIN_SPAM_TIME)
362 GlobalSetOptions.spam_time = MIN_SPAM_TIME;
364 else /* if (newval < MIN_SPAM_TIME) */
366 GlobalSetOptions.spam_time = newval;
368 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s has changed SPAMTIME to %i",
369 source_p->name, GlobalSetOptions.spam_time);
371 else
373 sendto_one(source_p, ":%s NOTICE %s :SPAMTIME is currently %i",
374 me.name, source_p->name, GlobalSetOptions.spam_time);
378 /* this table is what splitmode may be set to */
379 static const char *splitmode_values[] = {
380 "OFF",
381 "ON",
382 "AUTO",
383 NULL
386 /* this table is what splitmode may be */
387 static const char *splitmode_status[] = {
388 "OFF",
389 "AUTO (OFF)",
390 "ON",
391 "AUTO (ON)",
392 NULL
395 /* SET SPLITMODE */
396 static void
397 quote_splitmode(struct Client *source_p, char *charval)
399 if(charval)
401 int newval;
403 for (newval = 0; splitmode_values[newval]; newval++)
405 if(!irccmp(splitmode_values[newval], charval))
406 break;
409 /* OFF */
410 if(newval == 0)
412 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
413 "%s is disabling splitmode", get_oper_name(source_p));
415 splitmode = 0;
416 splitchecking = 0;
418 eventDelete(check_splitmode, NULL);
420 /* ON */
421 else if(newval == 1)
423 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
424 "%s is enabling and activating splitmode",
425 get_oper_name(source_p));
427 splitmode = 1;
428 splitchecking = 0;
430 /* we might be deactivating an automatic splitmode, so pull the event */
431 eventDelete(check_splitmode, NULL);
433 /* AUTO */
434 else if(newval == 2)
436 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
437 "%s is enabling automatic splitmode",
438 get_oper_name(source_p));
440 splitchecking = 1;
441 check_splitmode(NULL);
444 else
445 /* if we add splitchecking to splitmode*2 we get a unique table to
446 * pull values back out of, splitmode can be four states - but you can
447 * only set to three, which means we cant use the same table --fl_
449 sendto_one(source_p, ":%s NOTICE %s :SPLITMODE is currently %s",
450 me.name, source_p->name,
451 splitmode_status[(splitchecking + (splitmode * 2))]);
454 /* SET SPLITNUM */
455 static void
456 quote_splitnum(struct Client *source_p, int newval)
458 if(newval >= 0)
460 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
461 "%s has changed SPLITNUM to %i", source_p->name, newval);
462 split_servers = newval;
464 if(splitchecking)
465 check_splitmode(NULL);
467 else
468 sendto_one(source_p, ":%s NOTICE %s :SPLITNUM is currently %i",
469 me.name, source_p->name, split_servers);
472 /* SET SPLITUSERS */
473 static void
474 quote_splitusers(struct Client *source_p, int newval)
476 if(newval >= 0)
478 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
479 "%s has changed SPLITUSERS to %i", source_p->name, newval);
480 split_users = newval;
482 if(splitchecking)
483 check_splitmode(NULL);
485 else
486 sendto_one(source_p, ":%s NOTICE %s :SPLITUSERS is currently %i",
487 me.name, source_p->name, split_users);
491 * mo_set - SET command handler
492 * set options while running
494 static int
495 mo_set(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
497 int newval;
498 int i, n;
499 const char *arg = NULL;
500 const char *intarg = NULL;
502 if(!IsOperAdmin(source_p))
504 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "admin");
505 return 0;
508 if(parc > 1)
511 * Go through all the commands in set_cmd_table, until one is
512 * matched. I realize strcmp() is more intensive than a numeric
513 * lookup, but at least it's better than a big-ass switch/case
514 * statement.
516 for (i = 0; set_cmd_table[i].handler; i++)
518 if(!irccmp(set_cmd_table[i].name, parv[1]))
521 * Command found; now execute the code
523 n = 2;
525 if(set_cmd_table[i].wants_char)
527 arg = parv[n++];
530 if(set_cmd_table[i].wants_int)
532 intarg = parv[n++];
535 if((n - 1) > parc)
537 sendto_one(source_p,
538 ":%s NOTICE %s :SET %s expects (\"%s%s\") args",
539 me.name, source_p->name,
540 set_cmd_table[i].name,
541 (set_cmd_table[i].
542 wants_char ? "string, " : ""),
543 (set_cmd_table[i].
544 wants_char ? "int" : ""));
545 return 0;
548 if(parc <= 2)
550 arg = NULL;
551 intarg = NULL;
554 if(set_cmd_table[i].wants_int && (parc > 2))
556 if(intarg)
558 if(!irccmp(intarg, "yes") || !irccmp(intarg, "on"))
559 newval = 1;
560 else if(!irccmp(intarg, "no")
561 || !irccmp(intarg, "off"))
562 newval = 0;
563 else
564 newval = atoi(intarg);
566 else
568 newval = -1;
571 if(newval < 0)
573 sendto_one(source_p,
574 ":%s NOTICE %s :Value less than 0 illegal for %s",
575 me.name, source_p->name,
576 set_cmd_table[i].name);
578 return 0;
581 else
582 newval = -1;
584 if(set_cmd_table[i].wants_char)
586 if(set_cmd_table[i].wants_int)
587 set_cmd_table[i].handler(source_p, arg, newval);
588 else
589 set_cmd_table[i].handler(source_p, arg);
590 return 0;
592 else
594 if(set_cmd_table[i].wants_int)
595 set_cmd_table[i].handler(source_p, newval);
596 else
597 /* Just in case someone actually wants a
598 * set function that takes no args.. *shrug* */
599 set_cmd_table[i].handler(source_p);
600 return 0;
606 * Code here will be executed when a /QUOTE SET command is not
607 * found within set_cmd_table.
609 sendto_one(source_p, ":%s NOTICE %s :Variable not found.", me.name, parv[0]);
610 return 0;
613 list_quote_commands(source_p);
615 return 0;