From 7fadf56deddff540dd5aaa7b769a8f34b21e9348 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sun, 8 Jul 2012 21:18:35 +0200 Subject: [PATCH] Make sure that include paths are interpreted as relative to the config file that contains the include directive. --- base/application.cpp | 27 ++++++++++----------- base/utility.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++ base/utility.h | 3 +++ dyn/configcompiler.cpp | 31 ++++++++++++++---------- dyn/configcompiler.h | 15 ++++++++---- 5 files changed, 99 insertions(+), 32 deletions(-) diff --git a/base/application.cpp b/base/application.cpp index 80470aa94..3f0d4e46a 100644 --- a/base/application.cpp +++ b/base/application.cpp @@ -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; } diff --git a/base/utility.cpp b/base/utility.cpp index e4ce045c1..01f76a08e 100644 --- a/base/utility.cpp +++ b/base/utility.cpp @@ -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; +} diff --git a/base/utility.h b/base/utility.h index 13702cd8d..bf9b08233 100644 --- a/base/utility.h +++ b/base/utility.h @@ -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; diff --git a/dyn/configcompiler.cpp b/dyn/configcompiler.cpp index e94de6301..4c5d94932 100644 --- a/dyn/configcompiler.cpp +++ b/dyn/configcompiler.cpp @@ -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 ConfigCompiler::GetResult(void) const return m_Result; } +string ConfigCompiler::GetPath(void) const +{ + return m_Path; +} + void ConfigCompiler::HandleInclude(const string& include) { - vector items = m_HandleInclude(include); + string path = Utility::DirName(GetPath()) + "/" + include; + vector items = m_HandleInclude(path); std::copy(items.begin(), items.end(), back_inserter(m_Result)); } -vector ConfigCompiler::CompileStream(istream *stream) +vector ConfigCompiler::CompileStream(const string& path, istream *stream) { - ConfigCompiler ctx(stream); + ConfigCompiler ctx(path, stream); ctx.Compile(); return ctx.GetResult(); } -vector ConfigCompiler::CompileFile(const string& filename) +vector 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 ConfigCompiler::CompileText(const string& text) +vector ConfigCompiler::CompileText(const string& path, const string& text) { stringstream stream(text); - return CompileStream(&stream); + return CompileStream(path, &stream); } vector ConfigCompiler::HandleFileInclude(const string& include) diff --git a/dyn/configcompiler.h b/dyn/configcompiler.h index 77ce90eec..f1e167ce5 100644 --- a/dyn/configcompiler.h +++ b/dyn/configcompiler.h @@ -28,20 +28,22 @@ class I2_DYN_API ConfigCompiler public: typedef function (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 CompileStream(istream *stream); - static vector CompileFile(const string& filename); - static vector CompileText(const string& text); + static vector CompileStream(const string& path, istream *stream); + static vector CompileFile(const string& path); + static vector CompileText(const string& path, const string& text); static vector HandleFileInclude(const string& include); vector 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 m_Result;