Make sure that include paths are interpreted as relative to the config file that contains the include directive.

This commit is contained in:
Gunnar Beutner 2012-07-08 21:18:35 +02:00
parent 1c1e1ff5e2
commit 7fadf56ded
5 changed files with 99 additions and 32 deletions

View File

@ -270,6 +270,8 @@ string Application::GetExeDirectory(void) const
if (!result.empty())
return result;
string executablePath;
#ifndef _WIN32
string argv0 = m_Arguments[0];
@ -279,9 +281,9 @@ string Application::GetExeDirectory(void) const
string workingDirectory = buffer;
if (argv0[0] != '/')
result = workingDirectory + "/" + argv0;
executablePath = workingDirectory + "/" + argv0;
else
result = argv0;
executablePath = argv0;
if (argv0.find_first_of('/') == string::npos) {
const char *pathEnv = getenv("PATH");
@ -294,37 +296,34 @@ string Application::GetExeDirectory(void) const
string pathTest = *it + "/" + argv0;
if (access(pathTest.c_str(), X_OK) == 0) {
result = pathTest;
executablePath = pathTest;
foundPath = true;
break;
}
}
if (!foundPath) {
result.clear();
executablePath.clear();
throw runtime_error("Could not determine executable path.");
}
}
}
if (realpath(result.c_str(), buffer) == NULL)
if (realpath(executablePath.c_str(), buffer) == NULL)
throw PosixException("realpath failed", errno);
result = buffer;
size_t pos = result.find_last_of('/');
if (pos != string::npos)
result.erase(pos);
executablePath = buffer;
#else /* _WIN32 */
char FullExePath[MAXPATHLEN];
GetModuleFileName(NULL, FullExePath, sizeof(FullExePath));
if (!GetModuleFileName(NULL, FullExePath, sizeof(FullExePath)))
throw Win32Exception("GetModuleFileName() failed", GetLastError());
PathRemoveFileSpec(FullExePath);
result = FullExePath;
executablePath = FullExePath;
#endif /* _WIN32 */
result = Utility::DirName(executablePath);
return result;
}

View File

@ -166,3 +166,58 @@ bool Utility::Match(string pattern, string text)
{
return (match(pattern.c_str(), text.c_str()) == 0);
}
/**
* Returns the directory component of a path. See dirname(3) for details.
*
* @param path The full path.
* @returns The directory.
*/
string Utility::DirName(const string& path)
{
char *dir = strdup(path.c_str());
string result;
if (dir == NULL)
throw std::bad_alloc("strdup() failed");
#ifndef _WIN32
result = dirname(dir);
#else /* _WIN32 */
if (!PathRemoveFileSpec(dir)) {
free(dir);
throw Win32Exception("PathRemoveFileSpec() failed", GetLastError());
}
result = dir;
#endif /* _WIN32 */
free(dir);
return result;
}
/**
* Returns the file component of a path. See basename(3) for details.
*
* @param path The full path.
* @returns The filename.
*/
string Utility::BaseName(const string& path)
{
char *dir = strdup(path.c_str());
string result;
if (dir == NULL)
throw std::bad_alloc("strdup() failed");
#ifndef _WIN32
result = basename(dir);
#else /* _WIN32 */
result = PathFindFileName(dir);
#endif /* _WIN32 */
free(dir);
return result;
}

View File

@ -63,6 +63,9 @@ public:
static bool Match(string pattern, string text);
static string DirName(const string& path);
static string BaseName(const string& path);
private:
static bool m_SSLInitialized;

View File

@ -23,10 +23,9 @@ using std::ifstream;
using namespace icinga;
ConfigCompiler::ConfigCompiler(istream *input, HandleIncludeFunc includeHandler)
ConfigCompiler::ConfigCompiler(const string& path, istream *input, HandleIncludeFunc includeHandler)
: m_Path(path), m_Input(input), m_HandleInclude(includeHandler)
{
m_HandleInclude = includeHandler;
m_Input = input;
InitializeScanner();
}
@ -51,37 +50,43 @@ vector<ConfigItem::Ptr> ConfigCompiler::GetResult(void) const
return m_Result;
}
string ConfigCompiler::GetPath(void) const
{
return m_Path;
}
void ConfigCompiler::HandleInclude(const string& include)
{
vector<ConfigItem::Ptr> items = m_HandleInclude(include);
string path = Utility::DirName(GetPath()) + "/" + include;
vector<ConfigItem::Ptr> items = m_HandleInclude(path);
std::copy(items.begin(), items.end(), back_inserter(m_Result));
}
vector<ConfigItem::Ptr> ConfigCompiler::CompileStream(istream *stream)
vector<ConfigItem::Ptr> ConfigCompiler::CompileStream(const string& path, istream *stream)
{
ConfigCompiler ctx(stream);
ConfigCompiler ctx(path, stream);
ctx.Compile();
return ctx.GetResult();
}
vector<ConfigItem::Ptr> ConfigCompiler::CompileFile(const string& filename)
vector<ConfigItem::Ptr> ConfigCompiler::CompileFile(const string& path)
{
ifstream stream;
stream.exceptions(ifstream::badbit);
stream.open(filename.c_str(), ifstream::in);
stream.open(path.c_str(), ifstream::in);
if (!stream.good())
throw invalid_argument("Could not open config file: " + filename);
throw invalid_argument("Could not open config file: " + path);
Application::Log(LogInformation, "dyn", "Compiling config file: " + filename);
Application::Log(LogInformation, "dyn", "Compiling config file: " + path);
return CompileStream(&stream);
return CompileStream(path, &stream);
}
vector<ConfigItem::Ptr> ConfigCompiler::CompileText(const string& text)
vector<ConfigItem::Ptr> ConfigCompiler::CompileText(const string& path, const string& text)
{
stringstream stream(text);
return CompileStream(&stream);
return CompileStream(path, &stream);
}
vector<ConfigItem::Ptr> ConfigCompiler::HandleFileInclude(const string& include)

View File

@ -28,20 +28,22 @@ class I2_DYN_API ConfigCompiler
public:
typedef function<vector<ConfigItem::Ptr> (const string& include)> HandleIncludeFunc;
ConfigCompiler(istream *input = &cin,
ConfigCompiler(const string& path, istream *input = &cin,
HandleIncludeFunc includeHandler = &ConfigCompiler::HandleFileInclude);
virtual ~ConfigCompiler(void);
void Compile(void);
static vector<ConfigItem::Ptr> CompileStream(istream *stream);
static vector<ConfigItem::Ptr> CompileFile(const string& filename);
static vector<ConfigItem::Ptr> CompileText(const string& text);
static vector<ConfigItem::Ptr> CompileStream(const string& path, istream *stream);
static vector<ConfigItem::Ptr> CompileFile(const string& path);
static vector<ConfigItem::Ptr> CompileText(const string& path, const string& text);
static vector<ConfigItem::Ptr> HandleFileInclude(const string& include);
vector<ConfigItem::Ptr> GetResult(void) const;
string GetPath(void) const;
/* internally used methods */
void HandleInclude(const string& include);
void AddObject(const ConfigItem::Ptr& object);
@ -49,8 +51,11 @@ public:
void *GetScanner(void) const;
private:
HandleIncludeFunc m_HandleInclude;
string m_Path;
istream *m_Input;
HandleIncludeFunc m_HandleInclude;
void *m_Scanner;
vector<ConfigItem::Ptr> m_Result;