-/* +------------------------------------+
- * | Inspire Internet Relay Chat Daemon |
- * +------------------------------------+
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
*
- * InspIRCd: (C) 2002-2010 InspIRCd Development Team
- * See: http://wiki.inspircd.org/Credits
+ * Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
*
- * This program is free but copyrighted software; see
- * the file COPYING for details.
+ * This file is part of InspIRCd. InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
*
- * ---------------------------------------------------
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#include "inspircd.h"
#include <fstream>
#include "configparser.h"
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)
while (kv(items, seen));
+ if (name == mandatory_tag)
+ {
+ // Found the mandatory tag
+ mandatory_tag.clear();
+ }
+
if (name == "include")
{
stack.DoInclude(tag, flags);
{
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();
{
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))
{
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))
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");
}
}
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");
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++)
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++)
/* 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)
}
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)
{
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;
}