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

View File

@ -166,3 +166,58 @@ bool Utility::Match(string pattern, string text)
{ {
return (match(pattern.c_str(), text.c_str()) == 0); 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 bool Match(string pattern, string text);
static string DirName(const string& path);
static string BaseName(const string& path);
private: private:
static bool m_SSLInitialized; static bool m_SSLInitialized;

View File

@ -23,10 +23,9 @@ using std::ifstream;
using namespace icinga; 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(); InitializeScanner();
} }
@ -51,37 +50,43 @@ vector<ConfigItem::Ptr> ConfigCompiler::GetResult(void) const
return m_Result; return m_Result;
} }
string ConfigCompiler::GetPath(void) const
{
return m_Path;
}
void ConfigCompiler::HandleInclude(const string& include) 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)); 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(); ctx.Compile();
return ctx.GetResult(); return ctx.GetResult();
} }
vector<ConfigItem::Ptr> ConfigCompiler::CompileFile(const string& filename) vector<ConfigItem::Ptr> ConfigCompiler::CompileFile(const string& path)
{ {
ifstream stream; ifstream stream;
stream.exceptions(ifstream::badbit); stream.exceptions(ifstream::badbit);
stream.open(filename.c_str(), ifstream::in); stream.open(path.c_str(), ifstream::in);
if (!stream.good()) 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); stringstream stream(text);
return CompileStream(&stream); return CompileStream(path, &stream);
} }
vector<ConfigItem::Ptr> ConfigCompiler::HandleFileInclude(const string& include) vector<ConfigItem::Ptr> ConfigCompiler::HandleFileInclude(const string& include)

View File

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