]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/configreader.cpp
Fix multiple (useless) linefeeds on the end of ADDLINE in burst
[user/henk/code/inspircd.git] / src / configreader.cpp
index bf8fc9742d2bfc47651d70d796c8e108e4381a5d..7ca1a81250c3f403975553df77c603ff9351c4e3 100644 (file)
@@ -520,13 +520,6 @@ bool InitConnect(ServerConfig* conf, const char*)
 {
        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;
@@ -950,10 +943,12 @@ void ServerConfig::Read(bool bail, User* user)
        /* 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);
                this->config_data = newconfig;
+               ServerInstance->Threads->Mutex(false);
        }
        else
        {
@@ -987,6 +982,7 @@ void ServerConfig::Read(bool bail, User* user)
                        if (!Values[Index].validation_function(this, Values[Index].tag, Values[Index].value, vi))
                                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)
                        {
                                case DT_NOSPACES:
@@ -1014,7 +1010,10 @@ void ServerConfig::Read(bool bail, User* user)
                                {
                                        ValueContainerChar* vcc = (ValueContainerChar*)Values[Index].val;
                                        if (*(vi.GetString()) && !ServerInstance->IsChannel(vi.GetString()))
+                                       {
+                                               ServerInstance->Threads->Mutex(false);
                                                throw CoreException("The value of <"+std::string(Values[Index].tag)+":"+Values[Index].value+"> is not a valid channel name");
+                                       }
                                        vcc->Set(vi.GetString(), strlen(vi.GetString()) + 1);
                                }
                                break;
@@ -1045,6 +1044,7 @@ void ServerConfig::Read(bool bail, User* user)
                        }
                        /* We're done with this now */
                        delete Values[Index].val;
+                       ServerInstance->Threads->Mutex(false);
                }
 
                /* Read the multiple-tag items (class tags, connect tags, etc)
@@ -1053,7 +1053,9 @@ void ServerConfig::Read(bool bail, User* user)
                 */
                for (int Index = 0; MultiValues[Index].tag; Index++)
                {
+                       ServerInstance->Threads->Mutex(true);
                        MultiValues[Index].init_function(this, MultiValues[Index].tag);
+                       ServerInstance->Threads->Mutex(false);
 
                        int number_of_tags = ConfValueEnum(this->config_data, MultiValues[Index].tag);
 
@@ -1068,81 +1070,93 @@ void ServerConfig::Read(bool bail, User* user)
                                        dt &= ~DT_ALLOW_NEWLINE;
                                        dt &= ~DT_ALLOW_WILD;
 
-                                       switch (dt)
+                                       ServerInstance->Threads->Mutex(true);
+                                       /* We catch and rethrow any exception here just so we can free our mutex
+                                        */
+                                       try
                                        {
-                                               case DT_NOSPACES:
-                                               {
-                                                       char item[MAXBUF];
-                                                       if (ConfValue(this->config_data, MultiValues[Index].tag, MultiValues[Index].items[valuenum], MultiValues[Index].items_default[valuenum], tagnum, item, MAXBUF, allow_newlines))
-                                                               vl.push_back(ValueItem(item));
-                                                       else
-                                                               vl.push_back(ValueItem(""));
-                                                       this->ValidateNoSpaces(vl[vl.size()-1].GetString(), MultiValues[Index].tag, MultiValues[Index].items[valuenum]);
-                                               }
-                                               break;
-                                               case DT_HOSTNAME:
-                                               {
-                                                       char item[MAXBUF];
-                                                       if (ConfValue(this->config_data, MultiValues[Index].tag, MultiValues[Index].items[valuenum], MultiValues[Index].items_default[valuenum], tagnum, item, MAXBUF, allow_newlines))
-                                                               vl.push_back(ValueItem(item));
-                                                       else
-                                                               vl.push_back(ValueItem(""));
-                                                       this->ValidateHostname(vl[vl.size()-1].GetString(), MultiValues[Index].tag, MultiValues[Index].items[valuenum]);
-                                               }
-                                               break;
-                                               case DT_IPADDRESS:
-                                               {
-                                                       char item[MAXBUF];
-                                                       if (ConfValue(this->config_data, MultiValues[Index].tag, MultiValues[Index].items[valuenum], MultiValues[Index].items_default[valuenum], tagnum, item, MAXBUF, allow_newlines))
-                                                               vl.push_back(ValueItem(item));
-                                                       else
-                                                               vl.push_back(ValueItem(""));
-                                                       this->ValidateIP(vl[vl.size()-1].GetString(), MultiValues[Index].tag, MultiValues[Index].items[valuenum], allow_wild);
-                                               }
-                                               break;
-                                               case DT_CHANNEL:
-                                               {
-                                                       char item[MAXBUF];
-                                                       if (ConfValue(this->config_data, MultiValues[Index].tag, MultiValues[Index].items[valuenum], MultiValues[Index].items_default[valuenum], tagnum, item, MAXBUF, allow_newlines))
-                                                               vl.push_back(ValueItem(item));
-                                                       else
-                                                               vl.push_back(ValueItem(""));
-                                                       if (!ServerInstance->IsChannel(vl[vl.size()-1].GetString()))
-                                                               throw CoreException("The value of <"+std::string(MultiValues[Index].tag)+":"+MultiValues[Index].items[valuenum]+"> number "+ConvToStr(tagnum + 1)+" is not a valid channel name");
-                                               }
-                                               break;
-                                               case DT_CHARPTR:
-                                               {
-                                                       char item[MAXBUF];
-                                                       if (ConfValue(this->config_data, MultiValues[Index].tag, MultiValues[Index].items[valuenum], MultiValues[Index].items_default[valuenum], tagnum, item, MAXBUF, allow_newlines))
-                                                               vl.push_back(ValueItem(item));
-                                                       else
-                                                               vl.push_back(ValueItem(""));
-                                               }
-                                               break;
-                                               case DT_INTEGER:
+                                               switch (dt)
                                                {
-                                                       int item = 0;
-                                                       if (ConfValueInteger(this->config_data, MultiValues[Index].tag, MultiValues[Index].items[valuenum], MultiValues[Index].items_default[valuenum], tagnum, item))
+                                                       case DT_NOSPACES:
+                                                       {
+                                                               char item[MAXBUF];
+                                                               if (ConfValue(this->config_data, MultiValues[Index].tag, MultiValues[Index].items[valuenum], MultiValues[Index].items_default[valuenum], tagnum, item, MAXBUF, allow_newlines))
+                                                                       vl.push_back(ValueItem(item));
+                                                               else
+                                                                       vl.push_back(ValueItem(""));
+                                                               this->ValidateNoSpaces(vl[vl.size()-1].GetString(), MultiValues[Index].tag, MultiValues[Index].items[valuenum]);
+                                                       }
+                                                       break;
+                                                       case DT_HOSTNAME:
+                                                       {
+                                                               char item[MAXBUF];
+                                                               if (ConfValue(this->config_data, MultiValues[Index].tag, MultiValues[Index].items[valuenum], MultiValues[Index].items_default[valuenum], tagnum, item, MAXBUF, allow_newlines))
+                                                                       vl.push_back(ValueItem(item));
+                                                               else
+                                                                       vl.push_back(ValueItem(""));
+                                                               this->ValidateHostname(vl[vl.size()-1].GetString(), MultiValues[Index].tag, MultiValues[Index].items[valuenum]);
+                                                       }
+                                                       break;
+                                                       case DT_IPADDRESS:
+                                                       {
+                                                               char item[MAXBUF];
+                                                               if (ConfValue(this->config_data, MultiValues[Index].tag, MultiValues[Index].items[valuenum], MultiValues[Index].items_default[valuenum], tagnum, item, MAXBUF, allow_newlines))
+                                                                       vl.push_back(ValueItem(item));
+                                                               else
+                                                                       vl.push_back(ValueItem(""));
+                                                               this->ValidateIP(vl[vl.size()-1].GetString(), MultiValues[Index].tag, MultiValues[Index].items[valuenum], allow_wild);
+                                                       }
+                                                       break;
+                                                       case DT_CHANNEL:
+                                                       {
+                                                               char item[MAXBUF];
+                                                               if (ConfValue(this->config_data, MultiValues[Index].tag, MultiValues[Index].items[valuenum], MultiValues[Index].items_default[valuenum], tagnum, item, MAXBUF, allow_newlines))
+                                                                       vl.push_back(ValueItem(item));
+                                                               else
+                                                                       vl.push_back(ValueItem(""));
+                                                               if (!ServerInstance->IsChannel(vl[vl.size()-1].GetString()))
+                                                                       throw CoreException("The value of <"+std::string(MultiValues[Index].tag)+":"+MultiValues[Index].items[valuenum]+"> number "+ConvToStr(tagnum + 1)+" is not a valid channel name");
+                                                       }
+                                                       break;
+                                                       case DT_CHARPTR:
+                                                       {
+                                                               char item[MAXBUF];
+                                                               if (ConfValue(this->config_data, MultiValues[Index].tag, MultiValues[Index].items[valuenum], MultiValues[Index].items_default[valuenum], tagnum, item, MAXBUF, allow_newlines))
+                                                                       vl.push_back(ValueItem(item));
+                                                               else
+                                                                       vl.push_back(ValueItem(""));
+                                                       }
+                                                       break;
+                                                       case DT_INTEGER:
+                                                       {
+                                                               int item = 0;
+                                                               if (ConfValueInteger(this->config_data, MultiValues[Index].tag, MultiValues[Index].items[valuenum], MultiValues[Index].items_default[valuenum], tagnum, item))
+                                                                       vl.push_back(ValueItem(item));
+                                                               else
+                                                                       vl.push_back(ValueItem(0));
+                                                       }
+                                                       break;
+                                                       case DT_BOOLEAN:
+                                                       {
+                                                               bool item = ConfValueBool(this->config_data, MultiValues[Index].tag, MultiValues[Index].items[valuenum], MultiValues[Index].items_default[valuenum], tagnum);
                                                                vl.push_back(ValueItem(item));
-                                                       else
-                                                               vl.push_back(ValueItem(0));
-                                               }
-                                               break;
-                                               case DT_BOOLEAN:
-                                               {
-                                                       bool item = ConfValueBool(this->config_data, MultiValues[Index].tag, MultiValues[Index].items[valuenum], MultiValues[Index].items_default[valuenum], tagnum);
-                                                       vl.push_back(ValueItem(item));
+                                                       }
+                                                       break;
+                                                       default:
+                                                               /* Someone was smoking craq if we got here, and we're all gonna die. */
+                                                       break;
                                                }
-                                               break;
-                                               default:
-                                                       /* Someone was smoking craq if we got here, and we're all gonna die. */
-                                               break;
                                        }
+                                       catch (CoreException &e)
+                                       {
+                                               ServerInstance->Threads->Mutex(false);
+                                               throw e;
+                                       }
+                                       ServerInstance->Threads->Mutex(false);
                                }
