solanum/modules/m_set.c
Elizabeth Myers 3c7d6fcce7 Message handlers should return void.
Also fix up some return values and stuff to use bool (or void if
nothing). I just did it whilst I was here.

According to jilles, the return value used to signify whether or not the
client had exited. This was error-prone and was fixed a long, long time
ago, but the return value was left int for historical reasons.

Since the return type is not used (and has no clear use case anyway),
it's safe to just get rid of it.
2016-03-09 01:37:03 -06:00

553 lines
14 KiB
C

/*
* ircd-ratbox: A slightly useful ircd.
* m_set.c: Sets a server parameter.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
*
* 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
*/
/* rewritten by jdc */
#include "stdinc.h"
#include "client.h"
#include "match.h"
#include "ircd.h"
#include "numeric.h"
#include "s_serv.h"
#include "send.h"
#include "common.h"
#include "channel.h"
#include "s_conf.h"
#include "s_newconf.h"
#include "msg.h"
#include "parse.h"
#include "modules.h"
static const char set_desc[] = "Provides the SET command to change server parameters";
static void mo_set(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
struct Message set_msgtab = {
"SET", 0, 0, 0, 0,
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_set, 0}}
};
mapi_clist_av1 set_clist[] = { &set_msgtab, NULL };
DECLARE_MODULE_AV2(set, NULL, NULL, set_clist, NULL, NULL, NULL, NULL, set_desc);
/* Structure used for the SET table itself */
struct SetStruct
{
const char *name;
void (*handler)(struct Client *source_p, const char *chararg, int intarg);
int wants_char; /* 1 if it expects (char *, [int]) */
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_adminstring(struct Client *, const char *, int);
static void quote_autoconn(struct Client *, const char *, int);
static void quote_autoconnall(struct Client *, const char *, int);
static void quote_floodcount(struct Client *, const char *, int);
static void quote_identtimeout(struct Client *, const char *, int);
static void quote_max(struct Client *, const char *, int);
static void quote_operstring(struct Client *, const char *, int);
static void quote_spamnum(struct Client *, const char *, int);
static void quote_spamtime(struct Client *, const char *, int);
static void quote_splitmode(struct Client *, const char *, int);
static void quote_splitnum(struct Client *, const char *, int);
static void quote_splitusers(struct Client *, const char *, int);
static void list_quote_commands(struct Client *);
/*
* 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 struct SetStruct set_cmd_table[] = {
/* name function string arg int arg */
/* -------------------------------------------------------- */
{"ADMINSTRING", quote_adminstring, 1, 0 },
{"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 },
{"MAXCLIENTS", quote_max, 0, 1 },
{"OPERSTRING", quote_operstring, 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 },
/* -------------------------------------------------------- */
{(char *) 0, (void (*)(struct Client *, const char *, int)) 0, 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 i;
int j = 0;
const char *names[4];
sendto_one_notice(source_p, ":Available QUOTE SET commands:");
names[0] = names[1] = names[2] = names[3] = "";
for (i = 0; set_cmd_table[i].handler; i++)
{
names[j++] = set_cmd_table[i].name;
if(j > 3)
{
sendto_one_notice(source_p, ":%s %s %s %s",
names[0], names[1], names[2], names[3]);
j = 0;
names[0] = names[1] = names[2] = names[3] = "";
}
}
if(j)
sendto_one_notice(source_p, ":%s %s %s %s",
names[0], names[1], names[2], names[3]);
}
/* SET AUTOCONN */
static void
quote_autoconn(struct Client *source_p, const char *arg, int newval)
{
set_server_conf_autoconn(source_p, arg, newval);
}
/* SET AUTOCONNALL */
static void
quote_autoconnall(struct Client *source_p, const char *arg, int newval)
{
if(newval >= 0)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has changed AUTOCONNALL to %i",
source_p->name, newval);
GlobalSetOptions.autoconn = newval;
}
else
{
sendto_one_notice(source_p, ":AUTOCONNALL is currently %i",
GlobalSetOptions.autoconn);
}
}
/* SET FLOODCOUNT */
static void
quote_floodcount(struct Client *source_p, const char *arg, int newval)
{
if(newval >= 0)
{
GlobalSetOptions.floodcount = newval;
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"%s has changed FLOODCOUNT to %i", source_p->name,
GlobalSetOptions.floodcount);
}
else
{
sendto_one_notice(source_p, ":FLOODCOUNT is currently %i",
GlobalSetOptions.floodcount);
}
}
/* SET IDENTTIMEOUT */
static void
quote_identtimeout(struct Client *source_p, const char *arg, int newval)
{
if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
me.name, source_p->name, "admin");
return;
}
if(newval > 0)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"%s has changed IDENTTIMEOUT to %d",
get_oper_name(source_p), newval);
GlobalSetOptions.ident_timeout = newval;
}
else
sendto_one_notice(source_p, ":IDENTTIMEOUT is currently %d",
GlobalSetOptions.ident_timeout);
}
/* SET MAX */
static void
quote_max(struct Client *source_p, const char *arg, int newval)
{
if(newval > 0)
{
if(newval > maxconnections - MAX_BUFFER)
{
sendto_one_notice(source_p,
":You cannot set MAXCLIENTS to > %d",
maxconnections - MAX_BUFFER);
return;
}
if(newval < 32)
{
sendto_one_notice(source_p, ":You cannot set MAXCLIENTS to < 32 (%d:%d)",
GlobalSetOptions.maxclients, rb_getmaxconnect());
return;
}
GlobalSetOptions.maxclients = newval;
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"%s!%s@%s set new MAXCLIENTS to %d (%lu current)",
source_p->name, source_p->username, source_p->host,
GlobalSetOptions.maxclients,
rb_dlink_list_length(&lclient_list));
return;
}
else
{
sendto_one_notice(source_p, ":Current Maxclients = %d (%lu)",
GlobalSetOptions.maxclients, rb_dlink_list_length(&lclient_list));
}
}
/* SET OPERSTRING */
static void
quote_operstring(struct Client *source_p, const char *arg, int newval)
{
if(EmptyString(arg))
{
sendto_one_notice(source_p, ":OPERSTRING is currently '%s'", GlobalSetOptions.operstring);
}
else
{
rb_strlcpy(GlobalSetOptions.operstring, arg,
sizeof(GlobalSetOptions.operstring));
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"%s has changed OPERSTRING to '%s'",
get_oper_name(source_p), arg);
}
}
/* SET ADMINSTRING */
static void
quote_adminstring(struct Client *source_p, const char *arg, int newval)
{
if(EmptyString(arg))
{
sendto_one_notice(source_p, ":ADMINSTRING is currently '%s'", GlobalSetOptions.adminstring);
}
else
{
rb_strlcpy(GlobalSetOptions.adminstring, arg,
sizeof(GlobalSetOptions.adminstring));
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"%s has changed ADMINSTRING to '%s'",
get_oper_name(source_p), arg);
}
}
/* SET SPAMNUM */
static void
quote_spamnum(struct Client *source_p, const char *arg, int newval)
{
if(newval > 0)
{
if(newval == 0)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"%s has disabled ANTI_SPAMBOT", source_p->name);
GlobalSetOptions.spam_num = newval;
return;
}
if(newval < MIN_SPAM_NUM)
{
GlobalSetOptions.spam_num = MIN_SPAM_NUM;
}
else /* if (newval < MIN_SPAM_NUM) */
{
GlobalSetOptions.spam_num = newval;
}
sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has changed SPAMNUM to %i",
source_p->name, GlobalSetOptions.spam_num);
}
else
{
sendto_one_notice(source_p, ":SPAMNUM is currently %i", GlobalSetOptions.spam_num);
}
}
/* SET SPAMTIME */
static void
quote_spamtime(struct Client *source_p, const char *arg, int newval)
{
if(newval > 0)
{
if(newval < MIN_SPAM_TIME)
{
GlobalSetOptions.spam_time = MIN_SPAM_TIME;
}
else /* if (newval < MIN_SPAM_TIME) */
{
GlobalSetOptions.spam_time = newval;
}
sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has changed SPAMTIME to %i",
source_p->name, GlobalSetOptions.spam_time);
}
else
{
sendto_one_notice(source_p, ":SPAMTIME is currently %i", 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, const char *charval, int intval)
{
if(charval)
{
int newval;
for (newval = 0; splitmode_values[newval]; newval++)
{
if(!irccmp(splitmode_values[newval], charval))
break;
}
/* OFF */
if(newval == 0)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"%s is disabling splitmode", get_oper_name(source_p));
splitmode = 0;
splitchecking = 0;
rb_event_delete(check_splitmode_ev);
check_splitmode_ev = NULL;
}
/* ON */
else if(newval == 1)
{
sendto_realops_snomask(SNO_GENERAL, 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 */
rb_event_delete(check_splitmode_ev);
check_splitmode_ev = NULL;
}
/* AUTO */
else if(newval == 2)
{
sendto_realops_snomask(SNO_GENERAL, 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_notice(source_p, ":SPLITMODE is currently %s",
splitmode_status[(splitchecking + (splitmode * 2))]);
}
/* SET SPLITNUM */
static void
quote_splitnum(struct Client *source_p, const char *arg, int newval)
{
if(newval >= 0)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"%s has changed SPLITNUM to %i", source_p->name, newval);
split_servers = newval;
if(splitchecking)
check_splitmode(NULL);
}
else
sendto_one_notice(source_p, ":SPLITNUM is currently %i", split_servers);
}
/* SET SPLITUSERS */
static void
quote_splitusers(struct Client *source_p, const char *arg, int newval)
{
if(newval >= 0)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"%s has changed SPLITUSERS to %i", source_p->name, newval);
split_users = newval;
if(splitchecking)
check_splitmode(NULL);
}
else
sendto_one_notice(source_p, ":SPLITUSERS is currently %i", split_users);
}
/*
* mo_set - SET command handler
* set options while running
*/
static void
mo_set(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
int newval;
int i, n;
const char *arg = NULL;
const char *intarg = NULL;
if(parc > 1)
{
/*
* Go through all the commands in set_cmd_table, until one is
* matched. I realize strcmp() is more intensive than a numeric
* lookup, but at least it's better than a big-ass switch/case
* statement.
*/
for (i = 0; set_cmd_table[i].handler; i++)
{
if(!irccmp(set_cmd_table[i].name, parv[1]))
{
/*
* Command found; now execute the code
*/
n = 2;
if(set_cmd_table[i].wants_char)
{
arg = parv[n++];
}
if(set_cmd_table[i].wants_int)
{
intarg = parv[n++];
}
if((n - 1) > parc)
{
sendto_one_notice(source_p,
":SET %s expects (\"%s%s\") args",
set_cmd_table[i].name,
(set_cmd_table[i].
wants_char ? "string, " : ""),
(set_cmd_table[i].
wants_char ? "int" : ""));
return;
}
if(parc <= 2)
{
arg = NULL;
intarg = NULL;
}
if(set_cmd_table[i].wants_int && (parc > 2))
{
if(intarg)
{
if(!irccmp(intarg, "yes") || !irccmp(intarg, "on"))
newval = 1;
else if(!irccmp(intarg, "no")
|| !irccmp(intarg, "off"))
newval = 0;
else
newval = atoi(intarg);
}
else
{
newval = -1;
}
if(newval < 0)
{
sendto_one_notice(source_p,
":Value less than 0 illegal for %s",
set_cmd_table[i].name);
return;
}
}
else
newval = -1;
set_cmd_table[i].handler(source_p, arg, newval);
return;
}
}
/*
* Code here will be executed when a /QUOTE SET command is not
* found within set_cmd_table.
*/
sendto_one_notice(source_p, ":Variable not found.");
return;
}
list_quote_commands(source_p);
}