- /* +------------------------------------+
+/* +------------------------------------+
* | Inspire Internet Relay Chat Daemon |
* +------------------------------------+
*
#include "socketengine.h"
#include "socket.h"
#include "command_parse.h"
+#include "exitcodes.h"
/* Directory Searching for Unix-Only */
#ifndef WIN32
/** Refactored by Brain, Jun 2007. Much faster with some clever O(1) array
* lookups and pointer maths.
*/
-long InspIRCd::Duration(const char* str)
+long InspIRCd::Duration(const std::string &str)
{
- char n_field[MAXBUF];
- const char* maxsize = n_field + MAXBUF;
+ unsigned char multiplier = 0;
long total = 0;
- char* field_ptr = n_field;
- *n_field = 0;
+ long times = 1;
+ long subtotal = 0;
/* Iterate each item in the string, looking for number or multiplier */
- for (const char* i = str; *i; i++)
+ for (std::string::const_reverse_iterator i = str.rbegin(); i != str.rend(); ++i)
{
/* Found a number, queue it onto the current number */
- if ((*i >= '0') && (*i <= '9') && (field_ptr < maxsize))
- *field_ptr++ = *i;
+ if ((*i >= '0') && (*i <= '9'))
+ {
+ subtotal = subtotal + ((*i - '0') * times);
+ times = times * 10;
+ }
else
{
/* Found something thats not a number, find out how much
* it multiplies the built up number by, multiply the total
* and reset the built up number.
*/
- *field_ptr = 0;
- field_ptr = n_field;
- total += atoi(n_field) * duration_multi[(const unsigned char)*i];
- *n_field = 0;
+ if (subtotal)
+ total += subtotal * duration_multi[multiplier];
+
+ /* Next subtotal please */
+ subtotal = 0;
+ multiplier = *i;
+ times = 1;
}
}
- /* Any trailing values built up are treated as raw seconds */
- if (*n_field)
+ if (multiplier)
{
- *field_ptr = 0;
- total += atoi(n_field);
+ total += subtotal * duration_multi[multiplier];
+ subtotal = 0;
}
-
- return total;
+ /* Any trailing values built up are treated as raw seconds */
+ return total + subtotal;
}
/* LoopCall is used to call a command classes handler repeatedly based on the contents of a comma seperated list.
*/
irc::commasepstream items1(parameters[splithere]);
irc::commasepstream items2(parameters[extra]);
- std::string item = "*";
+ std::string extrastuff;
+ std::string item;
unsigned int max = 0;
/* Attempt to iterate these lists and call the command objech
* which called us, for every parameter pair until there are
* no more left to parse.
*/
- while (((item = items1.GetToken()) != "") && (max++ < ServerInstance->Config->MaxTargets))
+ while (items1.GetToken(item) && (max++ < ServerInstance->Config->MaxTargets))
{
if (dupes.find(item.c_str()) == dupes.end())
{
- const char* new_parameters[127];
+ const char* new_parameters[MAXPARAMETERS];
- for (int t = 0; (t < pcnt) && (t < 127); t++)
+ for (int t = 0; (t < pcnt) && (t < MAXPARAMETERS); t++)
new_parameters[t] = parameters[t];
- std::string extrastuff = items2.GetToken();
+ if (!items2.GetToken(extrastuff))
+ extrastuff = "";
new_parameters[splithere] = item.c_str();
new_parameters[extra] = extrastuff.c_str();
/* Only one commasepstream here */
irc::commasepstream items1(parameters[splithere]);
- std::string item = "*";
+ std::string item;
unsigned int max = 0;
/* Parse the commasepstream until there are no tokens remaining.
* Each token we parse out, call the command handler that called us
* with it
*/
- while (((item = items1.GetToken()) != "") && (max++ < ServerInstance->Config->MaxTargets))
+ while (items1.GetToken(item) && (max++ < ServerInstance->Config->MaxTargets))
{
if (dupes.find(item.c_str()) == dupes.end())
{
- const char* new_parameters[127];
+ const char* new_parameters[MAXPARAMETERS];
- for (int t = 0; (t < pcnt) && (t < 127); t++)
+ for (int t = 0; (t < pcnt) && (t < MAXPARAMETERS); t++)
new_parameters[t] = parameters[t];
new_parameters[splithere] = item.c_str();
{
if ((pcnt>=n->second->min_params) && (n->second->source != "<core>"))
{
- if ((!n->second->flags_needed) || (user->modes[n->second->flags_needed-65]))
+ if ((!n->second->flags_needed) || (user->IsModeSet(n->second->flags_needed)))
{
if (n->second->flags_needed)
{
{
if (pcnt >= n->second->min_params)
{
- if ((!n->second->flags_needed) || (user->modes[n->second->flags_needed-65]))
+ if ((!n->second->flags_needed) || (user->IsModeSet(n->second->flags_needed)))
{
if (n->second->flags_needed)
{
void CommandParser::ProcessCommand(userrec *user, std::string &cmd)
{
- const char *command_p[127];
+ const char *command_p[MAXPARAMETERS];
int items = 0;
irc::tokenstream tokens(cmd);
std::string command;
if (*command.c_str() == ':')
tokens.GetToken(command);
- while (tokens.GetToken(para[items]) && (items < 127))
+ while (tokens.GetToken(para[items]) && (items < MAXPARAMETERS))
{
command_p[items] = para[items].c_str();
items++;
{
/* command is disabled! */
user->WriteServ("421 %s %s :This command has been disabled.",user->nick,command.c_str());
+ ServerInstance->SNO->WriteToSnoMask('d', "%s denied for %s (%s@%s)",
+ command.c_str(), user->nick, user->ident, user->host);
return;
}
if (items < cm->second->min_params)
{
user->WriteServ("461 %s %s :Not enough parameters.", user->nick, command.c_str());
- /* If syntax is given, display this as the 461 reply */
if ((ServerInstance->Config->SyntaxHints) && (user->registered == REG_ALL) && (cm->second->syntax.length()))
user->WriteServ("304 %s :SYNTAX %s %s", user->nick, cm->second->command.c_str(), cm->second->syntax.c_str());
return;
return;
/*
- * WARNING: nothing may come after the
- * command handler call, as the handler
- * may free the user structure!
+ * WARNING: nothing should come after this, as the user may be on a cull list to
+ * be nuked next loop iteration. be sensible.
*/
CmdResult result = cm->second->Handle(command_p,items,user);
if (x->source == std::string(source))
{
cmdlist.erase(safei);
+ delete x;
}
}
CommandParser::CommandParser(InspIRCd* Instance) : ServerInstance(Instance)
{
para.resize(128);
- this->SetupCommandTable();
}
bool CommandParser::FindSym(void** v, void* h)
return true;
}
-bool CommandParser::ReloadCommand(const char* cmd)
+bool CommandParser::ReloadCommand(const char* cmd, userrec* user)
{
char filename[MAXBUF];
char commandname[MAXBUF];
RFCCommands.erase(command);
snprintf(filename, MAXBUF, "cmd_%s.so", commandname);
- this->LoadCommand(filename);
+ const char* err = this->LoadCommand(filename);
+ if (err)
+ {
+ if (user)
+ user->WriteServ("NOTICE %s :*** Error loading 'cmd_%s.so': %s", user->nick, cmd, err);
+ return false;
+ }
return true;
}
CmdResult cmd_reload::Handle(const char** parameters, int pcnt, userrec *user)
{
user->WriteServ("NOTICE %s :*** Reloading command '%s'",user->nick, parameters[0]);
- if (ServerInstance->Parser->ReloadCommand(parameters[0]))
+ if (ServerInstance->Parser->ReloadCommand(parameters[0], user))
{
user->WriteServ("NOTICE %s :*** Successfully reloaded command '%s'", user->nick, parameters[0]);
ServerInstance->WriteOpers("*** RELOAD: %s reloaded the '%s' command.", user->nick, parameters[0]);
}
else
{
- user->WriteServ("NOTICE %s :*** Could not reload command '%s'", user->nick, parameters[0]);
+ user->WriteServ("NOTICE %s :*** Could not reload command '%s' -- fix this problem, then /REHASH as soon as possible!", user->nick, parameters[0]);
return CMD_FAILURE;
}
}
-void CommandParser::LoadCommand(const char* name)
+const char* CommandParser::LoadCommand(const char* name)
{
char filename[MAXBUF];
void* h;
command_t* (*cmd_factory_func)(InspIRCd*);
+ /* Command already exists? Succeed silently - this is needed for REHASH */
+ if (RFCCommands.find(name) != RFCCommands.end())
+ {
+ ServerInstance->Log(DEBUG,"Not reloading command %s/%s, it already exists", LIBRARYDIR, name);
+ return NULL;
+ }
+
snprintf(filename, MAXBUF, "%s/%s", LIBRARYDIR, name);
h = dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
if (!h)
{
- ServerInstance->Log(SPARSE, "Error loading core command: %s", dlerror());
- return;
+ const char* n = dlerror();
+ ServerInstance->Log(SPARSE, "Error loading core command: %s", n);
+ return n;
}
if (this->FindSym((void **)&cmd_factory_func, h))
command_t* newcommand = cmd_factory_func(ServerInstance);
this->CreateCommand(newcommand, h);
}
+ return NULL;
}
-void CommandParser::SetupCommandTable()
+void CommandParser::SetupCommandTable(userrec* user)
{
RFCCommands.clear();
- printf("\nLoading core commands");
- fflush(stdout);
+ if (!user)
+ {
+ printf("\nLoading core commands");
+ fflush(stdout);
+ }
DIR* library = opendir(LIBRARYDIR);
if (library)
{
if (match(entry->d_name, "cmd_*.so"))
{
- printf(".");
- fflush(stdout);
- this->LoadCommand(entry->d_name);
+ if (!user)
+ {
+ printf(".");
+ fflush(stdout);
+ }
+ const char* err = this->LoadCommand(entry->d_name);
+ if (err)
+ {
+ if (user)
+ {
+ user->WriteServ("NOTICE %s :*** Failed to load core command %s: %s", user->nick, entry->d_name, err);
+ }
+ else
+ {
+ printf("Error loading %s: %s", entry->d_name, err);
+ exit(EXIT_STATUS_BADHANDLER);
+ }
+ }
}
}
closedir(library);
- printf("\n");
+ if (!user)
+ printf("\n");
}
- this->CreateCommand(new cmd_reload(ServerInstance));
+ if (cmdlist.find("RELOAD") == cmdlist.end())
+ this->CreateCommand(new cmd_reload(ServerInstance));
}