From 1f27bd7891a3013af3724e34e6f7a472a66107c9 Mon Sep 17 00:00:00 2001 From: Will Sobel Date: Fri, 22 Sep 2017 11:36:50 -0700 Subject: [PATCH] Added executable path fallback search scheme for configuration file and Devices.xml. Look in the same path as the exe. Issue #49. --- agent/CMakeLists.txt | 4 +- agent/config.cpp | 115 +++++++++++++++++++++++++++++++++++-------- agent/config.hpp | 1 + 3 files changed, 98 insertions(+), 22 deletions(-) diff --git a/agent/CMakeLists.txt b/agent/CMakeLists.txt index 9d3df5c6b..56e45ab48 100644 --- a/agent/CMakeLists.txt +++ b/agent/CMakeLists.txt @@ -9,8 +9,8 @@ set(CMAKE_FIND_APPBUNDLE NEVER) set (AGENT_VERSION_MAJOR 1) set (AGENT_VERSION_MINOR 4) set (AGENT_VERSION_PATCH 0) -set (AGENT_VERSION_BUILD 6) -set (AGENT_VERSION_RC "RC6") +set (AGENT_VERSION_BUILD 7) +set (AGENT_VERSION_RC "RC7") if(WIN32) # For windows XP use: cmake -G "Visual Studio 12" -T v120_xp -D WINVER=0x0501 diff --git a/agent/config.cpp b/agent/config.cpp index 363d48d08..46e00e9fc 100644 --- a/agent/config.cpp +++ b/agent/config.cpp @@ -30,6 +30,10 @@ #include #include "rolling_file_logger.hpp" +#ifdef MACOSX +#include +#endif + using namespace std; using namespace dlib; @@ -69,8 +73,45 @@ static inline bool get_bool_with_default(const config_reader::kernel_1a &reader, AgentConfiguration::AgentConfiguration() : mAgent(NULL), mLoggerFile(NULL), mMonitorFiles(false), - mMinimumConfigReloadAge(15), mRestart(false) + mMinimumConfigReloadAge(15), mRestart(false), mExePath("") { + bool success = false; + char pathSep = '/'; + +#if _WINDOWS + char path[MAX_PATH]; + pathSep = '\\'; + success = GetModuleFileName(NULL, path, MAX_PATH) > 0; +#else +#ifdef __linux__ + char path[PATH_MAX]; + success = readlink("/proc/self/exe", path, PATH_MAX) >= 0; +#else +#ifdef MACOSX + char path[PATH_MAX]; + uint32_t size = PATH_MAX; + success = _NSGetExecutablePath(path, &size) == 0; +#else + char *path = ""; + success = false; +#endif +#endif +#endif + + + if (success) + { + mExePath = path; + size_t found = mExePath.rfind(pathSep); + if (found != std::string::npos) + { + mExePath.erase(found + 1); + } + + cout << "Configuration search path: current directory and " << mExePath; + } else { + mExePath = ""; + } } void AgentConfiguration::initialize(int aArgc, const char *aArgv[]) @@ -87,6 +128,24 @@ void AgentConfiguration::initialize(int aArgc, const char *aArgv[]) try { + struct stat buf; + + // Check first if the file is in the current working directory... + if (stat(mConfigFile.c_str(), &buf) != 0) { + if (!mExePath.empty()) + { + sLogger << LINFO << "Cannot find " << mConfigFile << " in current directory, searching exe path: " << mExePath; + cerr << "Cannot find " << mConfigFile << " in current directory, searching exe path: " << mExePath; + mConfigFile = mExePath + mConfigFile; + } + else + { + sLogger << LFATAL << "Agent failed to load: Cannot find configuration file: '" << mConfigFile; + cerr << "Agent failed to load: Cannot find configuration file: '" << mConfigFile << std::endl; + optionList.usage(); + } + } + ifstream file(mConfigFile.c_str()); loadConfig(file); } @@ -384,28 +443,44 @@ void AgentConfiguration::loadConfig(std::istream &aFile) mMinimumConfigReloadAge = get_with_default(reader, "MinimumConfigReloadAge", 15); mPidFile = get_with_default(reader, "PidFile", "agent.pid"); - const char *probe; - struct stat buf; + std::vector devices_files; if (reader.is_key_defined("Devices")) { - probe = reader["Devices"].c_str(); - if (stat(probe, &buf) != 0) { - throw runtime_error(((string) "Please make sure the Devices XML configuration " - "file " + probe + " is in the current path ").c_str()); - } - } else { - probe = "probe.xml"; - if (stat(probe, &buf) != 0) - probe = "Devices.xml"; - if (stat(probe, &buf) != 0) { - throw runtime_error(((string) "Please make sure the configuration " - "file probe.xml or Devices.xml is in the current " - "directory or specify the correct file " - "in the configuration file " + mConfigFile + - " using Devices = ").c_str()); + string fileName = reader["Devices"]; + devices_files.push_back(fileName); + if (!mExePath.empty() && fileName[0] != '/' && fileName[0] != '\\' && fileName[1] != ':') + devices_files.push_back(mExePath + reader["Devices"]); + } + + devices_files.push_back("Devices.xml"); + if (!mExePath.empty()) + devices_files.push_back(mExePath + "Devices.xml"); + devices_files.push_back("probe.xml"); + if (!mExePath.empty()) + devices_files.push_back(mExePath +"probe.xml"); + + mDevicesFile.clear(); + + for (string probe: devices_files) + { + struct stat buf; + sLogger << LDEBUG << "Checking for Devices XML configuration file: " << probe; + if (stat(probe.c_str(), &buf) == 0) { + mDevicesFile = probe; + break; } + sLogger << LDEBUG << "Could not find file: " << probe; + cout << "Could not locate file: " << probe << endl; + } + + if (mDevicesFile.empty()) + { + throw runtime_error(((string) "Please make sure the configuration " + "file probe.xml or Devices.xml is in the current " + "directory or specify the correct file " + "in the configuration file " + mConfigFile + + " using Devices = ").c_str()); } - mDevicesFile = probe; mName = get_with_default(reader, "ServiceName", "MTConnect Agent"); @@ -416,7 +491,7 @@ void AgentConfiguration::loadConfig(std::istream &aFile) sLogger << LINFO << "Starting agent on port " << port; if (mAgent == NULL) - mAgent = new Agent(probe, bufferSize, maxAssets, checkpointFrequency); + mAgent = new Agent(mDevicesFile, bufferSize, maxAssets, checkpointFrequency); mAgent->set_listening_port(port); mAgent->set_listening_ip(serverIp); mAgent->setLogStreamData(get_bool_with_default(reader, "LogStreams", false)); diff --git a/agent/config.hpp b/agent/config.hpp index 38ad213c8..761c969c5 100644 --- a/agent/config.hpp +++ b/agent/config.hpp @@ -58,6 +58,7 @@ class AgentConfiguration : public MTConnectService { int mMinimumConfigReloadAge; std::string mDevicesFile; bool mRestart; + std::string mExePath; }; #endif