-                                       MultiValues[Index].validation_function(this, MultiValues[Index].tag, (char**)MultiValues[Index].items, vl, MultiValues[Index].datatype);
+                               MultiValues[Index].validation_function(this, MultiValues[Index].tag, (char**)MultiValues[Index].items, vl, MultiValues[Index].datatype);
                        }
-                               MultiValues[Index].finish_function(this, MultiValues[Index].tag);
+                       MultiValues[Index].finish_function(this, MultiValues[Index].tag);
                }
 
        }
@@ -1172,6 +1186,7 @@ void ServerConfig::Read(bool bail, User* user)
 
                if (pl.size() && user)
                {
+                       ServerInstance->Threads->Mutex(true);
                        user->WriteServ("NOTICE %s :*** Not all your client ports could be bound.", user->nick);
                        user->WriteServ("NOTICE %s :*** The following port(s) failed to bind:", user->nick);
                        int j = 1;
@@ -1179,8 +1194,10 @@ void ServerConfig::Read(bool bail, User* user)
                        {
                                user->WriteServ("NOTICE %s :*** %d.   IP: %s     Port: %lu", user->nick, j, i->first.empty() ? "<all>" : i->first.c_str(), (unsigned long)i->second);
                        }
+                       ServerInstance->Threads->Mutex(false);
                }
 
