]> jfr.im git - solanum.git/blame - modules/m_set.c
s_user: clean up return types and can YES/NO.
[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"
34#include "common.h"
35#include "channel.h"
36#include "s_conf.h"
37#include "s_newconf.h"
38#include "msg.h"
39#include "parse.h"
40#include "modules.h"
41
428ca87b 42static int mo_set(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
3abc337f 43static const char set_desc[] = "Provides the SET command to change server parameters";
212380e3
AC
44
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);
212380e3
AC
58 int wants_char; /* 1 if it expects (char *, [int]) */
59 int wants_int; /* 1 if it expects ([char *], int) */
60
61 /* eg: 0, 1 == only an int arg
62 * eg: 1, 1 == char and int args */
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[] = {
91 /* name function string arg int arg */
92 /* -------------------------------------------------------- */
93 {"ADMINSTRING", quote_adminstring, 1, 0 },
94 {"AUTOCONN", quote_autoconn, 1, 1 },
95 {"AUTOCONNALL", quote_autoconnall, 0, 1 },
96 {"FLOODCOUNT", quote_floodcount, 0, 1 },
97 {"IDENTTIMEOUT", quote_identtimeout, 0, 1 },
212380e3
AC
98 {"MAX", quote_max, 0, 1 },
99 {"MAXCLIENTS", quote_max, 0, 1 },
100 {"OPERSTRING", quote_operstring, 1, 0 },
101 {"SPAMNUM", quote_spamnum, 0, 1 },
102 {"SPAMTIME", quote_spamtime, 0, 1 },
103 {"SPLITMODE", quote_splitmode, 1, 0 },
104 {"SPLITNUM", quote_splitnum, 0, 1 },
105 {"SPLITUSERS", quote_splitusers, 0, 1 },
106 /* -------------------------------------------------------- */
21dc257c 107 {(char *) 0, (void (*)(struct Client *, const char *, int)) 0, 0, 0}
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 {
157 sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has changed AUTOCONNALL to %i",
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;
177 sendto_realops_snomask(SNO_GENERAL, L_ALL,
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 {
201 sendto_realops_snomask(SNO_GENERAL, L_ALL,
202 "%s has changed IDENTTIMEOUT to %d",
203 get_oper_name(source_p), newval);
204 GlobalSetOptions.ident_timeout = newval;
205 }
206 else
5366977b
AC
207 sendto_one_notice(source_p, ":IDENTTIMEOUT is currently %d",
208 GlobalSetOptions.ident_timeout);
212380e3
AC
209}
210
212380e3
AC
211/* SET MAX */
212static void
21dc257c 213quote_max(struct Client *source_p, const char *arg, int newval)
212380e3
AC
214{
215 if(newval > 0)
216 {
8bd5767b
JT
217 if(newval > maxconnections - MAX_BUFFER)
218 {
219 sendto_one_notice(source_p,
220 ":You cannot set MAXCLIENTS to > %d",
221 maxconnections - MAX_BUFFER);
222 return;
6c70c576
JT
223 }
224
212380e3
AC
225 if(newval < 32)
226 {
101db4c4
VY
227 sendto_one_notice(source_p, ":You cannot set MAXCLIENTS to < 32 (%d:%d)",
228 GlobalSetOptions.maxclients, rb_getmaxconnect());
212380e3
AC
229 return;
230 }
231
232 GlobalSetOptions.maxclients = newval;
233
234 sendto_realops_snomask(SNO_GENERAL, L_ALL,
235 "%s!%s@%s set new MAXCLIENTS to %d (%lu current)",
236 source_p->name, source_p->username, source_p->host,
55abcbb2 237 GlobalSetOptions.maxclients,
5b96d9a6 238 rb_dlink_list_length(&lclient_list));
212380e3
AC
239
240 return;
241 }
242 else
243 {
5366977b 244 sendto_one_notice(source_p, ":Current Maxclients = %d (%lu)",
5b96d9a6 245 GlobalSetOptions.maxclients, rb_dlink_list_length(&lclient_list));
212380e3
AC
246 }
247}
248
249/* SET OPERSTRING */
250static void
21dc257c 251quote_operstring(struct Client *source_p, const char *arg, int newval)
212380e3
AC
252{
253 if(EmptyString(arg))
254 {
5366977b 255 sendto_one_notice(source_p, ":OPERSTRING is currently '%s'", GlobalSetOptions.operstring);
212380e3
AC
256 }
257 else
258 {
f427c8b0 259 rb_strlcpy(GlobalSetOptions.operstring, arg,
212380e3 260 sizeof(GlobalSetOptions.operstring));
55abcbb2 261
212380e3
AC
262 sendto_realops_snomask(SNO_GENERAL, L_ALL,
263 "%s has changed OPERSTRING to '%s'",
264 get_oper_name(source_p), arg);
265 }
266}
267
268/* SET ADMINSTRING */
269static void
21dc257c 270quote_adminstring(struct Client *source_p, const char *arg, int newval)
212380e3
AC
271{
272 if(EmptyString(arg))
273 {
5366977b 274 sendto_one_notice(source_p, ":ADMINSTRING is currently '%s'", GlobalSetOptions.adminstring);
212380e3
AC
275 }
276 else
277 {
f427c8b0 278 rb_strlcpy(GlobalSetOptions.adminstring, arg,
212380e3 279 sizeof(GlobalSetOptions.adminstring));
55abcbb2 280
212380e3
AC
281 sendto_realops_snomask(SNO_GENERAL, L_ALL,
282 "%s has changed ADMINSTRING to '%s'",
283 get_oper_name(source_p), arg);
284 }
285}
286
287/* SET SPAMNUM */
288static void
21dc257c 289quote_spamnum(struct Client *source_p, const char *arg, int newval)
212380e3
AC
290{
291 if(newval > 0)
292 {
293 if(newval == 0)
294 {
295 sendto_realops_snomask(SNO_GENERAL, L_ALL,
296 "%s has disabled ANTI_SPAMBOT", source_p->name);
297 GlobalSetOptions.spam_num = newval;
298 return;
299 }
300 if(newval < MIN_SPAM_NUM)
301 {
302 GlobalSetOptions.spam_num = MIN_SPAM_NUM;
303 }
304 else /* if (newval < MIN_SPAM_NUM) */
305 {
306 GlobalSetOptions.spam_num = newval;
307 }
308 sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has changed SPAMNUM to %i",
309 source_p->name, GlobalSetOptions.spam_num);
310 }
311 else
312 {
5366977b 313 sendto_one_notice(source_p, ":SPAMNUM is currently %i", GlobalSetOptions.spam_num);
212380e3
AC
314 }
315}
316
317/* SET SPAMTIME */
318static void
21dc257c 319quote_spamtime(struct Client *source_p, const char *arg, int newval)
212380e3
AC
320{
321 if(newval > 0)
322 {
323 if(newval < MIN_SPAM_TIME)
324 {
325 GlobalSetOptions.spam_time = MIN_SPAM_TIME;
326 }
327 else /* if (newval < MIN_SPAM_TIME) */
328 {
329 GlobalSetOptions.spam_time = newval;
330 }
331 sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has changed SPAMTIME to %i",
332 source_p->name, GlobalSetOptions.spam_time);
333 }
334 else
335 {
5366977b 336 sendto_one_notice(source_p, ":SPAMTIME is currently %i", GlobalSetOptions.spam_time);
212380e3
AC
337 }
338}
339
340/* this table is what splitmode may be set to */
341static const char *splitmode_values[] = {
342 "OFF",
343 "ON",
344 "AUTO",
345 NULL
346};
347
348/* this table is what splitmode may be */
349static const char *splitmode_status[] = {
350 "OFF",
351 "AUTO (OFF)",
352 "ON",
353 "AUTO (ON)",
354 NULL
355};
356
357/* SET SPLITMODE */
358static void
21dc257c 359quote_splitmode(struct Client *source_p, const char *charval, int intval)
212380e3
AC
360{
361 if(charval)
362 {
363 int newval;
364
365 for (newval = 0; splitmode_values[newval]; newval++)
366 {
367 if(!irccmp(splitmode_values[newval], charval))
368 break;
369 }
370
371 /* OFF */
372 if(newval == 0)
373 {
374 sendto_realops_snomask(SNO_GENERAL, L_ALL,
375 "%s is disabling splitmode", get_oper_name(source_p));
376
377 splitmode = 0;
378 splitchecking = 0;
379
fa832850 380 rb_event_delete(check_splitmode_ev);
6a309903 381 check_splitmode_ev = NULL;
212380e3
AC
382 }
383 /* ON */
384 else if(newval == 1)
385 {
386 sendto_realops_snomask(SNO_GENERAL, L_ALL,
387 "%s is enabling and activating splitmode",
388 get_oper_name(source_p));
389
390 splitmode = 1;
391 splitchecking = 0;
392
393 /* we might be deactivating an automatic splitmode, so pull the event */
fa832850 394 rb_event_delete(check_splitmode_ev);
6a309903 395 check_splitmode_ev = NULL;
212380e3
AC
396 }
397 /* AUTO */
398 else if(newval == 2)
399 {
400 sendto_realops_snomask(SNO_GENERAL, L_ALL,
401 "%s is enabling automatic splitmode",
402 get_oper_name(source_p));
403
404 splitchecking = 1;
405 check_splitmode(NULL);
406 }
407 }
408 else
55abcbb2 409 /* if we add splitchecking to splitmode*2 we get a unique table to
212380e3
AC
410 * pull values back out of, splitmode can be four states - but you can
411 * only set to three, which means we cant use the same table --fl_
412 */
5366977b 413 sendto_one_notice(source_p, ":SPLITMODE is currently %s",
212380e3
AC
414 splitmode_status[(splitchecking + (splitmode * 2))]);
415}
416
417/* SET SPLITNUM */
418static void
21dc257c 419quote_splitnum(struct Client *source_p, const char *arg, int newval)
212380e3
AC
420{
421 if(newval >= 0)
422 {
423 sendto_realops_snomask(SNO_GENERAL, L_ALL,
424 "%s has changed SPLITNUM to %i", source_p->name, newval);
425 split_servers = newval;
426
427 if(splitchecking)
428 check_splitmode(NULL);
429 }
430 else
5366977b 431 sendto_one_notice(source_p, ":SPLITNUM is currently %i", split_servers);
212380e3
AC
432}
433
434/* SET SPLITUSERS */
435static void
21dc257c 436quote_splitusers(struct Client *source_p, const char *arg, int newval)
212380e3
AC
437{
438 if(newval >= 0)
439 {
440 sendto_realops_snomask(SNO_GENERAL, L_ALL,
441 "%s has changed SPLITUSERS to %i", source_p->name, newval);
442 split_users = newval;
443
444 if(splitchecking)
445 check_splitmode(NULL);
446 }
447 else
5366977b 448 sendto_one_notice(source_p, ":SPLITUSERS is currently %i", split_users);
212380e3
AC
449}
450
451/*
452 * mo_set - SET command handler
453 * set options while running
454 */
455static int
428ca87b 456mo_set(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3
AC
457{
458 int newval;
459 int i, n;
460 const char *arg = NULL;
461 const char *intarg = NULL;
462
463 if(parc > 1)
464 {
465 /*
466 * Go through all the commands in set_cmd_table, until one is
467 * matched. I realize strcmp() is more intensive than a numeric
468 * lookup, but at least it's better than a big-ass switch/case
469 * statement.
470 */
471 for (i = 0; set_cmd_table[i].handler; i++)
472 {
473 if(!irccmp(set_cmd_table[i].name, parv[1]))
474 {
475 /*
476 * Command found; now execute the code
477 */
478 n = 2;
479
480 if(set_cmd_table[i].wants_char)
481 {
482 arg = parv[n++];
483 }
484
485 if(set_cmd_table[i].wants_int)
486 {
487 intarg = parv[n++];
488 }
489
490 if((n - 1) > parc)
491 {
5366977b
AC
492 sendto_one_notice(source_p,
493 ":SET %s expects (\"%s%s\") args",
212380e3
AC
494 set_cmd_table[i].name,
495 (set_cmd_table[i].
496 wants_char ? "string, " : ""),
497 (set_cmd_table[i].
498 wants_char ? "int" : ""));
499 return 0;
500 }
501
502 if(parc <= 2)
503 {
504 arg = NULL;
505 intarg = NULL;
506 }
507
508 if(set_cmd_table[i].wants_int && (parc > 2))
509 {
510 if(intarg)
511 {
512 if(!irccmp(intarg, "yes") || !irccmp(intarg, "on"))
513 newval = 1;
514 else if(!irccmp(intarg, "no")
515 || !irccmp(intarg, "off"))
516 newval = 0;
517 else
518 newval = atoi(intarg);
519 }
520 else
521 {
522 newval = -1;
523 }
524
525 if(newval < 0)
526 {
5366977b
AC
527 sendto_one_notice(source_p,
528 ":Value less than 0 illegal for %s",
212380e3
AC
529 set_cmd_table[i].name);
530
531 return 0;
532 }
533 }
534 else
535 newval = -1;
536
21dc257c
JT
537 set_cmd_table[i].handler(source_p, arg, newval);
538 return 0;
212380e3
AC
539 }
540 }
541
542 /*
543 * Code here will be executed when a /QUOTE SET command is not
544 * found within set_cmd_table.
545 */
5366977b 546 sendto_one_notice(source_p, ":Variable not found.");
212380e3
AC
547 return 0;
548 }
549
550 list_quote_commands(source_p);
551
552 return 0;
553}