const ArgvMap::param_t::const_iterator ArgvMap::begin()
{
- return params.begin();
+ return d_params.begin();
}
const ArgvMap::param_t::const_iterator ArgvMap::end()
{
- return params.end();
+ return d_params.end();
}
string & ArgvMap::set(const string &var)
{
- return params[var];
+ return d_params[var];
}
void ArgvMap::setDefault(const string &var, const string &value)
void ArgvMap::setDefaults()
{
- for(map<string,string>::const_iterator i=params.begin();i!=params.end();++i)
- if(! defaultmap.count(i->first))
- defaultmap.insert(*i);
+ for (const auto& i: d_params)
+ if(! defaultmap.count(i.first))
+ defaultmap.insert(i);
}
bool ArgvMap::mustDo(const string &var)
vector<string>ArgvMap::list()
{
vector<string> ret;
- for(map<string,string>::const_iterator i=params.begin();i!=params.end();++i)
- ret.push_back(i->first);
+ for (const auto& i: d_params)
+ ret.push_back(i.first);
return ret;
}
bool ArgvMap::contains(const string &var, const string &val)
{
- params_t::const_iterator param = params.find(var);
- if(param == params.end() || param->second.empty()) {
+ const auto& param = d_params.find(var);
+ if(param == d_params.end() || param->second.empty()) {
return false;
}
vector<string> parts;
- stringtok( parts, param->second, ", \t" );
+ stringtok(parts, param->second, ", \t");
for (const auto& part: parts) {
if (part == val) {
return true;
return help;
}
+const string ArgvMap::formatOne(bool running, bool full, const string &var, const string &help, const string& theDefault, const string& current)
+{
+ string out;
+
+ if (!running || full) {
+ out += "#################################\n";
+ out += "# ";
+ out += var;
+ out += "\t";
+ out += help;
+ out += "\n#\n";
+ } else {
+ if (theDefault == current) {
+ return "";
+ }
+ }
+
+ if (! running || theDefault == current) {
+ out += "# ";
+ }
+
+ if (running) {
+ out += var + "=" + current + "\n";
+ if (full) {
+ out += "\n";
+ }
+ } else {
+ out += var + "=" + theDefault + "\n\n";
+ }
+
+ return out;
+}
+
+// If running and full, only changed settings are returned.
string ArgvMap::configstring(bool running, bool full)
{
string help;
else
help="# Autogenerated configuration file template\n\n";
+ // Affects parsing, should come first.
+ help += formatOne(running, full, "ignore-unknown-settings", helpmap["ignore-unknown-settings"], defaultmap["ignore-unknown-settings"], d_params["ignore-unknown-settings"]);
+
for(const auto& i: helpmap) {
- if(d_typeMap[i.first]=="Command")
+ if (d_typeMap[i.first] == "Command")
+ continue;
+ if (i.first == "ignore-unknown-settings")
continue;
- if (! defaultmap.count(i.first)) {
- throw ArgException(string("Default for parameter '")+i.first+"' not set");
+ if (!defaultmap.count(i.first)) {
+ throw ArgException(string("Default for setting '")+i.first+"' not set");
}
- if (!running || full) {
- help+="#################################\n";
- help+="# ";
- help+=i.first;
- help+="\t";
- help+=i.second;
- help+="\n#\n";
- } else {
- if (defaultmap[i.first] == params[i.first]) {
- continue;
- }
- }
-
- if (! running || defaultmap[i.first] == params[i.first]) {
- help+="# ";
- }
+ help += formatOne(running, full, i.first, i.second, defaultmap[i.first], d_params[i.first]);
+ }
- if (running) {
- help+=i.first+"="+params[i.first]+"\n";
- if (full) {
- help+="\n";
- }
- } else {
- help+=i.first+"="+defaultmap[i.first]+"\n\n";
+ if (running) {
+ for(const auto& i: d_unknownParams) {
+ help += formatOne(running, full, i.first, "unknown setting", "", i.second);
}
}
+
return help;
}
if(!parmIsset(arg))
throw ArgException(string("Undefined but needed argument: '")+arg+"'");
- return params[arg];
+ return d_params[arg];
}
mode_t ArgvMap::asMode(const string &arg)
if(!parmIsset(arg))
throw ArgException(string("Undefined but needed argument: '")+arg+"'");
- cptr_orig = params[arg].c_str();
+ cptr_orig = d_params[arg].c_str();
mode = static_cast<mode_t>(strtol(cptr_orig, &cptr_ret, 8));
if (mode == 0 && cptr_ret == cptr_orig)
throw ArgException("'" + arg + string("' contains invalid octal mode"));
if(!parmIsset(arg))
throw ArgException(string("Undefined but needed argument: '")+arg+"'");
- cptr_orig = params[arg].c_str();
+ cptr_orig = d_params[arg].c_str();
gid = static_cast<gid_t>(strtol(cptr_orig, &cptr_ret, 0));
if (gid == 0 && cptr_ret == cptr_orig) {
// try to resolve
- struct group *group = getgrnam(params[arg].c_str());
+ struct group *group = getgrnam(d_params[arg].c_str());
if (group == nullptr)
throw ArgException("'" + arg + string("' contains invalid group"));
gid = group->gr_gid;
if(!parmIsset(arg))
throw ArgException(string("Undefined but needed argument: '")+arg+"'");
- cptr_orig = params[arg].c_str();
+ cptr_orig = d_params[arg].c_str();
uid = static_cast<uid_t>(strtol(cptr_orig, &cptr_ret, 0));
if (uid == 0 && cptr_ret == cptr_orig) {
// try to resolve
- struct passwd *pwent = getpwnam(params[arg].c_str());
+ struct passwd *pwent = getpwnam(d_params[arg].c_str());
if (pwent == nullptr)
throw ArgException("'" + arg + string("' contains invalid group"));
uid = pwent->pw_uid;
throw ArgException(string("Undefined but needed argument: '")+arg+"'");
// use default for empty values
- if (params[arg].empty())
+ if (d_params[arg].empty())
return def;
- cptr_orig = params[arg].c_str();
+ cptr_orig = d_params[arg].c_str();
retval = static_cast<int>(strtol(cptr_orig, &cptr_ret, 0));
if (!retval && cptr_ret == cptr_orig)
throw ArgException("'"+arg+"' value '"+string(cptr_orig) + string( "' is not a valid number"));
{
if(!parmIsset(arg))
return true;
- return params[arg].empty();
+ return d_params[arg].empty();
}
double ArgvMap::asDouble(const string &arg)
if(!parmIsset(arg))
throw ArgException(string("Undefined but needed argument: '")+arg+"'");
- if (params[arg].empty())
+ if (d_params[arg].empty())
return 0.0;
- cptr_orig = params[arg].c_str();
+ cptr_orig = d_params[arg].c_str();
retval = strtod(cptr_orig, &cptr_ret);
if (retval == 0 && cptr_ret == cptr_orig)
ArgvMap::ArgvMap()
{
-
+ set("ignore-unknown-settings","Configuration settings to ignore if they are unknown")="";
}
bool ArgvMap::parmIsset(const string &var)
{
- return (params.find(var)!=params.end());
+ return d_params.find(var) != d_params.end();
}
void ArgvMap::parseOne(const string &arg, const string &parseOnly, bool lax)
{
if(incremental)
{
- if(params[var].empty())
+ if(d_params[var].empty())
{
if(!d_cleared.count(var))
- throw ArgException("Incremental parameter '"+var+"' without a parent");
- params[var]=val;
+ throw ArgException("Incremental setting '"+var+"' without a parent");
+ d_params[var] = val;
}
else
- params[var]+=", " + val;
+ d_params[var] += ", " + val;
}
else
{
- params[var]=val;
+ d_params[var] = val;
d_cleared.insert(var);
}
}
- else if(!lax)
- throw ArgException("Trying to set unknown parameter '"+var+"'");
+ else
+ {
+ // unknown setting encountered. see if its on the ignore list before throwing.
+ std::set<string> parts;
+ stringtok(parts, d_params["ignore-unknown-settings"], " ,\t\n\r");
+ if (parts.find(var) != parts.end()) {
+ d_unknownParams[var] = val;
+ g_log<<Logger::Warning<<"Ignoring unknown setting '"<<var<<"' as requested"<<endl;
+ return;
+ }
+
+ if (!lax) {
+ throw ArgException("Trying to set unknown setting '"+var+"'");
+ }
+ }
}
}
bool ArgvMap::preParseFile(const char *fname, const string &arg, const string& theDefault)
{
- params[arg]=theDefault;
+ d_params[arg] = theDefault;
return parseFile(fname, arg, false);
}
}
// handle include here (avoid re-include)
- if (!included && !params["include-dir"].empty()) {
+ if (!included && !d_params["include-dir"].empty()) {
std::vector<std::string> extraConfigs;
gatherIncludes(extraConfigs);
for(const std::string& fn : extraConfigs) {
void ArgvMap::gatherIncludes(std::vector<std::string> &extraConfigs) {
extraConfigs.clear();
- if (params["include-dir"].empty())
+ if (d_params["include-dir"].empty())
return; // nothing to do
DIR *dir;
- if (!(dir = opendir(params["include-dir"].c_str()))) {
+ if (!(dir = opendir(d_params["include-dir"].c_str()))) {
int err = errno;
- string msg = params["include-dir"] + " is not accessible: " + strerror(err);
+ string msg = d_params["include-dir"] + " is not accessible: " + strerror(err);
g_log << Logger::Error << msg << std::endl;
throw ArgException(msg);
}
continue; // skip any dots
if (boost::ends_with(ent->d_name, ".conf")) {
// build name
- string name = params["include-dir"] + "/" + ent->d_name; // FIXME: Use some path separator
+ string name = d_params["include-dir"] + "/" + ent->d_name; // FIXME: Use some path separator
// ensure it's readable file
struct stat st;
if (stat(name.c_str(), &st) || !S_ISREG(st.st_mode)) {
};
void parseService(const string &descr, ServiceTuple &st);
-template <typename Container>
+template<typename Container, class Enable = void>
void
stringtok (Container &container, string const &in,
- const char * const delimiters = " \t\n")
+ const char * const delimiters = " \t\n");
+
+template<typename Container,
+ typename std::enable_if<std::is_function<typename Container::push_back>::value>::type = true>
+void
+stringtok (Container &container, string const &in,
+ const char * const delimiters)
{
const string::size_type len = in.length();
string::size_type i = 0;
}
}
+template<typename Container,
+ typename std::enable_if<std::is_function<typename Container::insert>::value>::type = true>
+void
+stringtok (Container &container, string const &in,
+ const char * const delimiters)
+{
+ const string::size_type len = in.length();
+ string::size_type i = 0;
+
+ while (i<len) {
+ // eat leading whitespace
+ i = in.find_first_not_of (delimiters, i);
+ if (i == string::npos)
+ return; // nothing left but white space
+
+ // find the end of the token
+ string::size_type j = in.find_first_of (delimiters, i);
+
+ // push token
+ if (j == string::npos) {
+ container.insert (in.substr(i));
+ return;
+ } else
+ container.insert (in.substr(i, j-i));
+
+ // set up for next loop
+ i = j + 1;
+ }
+}
+
template<typename T> bool rfc1982LessThan(T a, T b)
{
static_assert(std::is_unsigned<T>::value, "rfc1982LessThan only works for unsigned types");