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:
parent
59067e6edf
commit
609a5371a0
|
@ -22,8 +22,23 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MAX_DEPTH 3
|
||||||
|
|
||||||
using namespace TelEngine;
|
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()
|
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)
|
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);
|
ObjList *l = makeSectHolder(sect);
|
||||||
if (!l)
|
if (!l)
|
||||||
return;
|
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)
|
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);
|
ObjList *l = makeSectHolder(sect);
|
||||||
if (!l)
|
if (!l)
|
||||||
return;
|
return;
|
||||||
|
@ -170,10 +185,23 @@ bool Configuration::load(bool warn)
|
||||||
m_sections.clear();
|
m_sections.clear();
|
||||||
if (null())
|
if (null())
|
||||||
return false;
|
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) {
|
if (f) {
|
||||||
String sect;
|
bool ok = true;
|
||||||
bool start = true;
|
bool start = true;
|
||||||
|
bool enabled = true;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
if (!::fgets(buf,sizeof(buf),f))
|
if (!::fgets(buf,sizeof(buf),f))
|
||||||
|
@ -202,11 +230,62 @@ bool Configuration::load(bool warn)
|
||||||
if (s[0] == '[') {
|
if (s[0] == '[') {
|
||||||
int r = s.find(']');
|
int r = s.find(']');
|
||||||
if (r > 0) {
|
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);
|
createSection(sect);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!enabled)
|
||||||
|
continue;
|
||||||
int q = s.find('=');
|
int q = s.find('=');
|
||||||
if (q == 0)
|
if (q == 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -235,12 +314,16 @@ bool Configuration::load(bool warn)
|
||||||
addValue(sect,key,s.trimBlanks());
|
addValue(sect,key,s.trimBlanks());
|
||||||
}
|
}
|
||||||
::fclose(f);
|
::fclose(f);
|
||||||
return true;
|
return ok;
|
||||||
}
|
}
|
||||||
if (warn) {
|
if (warn) {
|
||||||
int err = errno;
|
int err = errno;
|
||||||
Debug(DebugNote,"Failed to open config file '%s', using defaults (%d: %s)",
|
if (depth)
|
||||||
c_str(),err,strerror(err));
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,6 +228,7 @@ public:
|
||||||
private:
|
private:
|
||||||
ObjList *getSectHolder(const String& sect) const;
|
ObjList *getSectHolder(const String& sect) const;
|
||||||
ObjList *makeSectHolder(const String& sect);
|
ObjList *makeSectHolder(const String& sect);
|
||||||
|
bool loadFile(const char* file, String& sect, unsigned int depth, bool warn);
|
||||||
ObjList m_sections;
|
ObjList m_sections;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue