sys: Log to a file when ImHex wasn't opened though a terminal
This commit is contained in:
parent
2df4e22bf8
commit
8701e0f402
7
.idea/vcs.xml
generated
7
.idea/vcs.xml
generated
@ -9,5 +9,12 @@
|
||||
<mapping directory="$PROJECT_DIR$/external/nativefiledialog" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/external/xdgpp" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/external/yara/yara" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/lib/external/capstone" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/lib/external/curl" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/lib/external/fmt" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/lib/external/libromfs" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/lib/external/nativefiledialog" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/lib/external/xdgpp" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/lib/external/yara/yara" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -5,36 +5,54 @@
|
||||
|
||||
namespace hex::log {
|
||||
|
||||
FILE *getDestination();
|
||||
bool isRedirected();
|
||||
|
||||
template <typename... T>
|
||||
void print(fmt::format_string<T...> fmt, T&&... args) {
|
||||
fmt::print(getDestination(), fmt, args...);
|
||||
}
|
||||
|
||||
template <typename S, typename... Args>
|
||||
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();
|
||||
|
||||
}
|
@ -17,7 +17,8 @@ namespace hex {
|
||||
Yara,
|
||||
Config,
|
||||
Resources,
|
||||
Constants
|
||||
Constants,
|
||||
Logs
|
||||
};
|
||||
|
||||
std::string getExecutablePath();
|
||||
|
@ -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);
|
||||
}
|
||||
|
33
lib/libimhex/source/helpers/logger.cpp
Normal file
33
lib/libimhex/source/helpers/logger.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/helpers/file.hpp>
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -3,13 +3,18 @@
|
||||
#if defined(OS_LINUX)
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace hex {
|
||||
|
||||
void Window::initNative() {
|
||||
|
||||
if (!isatty(STDOUT_FILENO)) {
|
||||
log::redirectToFile();
|
||||
}
|
||||
}
|
||||
|
||||
void Window::setupNativeWindow() {
|
||||
|
@ -2,12 +2,17 @@
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace hex {
|
||||
|
||||
void Window::initNative() {
|
||||
|
||||
if (!isatty(STDOUT_FILENO)) {
|
||||
log::redirectToFile();
|
||||
}
|
||||
}
|
||||
|
||||
void Window::setupNativeWindow() {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user