Added support for including other files or directories in configuration files.

Added support for disabling portions of a configuration file.


git-svn-id: http://voip.null.ro/svn/yate@6178 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2017-02-01 13:11:05 +00:00
parent 59067e6edf
commit 609a5371a0
2 changed files with 92 additions and 8 deletions

View File

@ -22,8 +22,23 @@
#include <stdio.h>
#include <string.h>
#define MAX_DEPTH 3
using namespace TelEngine;
// Text sort callback
static int textSort(GenObject* obj1, GenObject* obj2, void* context)
{
const String* s1 = static_cast<const String*>(obj1);
const String* s2 = static_cast<const String*>(obj2);
if (TelEngine::null(s1))
return TelEngine::null(s2) ? 0 : -1;
if (TelEngine::null(s2))
return 1;
return ::strcmp(s1->c_str(),s2->c_str());
}
Configuration::Configuration()
{
}
@ -133,7 +148,7 @@ void Configuration::clearKey(const String& sect, const String& key)
void Configuration::addValue(const String& sect, const char* key, const char* value)
{
DDebug(DebugInfo,"Configuration::addValue(\"%s\",\"%s\",\"%s\")",sect.c_str(),key,value);
DDebug(DebugAll,"Configuration::addValue(\"%s\",\"%s\",\"%s\")",sect.c_str(),key,value);
ObjList *l = makeSectHolder(sect);
if (!l)
return;
@ -144,7 +159,7 @@ void Configuration::addValue(const String& sect, const char* key, const char* va
void Configuration::setValue(const String& sect, const char* key, const char* value)
{
DDebug(DebugInfo,"Configuration::setValue(\"%s\",\"%s\",\"%s\")",sect.c_str(),key,value);
DDebug(DebugAll,"Configuration::setValue(\"%s\",\"%s\",\"%s\")",sect.c_str(),key,value);
ObjList *l = makeSectHolder(sect);
if (!l)
return;
@ -170,10 +185,23 @@ bool Configuration::load(bool warn)
m_sections.clear();
if (null())
return false;
FILE *f = ::fopen(c_str(),"r");
String sect;
return loadFile(c_str(),sect,0,warn);
}
bool Configuration::loadFile(const char* file, String& sect, unsigned int depth, bool warn)
{
DDebug(DebugInfo,"Configuration::loadFile(\"%s\",\"%s\",%u,%s)",
file,sect.c_str(),depth,String::boolText(warn));
if (depth > MAX_DEPTH) {
Debug(DebugWarn,"Refusing to open config file '%s' at include depth %u",file,depth);
return false;
}
FILE *f = ::fopen(file,"r");
if (f) {
String sect;
bool ok = true;
bool start = true;
bool enabled = true;
for (;;) {
char buf[1024];
if (!::fgets(buf,sizeof(buf),f))
@ -202,11 +230,62 @@ bool Configuration::load(bool warn)
if (s[0] == '[') {
int r = s.find(']');
if (r > 0) {
sect = s.substr(1,r-1);
s = s.substr(1,r-1);
s.trimBlanks();
if (s.null())
continue;
if (s.startSkip("$enabled")) {
enabled = s.toBoolean(true);
continue;
}
if (!enabled)
continue;
bool noerr = false;
if (s.startSkip("$require") || (noerr = s.startSkip("$include"))) {
String path;
if (!s.startsWith(Engine::pathSeparator())) {
path = file;
int sep = path.rfind(Engine::pathSeparator());
if ('/' != *Engine::pathSeparator()) {
int s2 = path.rfind('/');
if (sep < s2)
sep = s2;
}
switch (sep) {
case -1:
path.clear();
break;
case 0:
path = Engine::pathSeparator();
break;
default:
path = path.substr(0,sep);
path << Engine::pathSeparator();
}
}
path << s;
ObjList files;
if (File::listDirectory(path,0,&files)) {
path << Engine::pathSeparator();
DDebug(DebugInfo,"Configuration loading %u files from '%s'",
files.count(),path.c_str());
files.sort(textSort);
while (String* it = static_cast<String*>(files.remove(false))) {
ok = (loadFile(path + *it,sect,depth+1,warn) || noerr) && ok;
TelEngine::destruct(it);
}
}
else
ok = (loadFile(path,sect,depth+1,warn) || noerr) && ok;
continue;
}
sect = s;
createSection(sect);
}
continue;
}
if (!enabled)
continue;
int q = s.find('=');
if (q == 0)
continue;
@ -235,12 +314,16 @@ bool Configuration::load(bool warn)
addValue(sect,key,s.trimBlanks());
}
::fclose(f);
return true;
return ok;
}
if (warn) {
int err = errno;
Debug(DebugNote,"Failed to open config file '%s', using defaults (%d: %s)",
c_str(),err,strerror(err));
if (depth)
Debug(DebugNote,"Failed to open included config file '%s' (%d: %s)",
file,err,strerror(err));
else
Debug(DebugNote,"Failed to open config file '%s', using defaults (%d: %s)",
file,err,strerror(err));
}
return false;
}

View File

@ -228,6 +228,7 @@ public:
private:
ObjList *getSectHolder(const String& sect) const;
ObjList *makeSectHolder(const String& sect);
bool loadFile(const char* file, String& sect, unsigned int depth, bool warn);
ObjList m_sections;
};