summaryrefslogtreecommitdiff
path: root/modules/m_set.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/m_set.c')
-rw-r--r--modules/m_set.c616
1 files changed, 616 insertions, 0 deletions
diff --git a/modules/m_set.c b/modules/m_set.c
new file mode 100644
index 0000000..f17b4a6
--- /dev/null
+++ b/modules/m_set.c
@@ -0,0 +1,616 @@
+/*
+ * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
+ * m_set.c: Sets a server parameter.
+ *
+ * Copyright (C) 2002 by the past and present ircd coders, and others.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * $Id$
+ */
+
+/* rewritten by jdc */
+
+#include "stdinc.h"
+#include "client.h"
+#include "event.h"
+#include "irc_string.h"
+#include "ircd.h"
+#include "numeric.h"
+#include "fdlist.h"
+#include "s_bsd.h"
+#include "s_serv.h"
+#include "send.h"
+#include "channel.h"
+#include "conf.h"
+#include "parse.h"
+#include "modules.h"
+#include "s_user.h"
+#include "s_misc.h"
+
+
+/* Structure used for the SET table itself */
+struct SetStruct
+{
+ const char *name;
+ void (*handler)();
+ const int wants_char; /* 1 if it expects (char *, [int]) */
+ const int wants_int; /* 1 if it expects ([char *], int) */
+ /* eg: 0, 1 == only an int arg
+ * eg: 1, 1 == char and int args */
+};
+
+static void quote_autoconn(struct Client *, const char *, int);
+static void quote_autoconnall(struct Client *, int);
+static void quote_floodcount(struct Client *, int);
+static void quote_identtimeout(struct Client *, int);
+static void quote_max(struct Client *, int);
+static void quote_msglocale(struct Client *, char *);
+static void quote_spamnum(struct Client *, int);
+static void quote_spamtime(struct Client *, int);
+static void quote_splitmode(struct Client *, char *);
+static void quote_splitnum(struct Client *, int);
+static void quote_splitusers(struct Client *, int);
+static void list_quote_commands(struct Client *);
+static void quote_jfloodtime(struct Client *, int);
+static void quote_jfloodcount(struct Client *, int);
+
+/*
+ * If this ever needs to be expanded to more than one arg of each
+ * type, want_char/want_int could be the count of the arguments,
+ * instead of just a boolean flag...
+ *
+ * -davidt
+ */
+
+static const struct SetStruct set_cmd_table[] =
+{
+ /* name function string arg int arg */
+ /* -------------------------------------------------------- */
+ { "AUTOCONN", quote_autoconn, 1, 1 },
+ { "AUTOCONNALL", quote_autoconnall, 0, 1 },
+ { "FLOODCOUNT", quote_floodcount, 0, 1 },
+ { "IDENTTIMEOUT", quote_identtimeout, 0, 1 },
+ { "MAX", quote_max, 0, 1 },
+ { "MSGLOCALE", quote_msglocale, 1, 0 },
+ { "SPAMNUM", quote_spamnum, 0, 1 },
+ { "SPAMTIME", quote_spamtime, 0, 1 },
+ { "SPLITMODE", quote_splitmode, 1, 0 },
+ { "SPLITNUM", quote_splitnum, 0, 1 },
+ { "SPLITUSERS", quote_splitusers, 0, 1 },
+ { "JFLOODTIME", quote_jfloodtime, 0, 1 },
+ { "JFLOODCOUNT", quote_jfloodcount, 0, 1 },
+ /* -------------------------------------------------------- */
+ { NULL, NULL, 0, 0 }
+};
+
+/*
+ * list_quote_commands() sends the client all the available commands.
+ * Four to a line for now.
+ */
+static void
+list_quote_commands(struct Client *source_p)
+{
+ int j = 0;
+ const struct SetStruct *tab = set_cmd_table;
+ const char *names[4] = { "", "", "", "" };
+
+ sendto_one(source_p, ":%s NOTICE %s :Available QUOTE SET commands:",
+ me.name, source_p->name);
+
+ for (; tab->handler; ++tab)
+ {
+ names[j++] = tab->name;
+
+ if (j > 3)
+ {
+ sendto_one(source_p, ":%s NOTICE %s :%s %s %s %s",
+ me.name, source_p->name,
+ names[0], names[1],
+ names[2], names[3]);
+ j = 0;
+ names[0] = names[1] = names[2] = names[3] = "";
+ }
+
+ }
+
+ if (j)
+ sendto_one(source_p, ":%s NOTICE %s :%s %s %s %s",
+ me.name, source_p->name,
+ names[0], names[1],
+ names[2], names[3]);
+}
+
+/* SET AUTOCONN */
+static void
+quote_autoconn(struct Client *source_p, const char *arg, int newval)
+{
+ struct AccessItem *aconf;
+
+ if (arg != NULL)
+ {
+ struct ConfItem *conf = find_exact_name_conf(SERVER_TYPE, NULL, arg, NULL, NULL);
+
+ if (conf != NULL)
+ {
+ aconf = map_to_conf(conf);
+ if (newval)
+ SetConfAllowAutoConn(aconf);
+ else
+ ClearConfAllowAutoConn(aconf);
+
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s has changed AUTOCONN for %s to %i",
+ get_oper_name(source_p), arg, newval);
+ sendto_one(source_p,
+ ":%s NOTICE %s :AUTOCONN for %s is now set to %i",
+ me.name, source_p->name, arg, newval);
+ }
+ else
+ {
+ sendto_one(source_p, ":%s NOTICE %s :Can't find %s",
+ me.name, source_p->name, arg);
+ }
+ }
+ else
+ {
+ sendto_one(source_p, ":%s NOTICE %s :Please specify a server name!",
+ me.name, source_p->name);
+ }
+}
+
+/* SET AUTOCONNALL */
+static void
+quote_autoconnall(struct Client *source_p, int newval)
+{
+ if (newval >= 0)
+ {
+ sendto_realops_flags(UMODE_ALL, L_ALL, "%s has changed AUTOCONNALL to %i",
+ get_oper_name(source_p), newval);
+
+ GlobalSetOptions.autoconn = newval;
+ }
+ else
+ sendto_one(source_p, ":%s NOTICE %s :AUTOCONNALL is currently %i",
+ me.name, source_p->name, GlobalSetOptions.autoconn);
+}
+
+/* SET FLOODCOUNT */
+static void
+quote_floodcount(struct Client *source_p, int newval)
+{
+ if (newval >= 0)
+ {
+ GlobalSetOptions.floodcount = newval;
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s has changed FLOODCOUNT to %i",
+ get_oper_name(source_p), GlobalSetOptions.floodcount);
+ }
+ else
+ sendto_one(source_p, ":%s NOTICE %s :FLOODCOUNT is currently %i",
+ me.name, source_p->name, GlobalSetOptions.floodcount);
+}
+
+/* SET IDENTTIMEOUT */
+static void
+quote_identtimeout(struct Client *source_p, int newval)
+{
+ if (!HasUMode(source_p, UMODE_ADMIN))
+ {
+ sendto_one(source_p, form_str(ERR_NOPRIVS),
+ me.name, source_p->name, "set");
+ return;
+ }
+
+ if (newval > 0)
+ {
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s has changed IDENTTIMEOUT to %d",
+ get_oper_name(source_p), newval);
+ GlobalSetOptions.ident_timeout = newval;
+ }
+ else
+ sendto_one(source_p, ":%s NOTICE %s :IDENTTIMEOUT is currently %d",
+ me.name, source_p->name, GlobalSetOptions.ident_timeout);
+}
+
+/* SET MAX */
+static void
+quote_max(struct Client *source_p, int newval)
+{
+ if (newval > 0)
+ {
+ recalc_fdlimit(NULL);
+
+ if (newval > MAXCLIENTS_MAX)
+ {
+ sendto_one(source_p,
+ ":%s NOTICE %s :You cannot set MAXCLIENTS to > %d, restoring to %d",
+ me.name, source_p->name, MAXCLIENTS_MAX, ServerInfo.max_clients);
+ return;
+ }
+
+ if (newval < MAXCLIENTS_MIN)
+ {
+ sendto_one(source_p,
+ ":%s NOTICE %s :You cannot set MAXCLIENTS to < %d, restoring to %d",
+ me.name, source_p->name, MAXCLIENTS_MIN, ServerInfo.max_clients);
+ return;
+ }
+
+ ServerInfo.max_clients = newval;
+
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s set new MAXCLIENTS to %d (%d current)",
+ get_oper_name(source_p), ServerInfo.max_clients, Count.local);
+ }
+ else
+ sendto_one(source_p, ":%s NOTICE %s :Current MAXCLIENTS = %d (%d)",
+ me.name, source_p->name, ServerInfo.max_clients, Count.local);
+}
+
+/* SET MSGLOCALE */
+static void
+quote_msglocale(struct Client *source_p, char *locale)
+{
+ if (locale != NULL)
+ {
+ set_locale(locale);
+ rebuild_isupport_message_line();
+ sendto_one(source_p, ":%s NOTICE %s :Set MSGLOCALE to '%s'",
+ me.name, source_p->name, get_locale());
+ }
+ else
+ sendto_one(source_p, ":%s NOTICE %s :MSGLOCALE is currently '%s'",
+ me.name, source_p->name, get_locale());
+}
+
+/* SET SPAMNUM */
+static void
+quote_spamnum(struct Client *source_p, int newval)
+{
+ if (newval >= 0)
+ {
+ if (newval == 0)
+ {
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s has disabled ANTI_SPAMBOT", source_p->name);
+ GlobalSetOptions.spam_num = newval;
+ return;
+ }
+
+ GlobalSetOptions.spam_num = IRCD_MAX(newval, MIN_SPAM_NUM);
+ sendto_realops_flags(UMODE_ALL, L_ALL, "%s has changed SPAMNUM to %i",
+ get_oper_name(source_p), GlobalSetOptions.spam_num);
+ }
+ else
+ sendto_one(source_p, ":%s NOTICE %s :SPAMNUM is currently %i",
+ me.name, source_p->name, GlobalSetOptions.spam_num);
+}
+
+/* SET SPAMTIME */
+static void
+quote_spamtime(struct Client *source_p, int newval)
+{
+ if (newval > 0)
+ {
+ GlobalSetOptions.spam_time = IRCD_MAX(newval, MIN_SPAM_TIME);
+ sendto_realops_flags(UMODE_ALL, L_ALL, "%s has changed SPAMTIME to %i",
+ get_oper_name(source_p), GlobalSetOptions.spam_time);
+ }
+ else
+ sendto_one(source_p, ":%s NOTICE %s :SPAMTIME is currently %i",
+ me.name, source_p->name, GlobalSetOptions.spam_time);
+}
+
+/* this table is what splitmode may be set to */
+static const char *splitmode_values[] =
+{
+ "OFF",
+ "ON",
+ "AUTO",
+ NULL
+};
+
+/* this table is what splitmode may be */
+static const char *splitmode_status[] =
+{
+ "OFF",
+ "AUTO (OFF)",
+ "ON",
+ "AUTO (ON)",
+ NULL
+};
+
+/* SET SPLITMODE */
+static void
+quote_splitmode(struct Client *source_p, char *charval)
+{
+ if (charval)
+ {
+ int newval;
+
+ for (newval = 0; splitmode_values[newval]; ++newval)
+ if (irccmp(splitmode_values[newval], charval) == 0)
+ break;
+
+ /* OFF */
+ if (newval == 0)
+ {
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s is disabling splitmode",
+ get_oper_name(source_p));
+
+ splitmode = 0;
+ splitchecking = 0;
+
+ eventDelete(check_splitmode, NULL);
+ }
+ /* ON */
+ else if (newval == 1)
+ {
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s is enabling and activating splitmode",
+ get_oper_name(source_p));
+
+ splitmode = 1;
+ splitchecking = 0;
+
+ /* we might be deactivating an automatic splitmode, so pull the event */
+ eventDelete(check_splitmode, NULL);
+ }
+ /* AUTO */
+ else if (newval == 2)
+ {
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s is enabling automatic splitmode",
+ get_oper_name(source_p));
+
+ splitchecking = 1;
+ check_splitmode(NULL);
+ }
+ }
+ else
+ /* if we add splitchecking to splitmode*2 we get a unique table to
+ * pull values back out of, splitmode can be four states - but you can
+ * only set to three, which means we cant use the same table --fl_
+ */
+ sendto_one(source_p, ":%s NOTICE %s :SPLITMODE is currently %s",
+ me.name, source_p->name,
+ splitmode_status[(splitchecking + (splitmode * 2))]);
+}
+
+/* SET SPLITNUM */
+static void
+quote_splitnum(struct Client *source_p, int newval)
+{
+ if (newval >= 0)
+ {
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s has changed SPLITNUM to %i",
+ get_oper_name(source_p), newval);
+ split_servers = newval;
+
+ if (splitchecking)
+ check_splitmode(NULL);
+ }
+ else
+ sendto_one(source_p, ":%s NOTICE %s :SPLITNUM is currently %i",
+ me.name, source_p->name, split_servers);
+}
+
+/* SET SPLITUSERS */
+static void
+quote_splitusers(struct Client *source_p, int newval)
+{
+ if (newval >= 0)
+ {
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s has changed SPLITUSERS to %i",
+ get_oper_name(source_p), newval);
+ split_users = newval;
+
+ if (splitchecking)
+ check_splitmode(NULL);
+ }
+ else
+ sendto_one(source_p, ":%s NOTICE %s :SPLITUSERS is currently %i",
+ me.name, source_p->name, split_users);
+}
+
+/* SET JFLOODTIME */
+static void
+quote_jfloodtime(struct Client *source_p, int newval)
+{
+ if (newval >= 0)
+ {
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s has changed JFLOODTIME to %i",
+ get_oper_name(source_p), newval);
+ GlobalSetOptions.joinfloodtime = newval;
+ }
+ else
+ sendto_one(source_p, ":%s NOTICE %s :JFLOODTIME is currently %i",
+ me.name, source_p->name, GlobalSetOptions.joinfloodtime);
+}
+
+/* SET JFLOODCOUNT */
+static void
+quote_jfloodcount(struct Client *source_p, int newval)
+{
+ if (newval >= 0)
+ {
+ sendto_realops_flags(UMODE_ALL, L_ALL,
+ "%s has changed JFLOODCOUNT to %i",
+ get_oper_name(source_p), newval);
+ GlobalSetOptions.joinfloodcount = newval;
+ }
+ else
+ sendto_one(source_p, ":%s NOTICE %s :JFLOODCOUNT is currently %i",
+ me.name, source_p->name, GlobalSetOptions.joinfloodcount);
+}
+
+/*
+ * mo_set - SET command handler
+ * set options while running
+ */
+static void
+mo_set(struct Client *client_p, struct Client *source_p,
+ int parc, char *parv[])
+{
+ int n;
+ int newval;
+ const char *arg = NULL;
+ const char *intarg = NULL;
+ const struct SetStruct *tab = set_cmd_table;
+
+ if (!HasOFlag(source_p, OPER_FLAG_SET))
+ {
+ sendto_one(source_p, form_str(ERR_NOPRIVS),
+ me.name, source_p->name, "set");
+ return;
+ }
+
+ if (parc > 1)
+ {
+ /*
+ * Go through all the commands in set_cmd_table, until one is
+ * matched.
+ */
+ for (; tab->handler; ++tab)
+ {
+ if (!irccmp(tab->name, parv[1]))
+ {
+ /*
+ * Command found; now execute the code
+ */
+ n = 2;
+
+ if (tab->wants_char)
+ arg = parv[n++];
+
+ if (tab->wants_int)
+ intarg = parv[n++];
+
+ if ((n - 1) > parc)
+ {
+ if (parc > 2)
+ sendto_one(source_p,
+ ":%s NOTICE %s :SET %s expects (\"%s%s\") args",
+ me.name, source_p->name, tab->name,
+ (tab->wants_char ? "string, " : ""),
+ (tab->wants_char ? "int" : ""));
+ }
+
+ if (parc <= 2)
+ {
+ arg = NULL;
+ intarg = NULL;
+ }
+
+ if (!strcmp(tab->name, "AUTOCONN") && (parc < 4))
+ {
+ sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
+ me.name, source_p->name, "SET");
+ return;
+ }
+
+ if (tab->wants_int && (parc > 2))
+ {
+ if (intarg)
+ {
+ if (irccmp(intarg, "yes") == 0 || irccmp(intarg, "on") == 0)
+ newval = 1;
+ else if (irccmp(intarg, "no") == 0|| irccmp(intarg, "off") == 0)
+ newval = 0;
+ else
+ newval = atoi(intarg);
+ }
+ else
+ newval = -1;
+
+ if (newval < 0)
+ {
+ sendto_one(source_p,
+ ":%s NOTICE %s :Value less than 0 illegal for %s",
+ me.name, source_p->name,
+ tab->name);
+
+ return;
+ }
+ }
+ else
+ newval = -1;
+
+ if (tab->wants_char)
+ {
+ if (tab->wants_int)
+ tab->handler(source_p, arg, newval);
+ else
+ tab->handler(source_p, arg);
+ return;
+ }
+ else
+ {
+ if (tab->wants_int)
+ tab->handler(source_p, newval);
+ else
+ /* Just in case someone actually wants a
+ * set function that takes no args.. *shrug* */
+ tab->handler(source_p);
+ return;
+ }
+ }
+ }
+
+ /*
+ * Code here will be executed when a /QUOTE SET command is not
+ * found within set_cmd_table.
+ */
+ sendto_one(source_p, ":%s NOTICE %s :Variable not found.",
+ me.name, source_p->name);
+ return;
+ }
+
+ list_quote_commands(source_p);
+}
+
+static struct Message set_msgtab = {
+ "SET", 0, 0, 0, MAXPARA, MFLG_SLOW, 0,
+ {m_unregistered, m_not_oper, rfc1459_command_send_error, m_ignore, mo_set, m_ignore}
+};
+
+static void
+module_init(void)
+{
+ mod_add_cmd(&set_msgtab);
+}
+
+static void
+module_exit(void)
+{
+ mod_del_cmd(&set_msgtab);
+}
+
+struct module module_entry = {
+ .node = { NULL, NULL, NULL },
+ .name = NULL,
+ .version = "$Revision$",
+ .handle = NULL,
+ .modinit = module_init,
+ .modexit = module_exit,
+ .flags = 0
+};