bool ValidateServerName(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"Validating server name");
/* If we already have a servername, and they changed it, we should throw an exception. */
- if ((strcasecmp(conf->ServerName, data.GetString())) && (*conf->ServerName))
- {
- throw CoreException("Configuration error: You cannot change your servername at runtime! Please restart your server for this change to be applied.");
- /* We don't actually reach this return of course... */
- return false;
- }
- if (!strchr(data.GetString(),'.'))
+ if (!strchr(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(".");
bool ValidateSID(ServerConfig* conf, const char*, const char*, ValueItem &data)
{
+ conf->GetInstance()->Logs->Log("CONFIG",DEFAULT,"Validating server id");
+
const char *sid = data.GetString();
if (*sid && !conf->GetInstance()->IsSID(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.");
}
+ strlcpy(conf->sid, sid, 5);
+
return true;
}
{
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()->Logs->Log("CONFIG",DEBUG, "Address of class is %p", c);
- }
-
for (ClassVector::iterator i = conf->Classes.begin(); i != conf->Classes.end() ; )
{
ConnectClass* c = *i;
{"options", "softlimit", MAXCLIENTS_S, new ValueContainerUInt (&this->SoftLimit), DT_INTEGER, ValidateSoftLimit},
{"options", "somaxconn", SOMAXCONN_S, new ValueContainerInt (&this->MaxConn), DT_INTEGER, ValidateMaxConn},
{"options", "moronbanner", "Youre banned!", new ValueContainerChar (this->MoronBanner), DT_CHARPTR, NoValidation},
- {"server", "name", "", new ValueContainerChar (this->ServerName), DT_HOSTNAME, ValidateServerName},
+ {"server", "name", "", new ValueContainerChar (this->ServerName), DT_HOSTNAME|DT_BOOTONLY, ValidateServerName},
{"server", "description", "Configure Me", new ValueContainerChar (this->ServerDesc), DT_CHARPTR, NoValidation},
{"server", "network", "Network", new ValueContainerChar (this->Network), DT_NOSPACES, NoValidation},
- {"server", "id", "", new ValueContainerChar (this->sid), DT_CHARPTR, ValidateSID},
+ {"server", "id", "", new ValueContainerChar (this->sid), DT_CHARPTR|DT_BOOTONLY, 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},
/* Make a copy here so if it fails then we can carry on running with an unaffected config */
newconfig.clear();
- if (this->LoadConf(newconfig, ServerInstance->ConfigFileName, errstr))
+ if (this->DoInclude(newconfig, ServerInstance->ConfigFileName, errstr))
{
/* If we succeeded, set the ircd config to the new one */
ServerInstance->Threads->Mutex(true);
int dt = Values[Index].datatype;
bool allow_newlines = ((dt & DT_ALLOW_NEWLINE) > 0);
bool allow_wild = ((dt & DT_ALLOW_WILD) > 0);
+ bool bootonly = ((dt & DT_BOOTONLY) > 0);
dt &= ~DT_ALLOW_NEWLINE;
dt &= ~DT_ALLOW_WILD;
+ dt &= ~DT_BOOTONLY;
+
+ /* Silently ignore boot only values */
+ if (bootonly && !bail)
+ continue;
ConfValue(this->config_data, Values[Index].tag, Values[Index].value, Values[Index].default_value, 0, item, MAXBUF, allow_newlines);
ValueItem vi(item);
throw CoreException("One or more values in your configuration file failed to validate. Please see your ircd.log for more information.");
ServerInstance->Threads->Mutex(true);
- switch (Values[Index].datatype)
+ switch (dt)
{
case DT_NOSPACES:
{
ValueContainerChar* vcc = (ValueContainerChar*)Values[Index].val;
this->ValidateHostname(vi.GetString(), Values[Index].tag, Values[Index].value);
vcc->Set(vi.GetString(), strlen(vi.GetString()) + 1);
+ ServerInstance->Logs->Log("CONFIG",DEFAULT,"Got %s", vi.GetString());
}
break;
case DT_IPADDRESS:
}
-bool ServerConfig::LoadConf(ConfigDataHash &target, const char* filename, std::ostringstream &errorstream)
+bool ServerConfig::LoadConf(ConfigDataHash &target, FILE* &conf, const char* filename, std::ostringstream &errorstream)
{
- std::ifstream conf(filename);
std::string line;
char ch;
long linenumber;
in_quote = false;
in_comment = false;
+ ServerInstance->Logs->Log("CONFIG", DEBUG, "Reading %s", filename);
+
/* Check if the file open failed first */
if (!conf)
{
return false;
}
- /* Fix the chmod of the file to restrict it to the current user and group */
- chmod(filename,0600);
-
for (unsigned int t = 0; t < include_stack.size(); t++)
{
if (std::string(filename) == include_stack[t])
include_stack.push_back(filename);
/* Start reading characters... */
- while (conf.get(ch))
+ while (!feof(conf))
{
-
+ ch = fgetc(conf);
/*
* Fix for moronic windows issue spotted by Adremelech.
* Some windows editors save text files as utf-16, which is
{
line += ch;
char real_character;
- if (conf.get(real_character))
+ if (!feof(conf))
{
+ real_character = fgetc(conf);
if (real_character == 'n')
real_character = '\n';
line += real_character;
}
-bool ServerConfig::LoadConf(ConfigDataHash &target, const std::string &filename, std::ostringstream &errorstream)
+bool ServerConfig::LoadConf(ConfigDataHash &target, FILE* &conf, const std::string &filename, std::ostringstream &errorstream)
{
- return this->LoadConf(target, filename.c_str(), errorstream);
+ return this->LoadConf(target, conf, filename.c_str(), errorstream);
}
bool ServerConfig::ParseLine(ConfigDataHash &target, std::string &line, long &linenumber, std::ostringstream &errorstream)
if (!this->DoInclude(target, current_value, errorstream))
return false;
}
+ else if ((tagname == "include") && (current_key == "executable"))
+ {
+ /* Pipe an executable and use its stdout as config data */
+ if (!this->DoPipe(target, current_value, errorstream))
+ return false;
+ }
current_key.clear();
current_value.clear();
return true;
}
+bool ServerConfig::DoPipe(ConfigDataHash &target, const std::string &file, std::ostringstream &errorstream)
+{
+ FILE* conf = popen(file.c_str(), "r");
+ bool ret = false;
+
+ if (conf)
+ {
+ ret = LoadConf(target, conf, file.c_str(), errorstream);
+ pclose(conf);
+ }
+ else
+ errorstream << "Couldn't execute: " << file << std::endl;
+
+ return ret;
+}
+
bool ServerConfig::DoInclude(ConfigDataHash &target, const std::string &file, std::ostringstream &errorstream)
{
std::string confpath;
}
}
- return LoadConf(target, newfile, errorstream);
+ FILE* conf = fopen(newfile.c_str(), "r");
+ bool ret = false;
+
+ if (conf)
+ {
+ ret = LoadConf(target, conf, newfile, errorstream);
+ fclose(conf);
+ }
+ else
+ errorstream << "Couldn't open config file: " << file << std::endl;
+
+ return ret;
}
bool ServerConfig::ConfValue(ConfigDataHash &target, const char* tag, const char* var, int index, char* result, int length, bool allow_linefeeds)
{
/* TODO: TheUser may be invalid by the time we get here! Check its validity, or pass a UID would be better */
ServerInstance->Config->Read(do_bail, TheUser);
+ ServerInstance->Threads->Mutex(true);
+ this->SetExitFlag();
+ ServerInstance->Threads->Mutex(false);
}