]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/configparser.cpp
Merge pull request #1162 from SaberUK/insp20+fix-deinstall
[user/henk/code/inspircd.git] / src / configparser.cpp
index 056ed54a4b3e5fb019d88122f1359c4fee06e448..409ebdd395e67fe38de058edd0e823e73d28d3f2 100644 (file)
@@ -30,9 +30,10 @@ struct Parser
        fpos last_tag;
        reference<ConfigTag> tag;
        int ungot;
+       std::string mandatory_tag;
 
-       Parser(ParseStack& me, int myflags, FILE* conf, const std::string& name)
-               : stack(me), flags(myflags), file(conf), current(name), last_tag(name), ungot(-1)
+       Parser(ParseStack& me, int myflags, FILE* conf, const std::string& name, const std::string& mandatorytag)
+               : stack(me), flags(myflags), file(conf), current(name), last_tag(name), ungot(-1), mandatory_tag(mandatorytag)
        { }
 
        int next(bool eof_ok = false)
@@ -184,6 +185,12 @@ struct Parser
 
                while (kv(items, seen));
 
+               if (name == mandatory_tag)
+               {
+                       // Found the mandatory tag
+                       mandatory_tag.clear();
+               }
+
                if (name == "include")
                {
                        stack.DoInclude(tag, flags);
@@ -241,6 +248,8 @@ struct Parser
                                {
                                        case EOF:
                                                // this is the one place where an EOF is not an error
+                                               if (!mandatory_tag.empty())
+                                                       throw CoreException("Mandatory tag \"" + mandatory_tag + "\" not found");
                                                return true;
                                        case '#':
                                                comment();
@@ -277,6 +286,10 @@ void ParseStack::DoInclude(ConfigTag* tag, int flags)
 {
        if (flags & FLAG_NO_INC)
                throw CoreException("Invalid <include> tag in file included with noinclude=\"yes\"");
+
+       std::string mandatorytag;
+       tag->readString("mandatorytag", mandatorytag);
+
        std::string name;
        if (tag->readString("file", name))
        {
@@ -284,7 +297,7 @@ void ParseStack::DoInclude(ConfigTag* tag, int flags)
                        flags |= FLAG_NO_INC;
                if (tag->getBool("noexec", false))
                        flags |= FLAG_NO_EXEC;
-               if (!ParseFile(name, flags))
+               if (!ParseFile(name, flags, mandatorytag))
                        throw CoreException("Included");
        }
        else if (tag->readString("executable", name))
@@ -295,7 +308,7 @@ void ParseStack::DoInclude(ConfigTag* tag, int flags)
                        flags |= FLAG_NO_INC;
                if (tag->getBool("noexec", true))
                        flags |= FLAG_NO_EXEC;
-               if (!ParseExec(name, flags))
+               if (!ParseExec(name, flags, mandatorytag))
                        throw CoreException("Included");
        }
 }
@@ -307,7 +320,7 @@ void ParseStack::DoReadFile(const std::string& key, const std::string& name, int
        if (exec && (flags & FLAG_NO_EXEC))
                throw CoreException("Invalid <execfiles> tag in file included with noexec=\"yes\"");
 
-       FileWrapper file(exec ? popen(name.c_str(), "r") : fopen(name.c_str(), "r"));
+       FileWrapper file(exec ? popen(name.c_str(), "r") : fopen(name.c_str(), "r"), exec);
        if (!file)
                throw CoreException("Could not read \"" + name + "\" for \"" + key + "\" file");
 
@@ -317,13 +330,17 @@ void ParseStack::DoReadFile(const std::string& key, const std::string& name, int
        char linebuf[MAXBUF*10];
        while (fgets(linebuf, sizeof(linebuf), file))
        {
-               int len = strlen(linebuf);
+               size_t len = strlen(linebuf);
                if (len)
-                       cache.push_back(std::string(linebuf, len - 1));
+               {
+                       if (linebuf[len-1] == '\n')
+                               len--;
+                       cache.push_back(std::string(linebuf, len));
+               }
        }
 }
 
-bool ParseStack::ParseFile(const std::string& name, int flags)
+bool ParseStack::ParseFile(const std::string& name, int flags, const std::string& mandatory_tag)
 {
        ServerInstance->Logs->Log("CONFIG", DEBUG, "Reading file %s", name.c_str());
        for (unsigned int t = 0; t < reading.size(); t++)
@@ -341,13 +358,13 @@ bool ParseStack::ParseFile(const std::string& name, int flags)
                throw CoreException("Could not read \"" + name + "\" for include");
 
        reading.push_back(name);
-       Parser p(*this, flags, file, name);
+       Parser p(*this, flags, file, name, mandatory_tag);
        bool ok = p.outer_parse();
        reading.pop_back();
        return ok;
 }
 
-bool ParseStack::ParseExec(const std::string& name, int flags)
+bool ParseStack::ParseExec(const std::string& name, int flags, const std::string& mandatory_tag)
 {
        ServerInstance->Logs->Log("CONFIG", DEBUG, "Reading executable %s", name.c_str());
        for (unsigned int t = 0; t < reading.size(); t++)
@@ -360,19 +377,29 @@ bool ParseStack::ParseExec(const std::string& name, int flags)
 
        /* It's not already included, add it to the list of files we've loaded */
 
-       FileWrapper file(popen(name.c_str(), "r"));
+       FileWrapper file(popen(name.c_str(), "r"), true);
        if (!file)
                throw CoreException("Could not open executable \"" + name + "\" for include");
 
        reading.push_back(name);
-       Parser p(*this, flags, file, name);
+       Parser p(*this, flags, file, name, mandatory_tag);
        bool ok = p.outer_parse();
        reading.pop_back();
        return ok;
 }
 
+#ifdef __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wunknown-pragmas"
+# pragma clang diagnostic ignored "-Wundefined-bool-conversion"
+#elif defined __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wpragmas"
+# pragma GCC diagnostic ignored "-Wnonnull-compare"
+#endif
 bool ConfigTag::readString(const std::string& key, std::string& value, bool allow_lf)
 {
+       // TODO: this is undefined behaviour but changing the API is too risky for 2.0.
        if (!this)
                return false;
        for(std::vector<KeyVal>::iterator j = items.begin(); j != items.end(); ++j)
@@ -392,6 +419,11 @@ bool ConfigTag::readString(const std::string& key, std::string& value, bool allo
        }
        return false;
 }
+#ifdef __clang__
+# pragma clang diagnostic pop
+#elif defined __GNUC__
+# pragma GCC diagnostic pop
+#endif
 
 std::string ConfigTag::getString(const std::string& key, const std::string& def)
 {
@@ -455,10 +487,10 @@ std::string ConfigTag::getTagLocation()
        return src_name + ":" + ConvToStr(src_line);
 }
 
-ConfigTag* ConfigTag::create(const std::string& Tag, const std::string& file, int line, std::vector<KeyVal>*&items)
+ConfigTag* ConfigTag::create(const std::string& Tag, const std::string& file, int line, std::vector<KeyVal>*& Items)
 {
        ConfigTag* rv = new ConfigTag(Tag, file, line);
-       items = &rv->items;
+       Items = &rv->items;
        return rv;
 }