* | Inspire Internet Relay Chat Daemon |
* +------------------------------------+
*
- * InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * InspIRCd: (C) 2002-2008 InspIRCd Development Team
* See: http://www.inspircd.org/wiki/index.php/Credits
*
* This program is free but copyrighted software; see
user->WriteServ("005 %s %s", user->nick, line->c_str());
}
-bool ServerConfig::CheckOnce(char* tag)
+bool ServerConfig::CheckOnce(const char* tag)
{
int count = ConfValueEnum(this->config_data, tag);
{
if ((data.GetInteger() < 0) || (data.GetInteger() > 31))
{
- conf->GetInstance()->Log(DEFAULT,"WARNING: <options:maxtargets> value is greater than 31 or less than 0, set to 20.");
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"WARNING: <options:maxtargets> value is greater than 31 or less than 0, set to 20.");
data.Set(20);
}
return true;
{
if ((data.GetInteger() < 1) || (data.GetInteger() > MAXCLIENTS))
{
- conf->GetInstance()->Log(DEFAULT,"WARNING: <options:softlimit> value is greater than %d or less than 0, set to %d.",MAXCLIENTS,MAXCLIENTS);
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"WARNING: <options:softlimit> value is greater than %d or less than 0, set to %d.",MAXCLIENTS,MAXCLIENTS);
data.Set(MAXCLIENTS);
}
return true;
bool ValidateMaxConn(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
if (data.GetInteger() > SOMAXCONN)
- conf->GetInstance()->Log(DEFAULT,"WARNING: <options:somaxconn> value may be higher than the system-defined SOMAXCONN value!");
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"WARNING: <options:somaxconn> value may be higher than the system-defined SOMAXCONN value!");
return true;
}
{
std::string nameserver;
// attempt to look up their nameserver from /etc/resolv.conf
- conf->GetInstance()->Log(DEFAULT,"WARNING: <dns:server> not defined, attempting to find working server in /etc/resolv.conf...");
- ifstream resolv("/etc/resolv.conf");
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"WARNING: <dns:server> not defined, attempting to find working server in /etc/resolv.conf...");
+ std::ifstream resolv("/etc/resolv.conf");
bool found_server = false;
if (resolv.is_open())
resolv >> nameserver;
data.Set(nameserver.c_str());
found_server = true;
- conf->GetInstance()->Log(DEFAULT,"<dns:server> set to '%s' as first resolver in /etc/resolv.conf.",nameserver.c_str());
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"<dns:server> set to '%s' as first resolver in /etc/resolv.conf.",nameserver.c_str());
}
}
if (!found_server)
{
- conf->GetInstance()->Log(DEFAULT,"/etc/resolv.conf contains no viable nameserver entries! Defaulting to nameserver '127.0.0.1'!");
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"/etc/resolv.conf contains no viable nameserver entries! Defaulting to nameserver '127.0.0.1'!");
data.Set("127.0.0.1");
}
}
else
{
- conf->GetInstance()->Log(DEFAULT,"/etc/resolv.conf can't be opened! Defaulting to nameserver '127.0.0.1'!");
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"/etc/resolv.conf can't be opened! Defaulting to nameserver '127.0.0.1'!");
data.Set("127.0.0.1");
}
}
}
if (!strchr(data.GetString(),'.'))
{
- conf->GetInstance()->Log(DEFAULT,"WARNING: <server:name> '%s' is not a fully-qualified domain name. Changed to '%s%c'",data.GetString(),data.GetString(),'.');
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"WARNING: <server:name> '%s' is not a fully-qualified domain name. Changed to '%s%c'",data.GetString(),data.GetString(),'.');
std::string moo = std::string(data.GetString()).append(".");
data.Set(moo.c_str());
}
{
if ((!data.GetInteger()) || (data.GetInteger() > 65535) || (data.GetInteger() < 1024))
{
- conf->GetInstance()->Log(DEFAULT,"No NetBufferSize specified or size out of range, setting to default of 10240.");
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"No NetBufferSize specified or size out of range, setting to default of 10240.");
data.Set(10240);
}
return true;
{
if ((data.GetInteger() > 65535) || (data.GetInteger() < 1))
{
- conf->GetInstance()->Log(DEFAULT,"<options:maxwhoresults> size out of range, setting to default of 128.");
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"<options:maxwhoresults> size out of range, setting to default of 128.");
data.Set(128);
}
return true;
bool ValidateSID(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
- int sid = data.GetInteger();
- if ((sid > 999) || (sid < 0))
+ const char *sid = data.GetString();
+
+ if (*sid && !conf->GetInstance()->IsSID(sid))
{
- sid = sid % 1000;
- data.Set(sid);
- conf->GetInstance()->Log(DEFAULT,"WARNING: Server ID is less than 0 or greater than 999. Set to %d", sid);
+ throw CoreException(std::string(sid) + " is not a valid server ID. A server ID must be 3 characters long, with the first character a digit and the next two characters a digit or letter.");
}
+
return true;
}
if (conf->WhoWasMaxKeep < 3600)
{
conf->WhoWasMaxKeep = 3600;
- conf->GetInstance()->Log(DEFAULT,"WARNING: <whowas:maxkeep> value less than 3600, setting to default 3600");
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"WARNING: <whowas:maxkeep> value less than 3600, setting to default 3600");
}
Command* whowas_command = conf->GetInstance()->Parser->GetHandler("WHOWAS");
*/
bool InitConnect(ServerConfig* conf, const char*)
{
- conf->GetInstance()->Log(DEFAULT,"Reading connect classes...");
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"Reading connect classes...");
for (ClassVector::iterator i = conf->Classes.begin(); i != conf->Classes.end(); i++)
{
ConnectClass *c = *i;
- conf->GetInstance()->Log(DEBUG, "Address of class is %p", c);
+ conf->GetInstance()->Logs->Log("CONFIG",DEBUG, "Address of class is %p", c);
}
- for (ClassVector::iterator i = conf->Classes.begin(); i != conf->Classes.end(); i++)
+ for (ClassVector::iterator i = conf->Classes.begin(); i != conf->Classes.end() ; )
{
- ConnectClass *c = *i;
+ ConnectClass* c = *i;
/* only delete a class with refcount 0 */
if (c->RefCount == 0)
{
- conf->GetInstance()->Log(DEFAULT, "Removing connect class, refcount is 0!");
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT, "Removing connect class, refcount is 0!");
+
+ /* This was causing a crash, because we'd set i to .begin() just here, but then the for loop's increment would
+ * set it to .begin() + 1. Which if it was already the last thing in the list, wasn't good.
+ * Now the increment is in the else { } below.
+ */
conf->Classes.erase(i);
i = conf->Classes.begin(); // start over so we don't trample on a bad iterator
}
-
- /* also mark all existing classes disabled, if they still exist in the conf, they will be reenabled. */
- c->SetDisabled(true);
+ else
+ {
+ /* also mark all existing classes disabled, if they still exist in the conf, they will be reenabled. */
+ c->SetDisabled(true);
+ i++;
+ }
}
return true;
const char* parent = values[13].GetString();
int maxchans = values[14].GetInteger();
unsigned long limit = values[15].GetInteger();
+ const char* hashtype = values[16].GetString();
/*
* duplicates check: Now we don't delete all connect classes on rehash, we need to ensure we don't add dupes.
*/
for (ClassVector::iterator item = conf->Classes.begin(); item != conf->Classes.end(); ++item)
{
- ConnectClass* c = *item;
- if ((*name && (c->GetName() == name)) || (*allow && (c->GetHost() == allow)) || (*deny && (c->GetHost() == deny)))
+ ConnectClass* cc = *item;
+ if ((*name && (cc->GetName() == name)) || (*allow && (cc->GetHost() == allow)) || (*deny && (cc->GetHost() == deny)))
{
/* reenable class so users can be shoved into it :P */
- c->SetDisabled(false);
- conf->GetInstance()->Log(DEFAULT, "Not adding class, it already exists!");
+ cc->SetDisabled(false);
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT, "Not adding class, it already exists!");
return true;
}
}
- conf->GetInstance()->Log(DEFAULT,"Adding a connect class!");
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"Adding a connect class!");
if (*parent)
{
ClassVector::iterator item = conf->Classes.begin();
for (; item != conf->Classes.end(); ++item)
{
- ConnectClass* c = *item;
- conf->GetInstance()->Log(DEBUG,"Class: %s", c->GetName().c_str());
- if (c->GetName() == parent)
+ ConnectClass* cc = *item;
+ conf->GetInstance()->Logs->Log("CONFIG",DEBUG,"Class: %s", cc->GetName().c_str());
+ if (cc->GetName() == parent)
{
- ConnectClass* newclass = new ConnectClass(name, c);
+ ConnectClass* newclass = new ConnectClass(name, cc);
newclass->Update(timeout, flood, *allow ? allow : deny, pingfreq, password, threshold, sendq, recvq, localmax, globalmax, maxchans, port, limit);
conf->Classes.push_back(newclass);
break;
{
if (*allow)
{
- ConnectClass* c = new ConnectClass(name, timeout, flood, allow, pingfreq, password, threshold, sendq, recvq, localmax, globalmax, maxchans);
- c->limit = limit;
- c->SetPort(port);
- conf->Classes.push_back(c);
+ ConnectClass* cc = new ConnectClass(name, timeout, flood, allow, pingfreq, password, hashtype, threshold, sendq, recvq, localmax, globalmax, maxchans);
+ cc->limit = limit;
+ cc->SetPort(port);
+ conf->Classes.push_back(cc);
}
else
{
- ConnectClass* c = new ConnectClass(name, deny);
- c->SetPort(port);
- conf->Classes.push_back(c);
+ ConnectClass* cc = new ConnectClass(name, deny);
+ cc->SetPort(port);
+ conf->Classes.push_back(cc);
}
}
*/
bool DoneConnect(ServerConfig *conf, const char*)
{
- conf->GetInstance()->Log(DEFAULT, "Done adding connect classes!");
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT, "Done adding connect classes!");
return true;
}
void ServerConfig::ReportConfigError(const std::string &errormessage, bool bail, User* user)
{
- ServerInstance->Log(DEFAULT, "There were errors in your configuration file: %s", errormessage.c_str());
+ ServerInstance->Logs->Log("CONFIG",DEFAULT, "There were errors in your configuration file: %s", errormessage.c_str());
if (bail)
{
/* Unneeded because of the ServerInstance->Log() aboive? */
}
else
{
- ServerInstance->WriteOpers("There were errors in the configuration file:");
+ ServerInstance->SNO->WriteToSnoMask('A', "There were errors in the configuration file:");
while (start < errors.length())
{
- ServerInstance->WriteOpers(errors.substr(start, 360).c_str());
+ ServerInstance->SNO->WriteToSnoMask('A', errors.substr(start, 360).c_str());
start += 360;
}
}
errstr.clear();
/* These tags MUST occur and must ONLY occur once in the config file */
- static char* Once[] = { "server", "admin", "files", "power", "options", NULL };
+ static const char* Once[] = { "server", "admin", "files", "power", "options", NULL };
/* These tags can occur ONCE or not at all */
InitialConfig Values[] = {
{"server", "name", "", new ValueContainerChar (this->ServerName), DT_HOSTNAME, ValidateServerName},
{"server", "description", "Configure Me", new ValueContainerChar (this->ServerDesc), DT_CHARPTR, NoValidation},
{"server", "network", "Network", new ValueContainerChar (this->Network), DT_NOSPACES, NoValidation},
- {"server", "id", "0", new ValueContainerInt (&this->sid), DT_NOSPACES, ValidateSID},
+ {"server", "id", "", new ValueContainerChar (this->sid), DT_CHARPTR, ValidateSID},
{"admin", "name", "", new ValueContainerChar (this->AdminName), DT_CHARPTR, NoValidation},
{"admin", "email", "Mis@configu.red", new ValueContainerChar (this->AdminEmail), DT_CHARPTR, NoValidation},
{"admin", "nick", "Misconfigured", new ValueContainerChar (this->AdminNick), DT_CHARPTR, NoValidation},
{"files", "rules", "", new ValueContainerChar (this->rules), DT_CHARPTR, ValidateRules},
{"power", "diepass", "", new ValueContainerChar (this->diepass), DT_CHARPTR, ValidateNotEmpty},
{"power", "pause", "", new ValueContainerInt (&this->DieDelay), DT_INTEGER, NoValidation},
+ {"power", "hash", "", new ValueContainerChar (this->powerhash), DT_CHARPTR, NoValidation},
{"power", "restartpass", "", new ValueContainerChar (this->restartpass), DT_CHARPTR, ValidateNotEmpty},
{"options", "prefixquit", "", new ValueContainerChar (this->PrefixQuit), DT_CHARPTR, NoValidation},
{"options", "suffixquit", "", new ValueContainerChar (this->SuffixQuit), DT_CHARPTR, NoValidation},
{"options", "fixedquit", "", new ValueContainerChar (this->FixedQuit), DT_CHARPTR, NoValidation},
+ {"options", "prefixpart", "", new ValueContainerChar (this->PrefixPart), DT_CHARPTR, NoValidation},
+ {"options", "suffixpart", "", new ValueContainerChar (this->SuffixPart), DT_CHARPTR, NoValidation},
+ {"options", "fixedpart", "", new ValueContainerChar (this->FixedPart), DT_CHARPTR, NoValidation},
{"options", "loglevel", "default", new ValueContainerChar (debug), DT_CHARPTR, ValidateLogLevel},
{"options", "netbuffersize","10240", new ValueContainerInt (&this->NetBufferSize), DT_INTEGER, ValidateNetBufferSize},
{"options", "maxwho", "128", new ValueContainerInt (&this->MaxWhoResults), DT_INTEGER, ValidateMaxWho},
{"connect",
{"allow", "deny", "password", "timeout", "pingfreq", "flood",
"threshold", "sendq", "recvq", "localmax", "globalmax", "port",
- "name", "parent", "maxchans", "limit",
+ "name", "parent", "maxchans", "limit", "hash",
NULL},
{"", "", "", "", "120", "",
"", "", "", "3", "3", "0",
- "", "", "0", "0",
+ "", "", "0", "0", "",
NULL},
{DT_IPADDRESS|DT_ALLOW_WILD,
DT_IPADDRESS|DT_ALLOW_WILD,
DT_CHARPTR, DT_INTEGER, DT_INTEGER, DT_INTEGER,
DT_INTEGER, DT_INTEGER, DT_INTEGER, DT_INTEGER, DT_INTEGER, DT_INTEGER,
- DT_NOSPACES, DT_NOSPACES, DT_INTEGER, DT_INTEGER},
+ DT_NOSPACES, DT_NOSPACES, DT_INTEGER, DT_INTEGER, DT_CHARPTR},
InitConnect, DoConnect, DoneConnect},
{"uline",
}
/** XXX END PASS **/
- ServerInstance->Log(DEBUG,"End config pass %d", pass);
+ ServerInstance->Logs->Log("CONFIG",DEBUG,"End config pass %d", pass);
if (pass == 0)
{
if (pass == 0)
{
- if (isatty(0) && isatty(1) && isatty(2))
- printf("Downloading configuration ");
+ ServerInstance->Logs->Log("CONFIG",DEBUG, "Downloading configuration");
TotalDownloaded = 0;
FileErrors = 0;
* stuff. Check that we have at least the required number
* of whichever items. This is no longer done first.
*/
+ /* Close all logs at this point and reopen <log method="file"> logs. */
+ ServerInstance->Logs->CloseLogs();
+ ServerInstance->Logs->OpenFileLogs();
ConfigReader* n = new ConfigReader(ServerInstance);
FOREACH_MOD(I_OnReadConfig,OnReadConfig(this, n));
// write once here, to try it out and make sure its ok
ServerInstance->WritePID(this->PID);
- ServerInstance->Log(DEFAULT,"Done reading configuration file.");
+ ServerInstance->Logs->Log("CONFIG",DEFAULT,"Done reading configuration file.");
/* If we're rehashing, let's load any new modules, and unload old ones
*/
{
if (ServerInstance->Modules->Unload(removing->c_str()))
{
- ServerInstance->WriteOpers("*** REHASH UNLOADED MODULE: %s",removing->c_str());
+ ServerInstance->SNO->WriteToSnoMask('A', "REHASH UNLOADED MODULE: %s",removing->c_str());
if (user)
user->WriteServ("973 %s %s :Module %s successfully unloaded.",user->nick, removing->c_str(), removing->c_str());
rem++;
if (ServerInstance->Modules->Load(adding->c_str()))
{
- ServerInstance->WriteOpers("*** REHASH LOADED MODULE: %s",adding->c_str());
+ ServerInstance->SNO->WriteToSnoMask('A', "REHASH LOADED MODULE: %s",adding->c_str());
if (user)
user->WriteServ("975 %s %s :Module %s successfully loaded.",user->nick, adding->c_str(), adding->c_str());
}
}
- ServerInstance->Log(DEFAULT,"Successfully unloaded %lu of %lu modules and loaded %lu of %lu modules.",(unsigned long)rem,(unsigned long)removed_modules.size(),(unsigned long)add,(unsigned long)added_modules.size());
+ ServerInstance->Logs->Log("CONFIG",DEFAULT,"Successfully unloaded %lu of %lu modules and loaded %lu of %lu modules.",(unsigned long)rem,(unsigned long)removed_modules.size(),(unsigned long)add,(unsigned long)added_modules.size());
if (user)
user->WriteServ("NOTICE %s :*** Successfully rehashed server.", user->nick);
else
- ServerInstance->WriteOpers("*** Successfully rehashed server.");
-}
-
-bool ServerConfig::Downloading()
-{
- if (isatty(0) && isatty(1) && isatty(2))
- {
- printf(".");
- fflush(stdout);
- }
-
- ServerInstance->Log(DEBUG, "ServerConfig::Downloading %d %d", TotalDownloaded, IncludedFiles.size());
-
- /* Returns true if there are still files in the process of downloading */
- return (TotalDownloaded < IncludedFiles.size());
-}
-
-void ServerConfig::Complete(const std::string &filename, bool error)
-{
- ServerInstance->Log(DEBUG,"Flag complete: %s %d", filename.c_str(), error);
- std::map<std::string, std::istream*>::iterator x = IncludedFiles.find(filename);
-
- if (x != IncludedFiles.end())
- {
- if (error)
- {
- delete x->second;
- x->second = NULL;
- FileErrors++;
- }
- else
- {
- ServerInstance->Log(DEBUG,"Recursively follow conf %s", x->first.c_str());
- LoadConf(newconfig, x->first.c_str(), errstr, 0, x->second);
- StartDownloads();
- }
- TotalDownloaded++;
- }
-
- return;
+ ServerInstance->SNO->WriteToSnoMask('A', "Successfully rehashed server.");
}
-void ServerConfig::StartDownloads()
+/* XXX: This can and will block! */
+void ServerConfig::DoDownloads()
{
- ServerInstance->Log(DEBUG,"StartDownloads() size=%d", IncludedFiles.size());
+ ServerInstance->Logs->Log("CONFIG",DEBUG,"In DoDownloads()");
/* Reads all local files into the IncludedFiles map, then initiates sockets for the remote ones */
for (std::map<std::string, std::istream*>::iterator x = IncludedFiles.begin(); x != IncludedFiles.end(); ++x)
if (CompletedFiles.find(x->first) != CompletedFiles.end())
continue;
+ ServerInstance->Logs->Log("CONFIG",DEBUG,"StartDownloads File: %s", x->first.c_str());
+
std::string file = x->first;
if ((file[0] == '/') || (file.substr(0, 7) == "file://"))
{
std::ifstream* conf = new std::ifstream(file.c_str());
if (!conf->fail())
{
- ServerInstance->Log(DEBUG,"file:// schema file %s loaded OK", file.c_str());
+ ServerInstance->Logs->Log("CONFIG",DEBUG,"file:// schema file %s loaded OK", file.c_str());
delete x->second;
x->second = conf;
}
else
{
/* Modules handle these */
- ServerInstance->Log(DEBUG,"Module-handled schema for %s", x->first.c_str());
+ ServerInstance->Logs->Log("CONFIG",DEBUG,"Module-handled schema for %s", x->first.c_str());
/* For now, error it */
int MOD_RESULT = 0;
delete x->second;
x->second = NULL;
}
+ else
+ {
+ /* Search new file here for more includes to parse */
+ }
}
CompletedFiles[x->first] = true;
}
if (scan_for_includes_only)
{
- ServerInstance->Log(DEBUG,"scan_for_includes_only set");
+ ServerInstance->Logs->Log("CONFIG",DEBUG,"scan_for_includes_only set");
conf = scan_for_includes_only;
}
{
if (pass == 0)
{
- ServerInstance->Log(DEBUG,"Push include file %s onto map", filename);
+ ServerInstance->Logs->Log("CONFIG",DEBUG,"Push include file %s onto map", filename);
/* First pass, we insert the file into a map, and just return true */
IncludedFiles.insert(std::make_pair(filename,new std::stringstream));
return true;
else
{
/* Second pass, look for the file in the map */
- ServerInstance->Log(DEBUG,"We are in the second pass, and %s is not in the map!", filename);
+ ServerInstance->Logs->Log("CONFIG",DEBUG,"We are in the second pass, and %s is not in the map!", filename);
errorstream << "File " << filename << " could not be opened." << std::endl;
return false;
}
}
}
- ServerInstance->Log(DEBUG,"Start to read conf %s %08lx", filename, conf);
+ ServerInstance->Logs->Log("CONFIG",DEBUG,"Start to read conf %s %08lx", filename, conf);
/* Start reading characters... */
while (conf->get(ch))
{
if ((!allow_linefeeds) && (j->second.find('\n') != std::string::npos))
{
- ServerInstance->Log(DEFAULT, "Value of <" + tag + ":" + var+ "> contains a linefeed, and linefeeds in this value are not permitted -- stripped to spaces.");
+ ServerInstance->Logs->Log("CONFIG",DEFAULT, "Value of <" + tag + ":" + var+ "> contains a linefeed, and linefeeds in this value are not permitted -- stripped to spaces.");
for (std::string::iterator n = j->second.begin(); n != j->second.end(); n++)
if (*n == '\n')
*n = ' ';
std::string ServerConfig::GetSID()
{
- std::string OurSID;
- OurSID += (char)((sid / 100) + 48);
- OurSID += (char)((sid / 10) % 10 + 48);
- OurSID += (char)(sid % 10 + 48);
- return OurSID;
+ return sid;
}
ValueItem::ValueItem(int value)
v = n.str();
}
-ValueItem::ValueItem(char* value)
-{
- v = value;
-}
-
-void ValueItem::Set(char* value)
+ValueItem::ValueItem(const char* value)
{
v = value;
}
// this should probably be moved to configreader, but atm it relies on CheckELines above.
bool DoneELine(ServerConfig* conf, const char* tag)
{
- for (std::vector<User*>::const_iterator u2 = conf->GetInstance()->local_users.begin(); u2 != conf->GetInstance()->local_users.end(); u2++)
+ for (std::vector<User*>::const_iterator u2 = conf->GetInstance()->Users->local_users.begin(); u2 != conf->GetInstance()->Users->local_users.end(); u2++)
{
User* u = (User*)(*u2);
u->exempt = false;
conf->GetInstance()->XLines->CheckELines();
return true;
}
-