+               ServerInstance->Threads->Mutex(true);
                if (!removed_modules.empty())
                {
                        for (std::vector<std::string>::iterator removing = removed_modules.begin(); removing != removed_modules.end(); removing++)
@@ -1224,10 +1241,15 @@ void ServerConfig::Read(bool bail, User* user)
                }
 
                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->Threads->Mutex(false);
+
        }
 
        /** Note: This is safe, the method checks for user == NULL */
+       ServerInstance->Threads->Mutex(true);
        ServerInstance->Parser->SetupCommandTable(user);
+       ServerInstance->Threads->Mutex(false);
 
        if (user)
                user->WriteServ("NOTICE %s :*** Successfully rehashed server.", user->nick);
@@ -1237,9 +1259,8 @@ void ServerConfig::Read(bool bail, User* user)
 }
 
 
-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;
@@ -1253,6 +1274,8 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const char* filename, std::o
        in_quote = false;
        in_comment = false;
 
+       ServerInstance->Logs->Log("CONFIG", DEBUG, "Reading %s", filename);
+
        /* Check if the file open failed first */
        if (!conf)
        {
@@ -1260,9 +1283,6 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const char* filename, std::o
                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])
@@ -1276,9 +1296,9 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const char* filename, std::o
        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
@@ -1335,8 +1355,9 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const char* filename, std::o
                {
                        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;
@@ -1441,9 +1462,9 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const char* filename, std::o
 }
 
 
-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)
@@ -1548,6 +1569,12 @@ bool ServerConfig::ParseLine(ConfigDataHash &target, std::string &line, long &li
                                                        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();
@@ -1570,6 +1597,22 @@ bool ServerConfig::ParseLine(ConfigDataHash &target, std::string &line, long &li
        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;
@@ -1596,7 +1639,18 @@ bool ServerConfig::DoInclude(ConfigDataHash &target, const std::string &file, st
                }
        }
 
-       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)
@@ -2164,5 +2218,8 @@ void ConfigReaderThread::Run()
 {
        /* 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);
 }