From 8701e0f402b79dcd39a1e2ab02f91dbf4efcb460 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Mon, 17 Jan 2022 20:06:00 +0100 Subject: [PATCH] sys: Log to a file when ImHex wasn't opened though a terminal --- .idea/vcs.xml | 7 +++ lib/libimhex/CMakeLists.txt | 1 + lib/libimhex/include/hex/helpers/file.hpp | 7 ++- lib/libimhex/include/hex/helpers/logger.hpp | 48 ++++++++++++++------- lib/libimhex/include/hex/helpers/paths.hpp | 3 +- lib/libimhex/source/helpers/file.cpp | 14 +++++- lib/libimhex/source/helpers/logger.cpp | 33 ++++++++++++++ lib/libimhex/source/helpers/paths.cpp | 12 ++++++ main/include/helpers/plugin_manager.hpp | 6 ++- main/source/helpers/plugin_manager.cpp | 18 ++++++-- main/source/init/splash_window.cpp | 3 +- main/source/init/tasks.cpp | 8 ++-- main/source/window/linux_window.cpp | 7 ++- main/source/window/macos_window.cpp | 7 ++- main/source/window/win_window.cpp | 23 +++++----- 15 files changed, 155 insertions(+), 42 deletions(-) create mode 100644 lib/libimhex/source/helpers/logger.cpp diff --git a/.idea/vcs.xml b/.idea/vcs.xml index f987939bb..4ff7122dd 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -9,5 +9,12 @@ + + + + + + + \ No newline at end of file diff --git a/lib/libimhex/CMakeLists.txt b/lib/libimhex/CMakeLists.txt index d6cfc8abe..c23cd3620 100644 --- a/lib/libimhex/CMakeLists.txt +++ b/lib/libimhex/CMakeLists.txt @@ -123,6 +123,7 @@ set(LIBIMHEX_SOURCES source/helpers/project_file_handler.cpp source/helpers/encoding_file.cpp source/helpers/loader_script_handler.cpp + source/helpers/logger.cpp source/pattern_language/pattern_language.cpp source/pattern_language/preprocessor.cpp diff --git a/lib/libimhex/include/hex/helpers/file.hpp b/lib/libimhex/include/hex/helpers/file.hpp index 122664324..33834f298 100644 --- a/lib/libimhex/include/hex/helpers/file.hpp +++ b/lib/libimhex/include/hex/helpers/file.hpp @@ -26,13 +26,16 @@ namespace hex { Create }; - explicit File(const fs::path &path, Mode mode); - File(); + explicit File(const fs::path &path, Mode mode) noexcept; + File() noexcept; File(const File&) = delete; File(File &&other) noexcept; ~File(); + File& operator=(File &&other) noexcept; + + [[nodiscard]] bool isValid() const { return this->m_file != nullptr; } void seek(u64 offset); diff --git a/lib/libimhex/include/hex/helpers/logger.hpp b/lib/libimhex/include/hex/helpers/logger.hpp index 5fa9b231b..01b568e42 100644 --- a/lib/libimhex/include/hex/helpers/logger.hpp +++ b/lib/libimhex/include/hex/helpers/logger.hpp @@ -5,36 +5,54 @@ namespace hex::log { + FILE *getDestination(); + bool isRedirected(); + + template + void print(fmt::format_string fmt, T&&... args) { + fmt::print(getDestination(), fmt, args...); + } + + template + void print(const fmt::text_style& ts, const S& fmt, const Args&... args) { + if (isRedirected()) + fmt::print(getDestination(), fmt::runtime(fmt), args...); + else + fmt::print(getDestination(), ts, fmt, args...); + } + void debug(const std::string &fmt, auto ... args) { #if defined(DEBUG) - fmt::print(fg(fmt::color::green_yellow) | fmt::emphasis::bold, "[DEBUG] "); - fmt::print(fmt::runtime(fmt), args...); - fmt::print("\n"); + log::print(fg(fmt::color::green_yellow) | fmt::emphasis::bold, "[DEBUG] "); + log::print(fmt::runtime(fmt), args...); + log::print("\n"); #endif } void info(const std::string &fmt, auto ... args) { - fmt::print(fg(fmt::color::cadet_blue) | fmt::emphasis::bold, "[INFO] "); - fmt::print(fmt::runtime(fmt), args...); - fmt::print("\n"); + log::print(fg(fmt::color::cadet_blue) | fmt::emphasis::bold, "[INFO] "); + log::print(fmt::runtime(fmt), args...); + log::print("\n"); } void warn(const std::string &fmt, auto ... args) { - fmt::print(fg(fmt::color::orange) | fmt::emphasis::bold, "[WARN] "); - fmt::print(fmt::runtime(fmt), args...); - fmt::print("\n"); + log::print(fg(fmt::color::orange) | fmt::emphasis::bold, "[WARN] "); + log::print(fmt::runtime(fmt), args...); + log::print("\n"); } void error(const std::string &fmt, auto ... args) { - fmt::print(fg(fmt::color::red) | fmt::emphasis::bold, "[ERROR] "); - fmt::print(fmt::runtime(fmt), args...); - fmt::print("\n"); + log::print(fg(fmt::color::red) | fmt::emphasis::bold, "[ERROR] "); + log::print(fmt::runtime(fmt), args...); + log::print("\n"); } void fatal(const std::string &fmt, auto ... args) { - fmt::print(fg(fmt::color::purple) | fmt::emphasis::bold, "[FATAL] "); - fmt::print(fmt::runtime(fmt), args...); - fmt::print("\n"); + log::print(fg(fmt::color::purple) | fmt::emphasis::bold, "[FATAL] "); + log::print(fmt::runtime(fmt), args...); + log::print("\n"); } + void redirectToFile(); + } \ No newline at end of file diff --git a/lib/libimhex/include/hex/helpers/paths.hpp b/lib/libimhex/include/hex/helpers/paths.hpp index dc9895d75..3d67db337 100644 --- a/lib/libimhex/include/hex/helpers/paths.hpp +++ b/lib/libimhex/include/hex/helpers/paths.hpp @@ -17,7 +17,8 @@ namespace hex { Yara, Config, Resources, - Constants + Constants, + Logs }; std::string getExecutablePath(); diff --git a/lib/libimhex/source/helpers/file.cpp b/lib/libimhex/source/helpers/file.cpp index 6ca2f125d..35767c6e0 100644 --- a/lib/libimhex/source/helpers/file.cpp +++ b/lib/libimhex/source/helpers/file.cpp @@ -3,7 +3,7 @@ namespace hex { - File::File(const fs::path &path, Mode mode) : m_path(path) { + File::File(const fs::path &path, Mode mode) noexcept : m_path(path) { if (mode == File::Mode::Read) this->m_file = fopen64(path.string().c_str(), "rb"); else if (mode == File::Mode::Write) @@ -13,7 +13,7 @@ namespace hex { this->m_file = fopen64(path.string().c_str(), "w+b"); } - File::File() { + File::File() noexcept { this->m_file = nullptr; } @@ -26,6 +26,16 @@ namespace hex { this->close(); } + File& File::operator=(File &&other) noexcept { + this->m_file = other.m_file; + other.m_file = nullptr; + + this->m_path = std::move(other.m_path); + + return *this; + } + + void File::seek(u64 offset) { fseeko64(this->m_file, offset, SEEK_SET); } diff --git a/lib/libimhex/source/helpers/logger.cpp b/lib/libimhex/source/helpers/logger.cpp new file mode 100644 index 000000000..18ea0bf25 --- /dev/null +++ b/lib/libimhex/source/helpers/logger.cpp @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +#include + +namespace hex::log { + + static File g_loggerFile; + + FILE* getDestination() { + if (g_loggerFile.isValid()) + return g_loggerFile.getHandle(); + else + return stdout; + } + + bool isRedirected() { + return g_loggerFile.isValid(); + } + + void redirectToFile() { + if (g_loggerFile.isValid()) return; + + for (const auto &path : hex::getPath(ImHexPath::Logs)) { + g_loggerFile = File(path / hex::format("{0:%Y%m%d_%H%M%S}.log", fmt::localtime(std::chrono::system_clock::now())), File::Mode::Create); + + if (g_loggerFile.isValid()) break; + } + } + +} \ No newline at end of file diff --git a/lib/libimhex/source/helpers/paths.cpp b/lib/libimhex/source/helpers/paths.cpp index ba119306a..b21e68e3b 100644 --- a/lib/libimhex/source/helpers/paths.cpp +++ b/lib/libimhex/source/helpers/paths.cpp @@ -98,6 +98,11 @@ namespace hex { return (path / "constants").string(); }); break; + case ImHexPath::Logs: + std::transform(paths.begin(), paths.end(), std::back_inserter(result), [](auto &path){ + return (path / "logs").string(); + }); + break; default: __builtin_unreachable(); } #elif defined(OS_MACOS) @@ -137,6 +142,9 @@ namespace hex { case ImHexPath::Constants: result.push_back((applicationSupportDir / "constants").string()); break; + case ImHexPath::Logs: + result.push_back((applicationSupportDir / "logs").string()); + break; default: __builtin_unreachable(); } #else @@ -191,6 +199,10 @@ namespace hex { std::transform(dataDirs.begin(), dataDirs.end(), std::back_inserter(result), [](auto p) { return (p / "constants").string(); }); break; + case ImHexPath::Logs: + std::transform(dataDirs.begin(), dataDirs.end(), std::back_inserter(result), + [](auto p) { return (p / "logs").string(); }); + break; default: __builtin_unreachable(); } #endif diff --git a/main/include/helpers/plugin_manager.hpp b/main/include/helpers/plugin_manager.hpp index 91e46416b..f55696b42 100644 --- a/main/include/helpers/plugin_manager.hpp +++ b/main/include/helpers/plugin_manager.hpp @@ -16,17 +16,18 @@ namespace hex { class Plugin { public: - Plugin(const fs::path &path); + explicit Plugin(const fs::path &path); Plugin(const Plugin&) = delete; Plugin(Plugin &&other) noexcept; ~Plugin(); - void initializePlugin() const; + [[nodiscard]] bool initializePlugin() const; [[nodiscard]] std::string getPluginName() const; [[nodiscard]] std::string getPluginAuthor() const; [[nodiscard]] std::string getPluginDescription() const; void setImGuiContext(ImGuiContext *ctx) const; + [[nodiscard]] const fs::path& getPath() const; private: using InitializePluginFunc = void(*)(); @@ -36,6 +37,7 @@ namespace hex { using SetImGuiContextFunc = void(*)(ImGuiContext*); void *m_handle = nullptr; + fs::path m_path; InitializePluginFunc m_initializePluginFunction = nullptr; GetPluginNameFunc m_getPluginNameFunction = nullptr; diff --git a/main/source/helpers/plugin_manager.cpp b/main/source/helpers/plugin_manager.cpp index aabb9e040..baee65e87 100644 --- a/main/source/helpers/plugin_manager.cpp +++ b/main/source/helpers/plugin_manager.cpp @@ -14,7 +14,7 @@ namespace hex { constexpr auto GetPluginDescriptionSymbol = "_ZN3hex6plugin{0}{1}8internal20getPluginDescriptionEv"; constexpr auto SetImGuiContextSymbol = "_ZN3hex6plugin{0}{1}8internal15setImGuiContextEP12ImGuiContext"; - Plugin::Plugin(const fs::path &path) { + Plugin::Plugin(const fs::path &path) : m_path(path) { this->m_handle = dlopen(path.string().c_str(), RTLD_LAZY); if (this->m_handle == nullptr) { @@ -33,6 +33,8 @@ namespace hex { Plugin::Plugin(Plugin &&other) noexcept { this->m_handle = other.m_handle; + this->m_path = std::move(other.m_path); + this->m_initializePluginFunction = other.m_initializePluginFunction; this->m_getPluginNameFunction = other.m_getPluginNameFunction; this->m_getPluginAuthorFunction = other.m_getPluginAuthorFunction; @@ -52,9 +54,13 @@ namespace hex { dlclose(this->m_handle); } - void Plugin::initializePlugin() const { - if (this->m_initializePluginFunction != nullptr) + bool Plugin::initializePlugin() const { + if (this->m_initializePluginFunction != nullptr) { this->m_initializePluginFunction(); + return true; + } else { + return false; + } } std::string Plugin::getPluginName() const { @@ -83,6 +89,12 @@ namespace hex { this->m_setImGuiContextFunction(ctx); } + const fs::path &Plugin::getPath() const { + return this->m_path; + } + + + bool PluginManager::load(const fs::path &pluginFolder) { if (!fs::exists(pluginFolder)) return false; diff --git a/main/source/init/splash_window.cpp b/main/source/init/splash_window.cpp index 3576c9405..e0040fbf7 100644 --- a/main/source/init/splash_window.cpp +++ b/main/source/init/splash_window.cpp @@ -49,7 +49,8 @@ namespace hex::init { try { status = task() && status; - } catch (...) { + } catch (std::exception &e) { + log::error("Init task {} threw an exception: {}", name, e.what()); status = false; } diff --git a/main/source/init/tasks.cpp b/main/source/init/tasks.cpp index 5f4bb3164..f02b5c592 100644 --- a/main/source/init/tasks.cpp +++ b/main/source/init/tasks.cpp @@ -57,7 +57,7 @@ namespace hex::init { bool createDirectories() { bool result = true; - std::array paths = { + constexpr std::array paths = { ImHexPath::Patterns, ImHexPath::PatternsInclude, ImHexPath::Magic, @@ -66,7 +66,8 @@ namespace hex::init { ImHexPath::Config, ImHexPath::Constants, ImHexPath::Yara, - ImHexPath::Python + ImHexPath::Python, + ImHexPath::Logs }; for (auto path : paths) { @@ -225,7 +226,8 @@ namespace hex::init { } for (const auto &plugin : PluginManager::getPlugins()) { - plugin.initializePlugin(); + if (!plugin.initializePlugin()) + log::error("Failed to initialize plugin {}", plugin.getPath().filename().string()); } return true; diff --git a/main/source/window/linux_window.cpp b/main/source/window/linux_window.cpp index 6a03987e4..5f9b9e5e9 100644 --- a/main/source/window/linux_window.cpp +++ b/main/source/window/linux_window.cpp @@ -3,13 +3,18 @@ #if defined(OS_LINUX) #include + #include + #include #include + #include namespace hex { void Window::initNative() { - + if (!isatty(STDOUT_FILENO)) { + log::redirectToFile(); + } } void Window::setupNativeWindow() { diff --git a/main/source/window/macos_window.cpp b/main/source/window/macos_window.cpp index fe5aa11fc..2e1fec93d 100644 --- a/main/source/window/macos_window.cpp +++ b/main/source/window/macos_window.cpp @@ -2,12 +2,17 @@ #if defined(OS_MACOS) + #include + #include + #include namespace hex { void Window::initNative() { - + if (!isatty(STDOUT_FILENO)) { + log::redirectToFile(); + } } void Window::setupNativeWindow() { diff --git a/main/source/window/win_window.cpp b/main/source/window/win_window.cpp index 28a9a6d12..01c950855 100644 --- a/main/source/window/win_window.cpp +++ b/main/source/window/win_window.cpp @@ -172,25 +172,26 @@ // Redirect cin, cout and cerr to that console freopen("CONIN$", "r", stdin); freopen("CONOUT$", "w", stdout); - freopen("CONERR$", "w", stderr); + freopen("CONOUT$", "w", stderr); setvbuf(stdin, nullptr, _IONBF, 0); setvbuf(stdout, nullptr, _IONBF, 0); setvbuf(stderr, nullptr, _IONBF, 0); fmt::print("\n"); - } - - // Enable color format specifiers in console - { - auto hConsole = ::GetStdHandle(STD_OUTPUT_HANDLE); - if (hConsole != INVALID_HANDLE_VALUE) { - DWORD mode = 0; - if (::GetConsoleMode(hConsole, &mode)) { - mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; - ::SetConsoleMode(hConsole, mode); + // Enable color format specifiers in console + { + auto hConsole = ::GetStdHandle(STD_OUTPUT_HANDLE); + if (hConsole != INVALID_HANDLE_VALUE) { + DWORD mode = 0; + if (::GetConsoleMode(hConsole, &mode)) { + mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; + ::SetConsoleMode(hConsole, mode); + } } } + } else { + log::redirectToFile(); } // Open new files in already existing ImHex instance