From 1d34a62e38e7215aa48049a3d091dd0a69d954a1 Mon Sep 17 00:00:00 2001 From: Chris Punches Date: Wed, 26 Mar 2025 01:10:18 -0400 Subject: [PATCH] improved consistency in argument handling, introduction of dpm_con (not everything needs to be in the log) --- dpmdk/include/CommonModuleAPI.hpp | 23 +++ include/Logger.hpp | 12 ++ include/dpm_interface.hpp | 2 + include/handlers.hpp | 2 + include/module_interface.hpp | 11 ++ modules/build/src/commands.cpp | 231 +++++++++++++++--------------- modules/info/src/infoFuncs.cpp | 39 ++--- src/Logger.cpp | 20 +++ src/dpm.cpp | 5 +- src/dpm_interface.cpp | 17 ++- src/handlers.cpp | 69 +++++---- src/module_interface.cpp | 31 ++++ 12 files changed, 288 insertions(+), 174 deletions(-) diff --git a/dpmdk/include/CommonModuleAPI.hpp b/dpmdk/include/CommonModuleAPI.hpp index 3ffcd45..d81ce4d 100644 --- a/dpmdk/include/CommonModuleAPI.hpp +++ b/dpmdk/include/CommonModuleAPI.hpp @@ -131,6 +131,17 @@ extern "C" { */ void dpm_log(int level, const char* message); + /** + * @brief Console logging function + * + * Allows modules to log messages to the console only, bypassing the file logging. + * This is useful for user-facing output that doesn't need to be recorded in logs. + * + * @param level The log level (LOG_FATAL, LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DEBUG) + * @param message The message to log + */ + void dpm_con(int level, const char* message); + /** * @brief Sets the logging level * @@ -174,6 +185,18 @@ default: level_str = "UNKNOWN"; break; \ } \ std::cout << "[" << level_str << "] " << message << std::endl; \ } \ +extern "C" void dpm_con(int level, const char* message) { \ +const char* level_str; \ +switch (level) { \ +case 0: level_str = "FATAL"; break; \ +case 1: level_str = "ERROR"; break; \ +case 2: level_str = "WARN"; break; \ +case 3: level_str = "INFO"; break; \ +case 4: level_str = "DEBUG"; break; \ +default: level_str = "UNKNOWN"; break; \ +} \ +std::cout << "[" << level_str << "] " << message << std::endl; \ +} \ extern "C" const char* dpm_get_config(const char* section, const char* key) { \ if (!section || !key) return nullptr; \ \ diff --git a/include/Logger.hpp b/include/Logger.hpp index 6207ec1..7ded5b1 100644 --- a/include/Logger.hpp +++ b/include/Logger.hpp @@ -77,6 +77,18 @@ public: */ void log(LoggingLevels log_level, const std::string& message); + /** + * @brief Logs a message to console only + * + * Writes a log message only to the console, skipping any file logging. + * Messages with levels FATAL, ERROR, or WARN are written to stderr, + * while others go to stdout. + * + * @param level The severity level of the message + * @param message The message to log + */ + void log_console(LoggingLevels level, const std::string& message); + /** * @brief Sets the log file path * diff --git a/include/dpm_interface.hpp b/include/dpm_interface.hpp index 1ac5616..f9a2d6d 100644 --- a/include/dpm_interface.hpp +++ b/include/dpm_interface.hpp @@ -41,6 +41,8 @@ #include "dpm_interface_helpers.hpp" #include "Logger.hpp" +#include + /** * @defgroup dpm_interface DPM Interface Methods * @brief Interface methods for the DPM command-line tool diff --git a/include/handlers.hpp b/include/handlers.hpp index 55bd5fe..4f08aeb 100644 --- a/include/handlers.hpp +++ b/include/handlers.hpp @@ -32,6 +32,8 @@ #include #include "error.hpp" +#include "LoggingLevels.hpp" +#include "module_interface.hpp" /** * @brief Main error handler that dispatches to specific handlers diff --git a/include/module_interface.hpp b/include/module_interface.hpp index 6cd9c2a..5c81c61 100644 --- a/include/module_interface.hpp +++ b/include/module_interface.hpp @@ -121,6 +121,17 @@ extern "C" { */ void dpm_log(int level, const char* message); + /** + * @brief Logs messages to console only + * + * Allows modules to log messages to the console only, skipping any file logging. + * This is useful for user-facing output that doesn't need to be recorded. + * + * @param level The log level as an integer (0=FATAL, 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG) + * @param message The message to log + */ + void dpm_con(int level, const char* message); + /** * @brief Sets the logging level * diff --git a/modules/build/src/commands.cpp b/modules/build/src/commands.cpp index 6e3413b..4ab571e 100644 --- a/modules/build/src/commands.cpp +++ b/modules/build/src/commands.cpp @@ -147,6 +147,7 @@ int cmd_stage(int argc, char** argv) { // Validate options int validate_result = validate_build_options(options); if (validate_result != 0) { + cmd_stage_help(argc, argv); return validate_result; } @@ -271,19 +272,19 @@ int cmd_sign(int argc, char** argv) { } int cmd_help(int argc, char** argv) { - dpm_log(LOG_INFO, "DPM Build Module - Creates DPM packages."); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Available commands:"); - dpm_log(LOG_INFO, " stage - Stage a new DPM package directory"); - dpm_log(LOG_INFO, " metadata - Generate or refresh package metadata"); - dpm_log(LOG_INFO, " sign - Sign a package or package stage directory"); - dpm_log(LOG_INFO, " seal - Seal a package stage directory into final format"); - dpm_log(LOG_INFO, " unseal - Unseal a package back to stage format"); - dpm_log(LOG_INFO, " help - Display this help message"); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Usage: dpm build "); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "For command-specific help, use: dpm build --help"); + dpm_con(LOG_INFO, "DPM Build Module - Creates DPM packages."); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "Available commands:"); + dpm_con(LOG_INFO, " stage - Stage a new DPM package directory"); + dpm_con(LOG_INFO, " metadata - Generate or refresh package metadata"); + dpm_con(LOG_INFO, " sign - Sign a package or package stage directory"); + dpm_con(LOG_INFO, " seal - Seal a package stage directory into final format"); + dpm_con(LOG_INFO, " unseal - Unseal a package back to stage format"); + dpm_con(LOG_INFO, " help - Display this help message"); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "Usage: dpm build "); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "For command-specific help, use: dpm build --help"); return 0; } @@ -291,76 +292,76 @@ int cmd_help(int argc, char** argv) { int cmd_unknown(const char* command, int argc, char** argv) { std::string msg = "Unknown command: "; msg += (command ? command : ""); - dpm_log(LOG_WARN, msg.c_str()); - dpm_log(LOG_WARN, "Run 'dpm build help' for a list of available commands"); + dpm_con(LOG_WARN, msg.c_str()); + dpm_con(LOG_WARN, "Run 'dpm build help' for a list of available commands"); return 1; } + int cmd_metadata_help(int argc, char** argv) { - dpm_log(LOG_INFO, "Usage: dpm build metadata [options]"); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Options:"); - dpm_log(LOG_INFO, " -s, --stage DIR Package stage directory path (required)"); - dpm_log(LOG_INFO, " -r, --refresh Refresh existing metadata (use for updating)"); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "For new metadata generation (when not using --refresh):"); - dpm_log(LOG_INFO, " -n, --name NAME Package name (required for new generation)"); - dpm_log(LOG_INFO, " -V, --version VERSION Package version (required for new generation)"); - dpm_log(LOG_INFO, " -a, --architecture ARCH Package architecture (required for new generation)"); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Additional options:"); - dpm_log(LOG_INFO, " -f, --force Force operation even if warnings occur"); - dpm_log(LOG_INFO, " -v, --verbose Enable verbose output"); - dpm_log(LOG_INFO, " -h, --help Display this help message"); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Examples:"); - dpm_log(LOG_INFO, " # Refresh metadata in an existing package stage:"); - dpm_log(LOG_INFO, " dpm build metadata --stage=./my-package-1.0.x86_64 --refresh"); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, " # Generate new metadata for a package stage:"); - dpm_log(LOG_INFO, " dpm build metadata --stage=./my-package-1.0.x86_64 --name=my-package --version=1.0 --architecture=x86_64"); + dpm_con(LOG_INFO, "Usage: dpm build metadata [options]"); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "Options:"); + dpm_con(LOG_INFO, " -s, --stage DIR Package stage directory path (required)"); + dpm_con(LOG_INFO, " -r, --refresh Refresh existing metadata (use for updating)"); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "For new metadata generation (when not using --refresh):"); + dpm_con(LOG_INFO, " -n, --name NAME Package name (required for new generation)"); + dpm_con(LOG_INFO, " -V, --version VERSION Package version (required for new generation)"); + dpm_con(LOG_INFO, " -a, --architecture ARCH Package architecture (required for new generation)"); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "Additional options:"); + dpm_con(LOG_INFO, " -f, --force Force operation even if warnings occur"); + dpm_con(LOG_INFO, " -v, --verbose Enable verbose output"); + dpm_con(LOG_INFO, " -h, --help Display this help message"); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "Examples:"); + dpm_con(LOG_INFO, " # Refresh metadata in an existing package stage:"); + dpm_con(LOG_INFO, " dpm build metadata --stage=./my-package-1.0.x86_64 --refresh"); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, " # Generate new metadata for a package stage:"); + dpm_con(LOG_INFO, " dpm build metadata --stage=./my-package-1.0.x86_64 --name=my-package --version=1.0 --architecture=x86_64"); return 0; } int cmd_stage_help(int argc, char** argv) { - dpm_log(LOG_INFO, "Usage: dpm build stage [options]"); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Options:"); - dpm_log(LOG_INFO, " -o, --output DIR Directory to save the staged package (required)"); - dpm_log(LOG_INFO, " -c, --contents DIR Directory with package contents (required)"); - dpm_log(LOG_INFO, " -H, --hooks DIR Directory with package hooks (optional)"); - dpm_log(LOG_INFO, " -n, --name NAME Package name (required)"); - dpm_log(LOG_INFO, " -V, --version VERSION Package version (required)"); - dpm_log(LOG_INFO, " -a, --architecture ARCH Package architecture (required, e.g., x86_64)"); - dpm_log(LOG_INFO, " -O, --os OS Package OS (optional, e.g., dhl2)"); - dpm_log(LOG_INFO, " -f, --force Force package staging even if warnings occur"); - dpm_log(LOG_INFO, " -v, --verbose Enable verbose output"); - dpm_log(LOG_INFO, " -h, --help Display this help message"); + dpm_con(LOG_INFO, "Usage: dpm build stage [options]"); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "Options:"); + dpm_con(LOG_INFO, " -o, --output DIR Directory to save the staged package (required)"); + dpm_con(LOG_INFO, " -c, --contents DIR Directory with package contents (required)"); + dpm_con(LOG_INFO, " -H, --hooks DIR Directory with package hooks (optional)"); + dpm_con(LOG_INFO, " -n, --name NAME Package name (required)"); + dpm_con(LOG_INFO, " -V, --version VERSION Package version (required)"); + dpm_con(LOG_INFO, " -a, --architecture ARCH Package architecture (required, e.g., x86_64)"); + dpm_con(LOG_INFO, " -O, --os OS Package OS (optional, e.g., dhl2)"); + dpm_con(LOG_INFO, " -f, --force Force package staging even if warnings occur"); + dpm_con(LOG_INFO, " -v, --verbose Enable verbose output"); + dpm_con(LOG_INFO, " -h, --help Display this help message"); return 0; } int cmd_sign_help(int argc, char** argv) { - dpm_log(LOG_INFO, "Usage: dpm build sign [options]"); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Sign a DPM package or package stage directory using GPG."); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Options:"); - dpm_log(LOG_INFO, " -k, --key-id ID GPG key ID or email to use for signing (required)"); - dpm_log(LOG_INFO, " -s, --stage DIR Package stage directory to sign"); - dpm_log(LOG_INFO, " -p, --package FILE Package file to sign"); - dpm_log(LOG_INFO, " -f, --force Force signing even if warnings occur"); - dpm_log(LOG_INFO, " -v, --verbose Enable verbose output"); - dpm_log(LOG_INFO, " -h, --help Display this help message"); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Either --stage or --package must be specified, but not both."); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Examples:"); - dpm_log(LOG_INFO, " dpm build sign --key-id=\"user@example.com\" --stage=./my-package-1.0.x86_64"); - dpm_log(LOG_INFO, " dpm build sign --key-id=\"AB123CD456\" --package=./my-package-1.0.x86_64.dpm"); + dpm_con(LOG_INFO, "Usage: dpm build sign [options]"); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "Sign a DPM package or package stage directory using GPG."); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "Options:"); + dpm_con(LOG_INFO, " -k, --key-id ID GPG key ID or email to use for signing (required)"); + dpm_con(LOG_INFO, " -s, --stage DIR Package stage directory to sign"); + dpm_con(LOG_INFO, " -p, --package FILE Package file to sign"); + dpm_con(LOG_INFO, " -f, --force Force signing even if warnings occur"); + dpm_con(LOG_INFO, " -v, --verbose Enable verbose output"); + dpm_con(LOG_INFO, " -h, --help Display this help message"); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "Either --stage or --package must be specified, but not both."); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "Examples:"); + dpm_con(LOG_INFO, " dpm build sign --key-id=\"user@example.com\" --stage=./my-package-1.0.x86_64"); + dpm_con(LOG_INFO, " dpm build sign --key-id=\"AB123CD456\" --package=./my-package-1.0.x86_64.dpm"); return 0; } - int cmd_unseal(int argc, char** argv) { // Parse command line options std::string input_path = ""; @@ -402,13 +403,13 @@ int cmd_unseal(int argc, char** argv) { // Validate that input path is provided if (input_path.empty()) { - dpm_log(LOG_ERROR, "Input path is required (--input/-i)"); + dpm_con(LOG_ERROR, "Input path is required (--input/-i)"); return cmd_unseal_help(argc, argv); } // Check for invalid option combinations if (components_mode && !output_dir.empty()) { - dpm_log(LOG_ERROR, "Output directory (-o/--output) cannot be specified in components mode (-c/--components)"); + dpm_con(LOG_ERROR, "Output directory (-o/--output) cannot be specified in components mode (-c/--components)"); return cmd_unseal_help(argc, argv); } @@ -417,7 +418,7 @@ int cmd_unseal(int argc, char** argv) { // Check if input path exists if (!std::filesystem::exists(input_path)) { - dpm_log(LOG_ERROR, ("Input path does not exist: " + input_path).c_str()); + dpm_con(LOG_ERROR, ("Input path does not exist: " + input_path).c_str()); return 1; } @@ -430,7 +431,7 @@ int cmd_unseal(int argc, char** argv) { if (components_mode) { // We're unsealing components of a stage directory if (!std::filesystem::is_directory(input_path)) { - dpm_log(LOG_ERROR, ("Input path must be a directory in components mode: " + input_path).c_str()); + dpm_con(LOG_ERROR, ("Input path must be a directory in components mode: " + input_path).c_str()); return 1; } @@ -439,7 +440,7 @@ int cmd_unseal(int argc, char** argv) { } else { // We're unsealing a package file if (std::filesystem::is_directory(input_path)) { - dpm_log(LOG_ERROR, ("Input path must be a file when not in components mode: " + input_path).c_str()); + dpm_con(LOG_ERROR, ("Input path must be a file when not in components mode: " + input_path).c_str()); return 1; } @@ -449,28 +450,28 @@ int cmd_unseal(int argc, char** argv) { } int cmd_unseal_help(int argc, char** argv) { - dpm_log(LOG_INFO, "Usage: dpm build unseal [options]"); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Unseals a DPM package file or package stage components."); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Options:"); - dpm_log(LOG_INFO, " -i, --input PATH Path to package file or stage directory (required)"); - dpm_log(LOG_INFO, " -o, --output DIR Directory to extract package to (optional, package mode only)"); - dpm_log(LOG_INFO, " -c, --components Component mode: unseal components in a stage directory"); - dpm_log(LOG_INFO, " Without this flag, input is treated as a package file"); - dpm_log(LOG_INFO, " -f, --force Force unsealing even if warnings occur or directory exists"); - dpm_log(LOG_INFO, " -v, --verbose Enable verbose output"); - dpm_log(LOG_INFO, " -h, --help Display this help message"); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Examples:"); - dpm_log(LOG_INFO, " # Unseal a package file to a directory:"); - dpm_log(LOG_INFO, " dpm build unseal --input=./my-package-1.0.x86_64.dpm"); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, " # Unseal a package file to a specific directory:"); - dpm_log(LOG_INFO, " dpm build unseal --input=./my-package-1.0.x86_64.dpm --output=./extract"); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, " # Unseal components in a stage directory:"); - dpm_log(LOG_INFO, " dpm build unseal --input=./my-package-1.0.x86_64 --components"); + dpm_con(LOG_INFO, "Usage: dpm build unseal [options]"); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "Unseals a DPM package file or package stage components."); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "Options:"); + dpm_con(LOG_INFO, " -i, --input PATH Path to package file or stage directory (required)"); + dpm_con(LOG_INFO, " -o, --output DIR Directory to extract package to (optional, package mode only)"); + dpm_con(LOG_INFO, " -c, --components Component mode: unseal components in a stage directory"); + dpm_con(LOG_INFO, " Without this flag, input is treated as a package file"); + dpm_con(LOG_INFO, " -f, --force Force unsealing even if warnings occur or directory exists"); + dpm_con(LOG_INFO, " -v, --verbose Enable verbose output"); + dpm_con(LOG_INFO, " -h, --help Display this help message"); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "Examples:"); + dpm_con(LOG_INFO, " # Unseal a package file to a directory:"); + dpm_con(LOG_INFO, " dpm build unseal --input=./my-package-1.0.x86_64.dpm"); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, " # Unseal a package file to a specific directory:"); + dpm_con(LOG_INFO, " dpm build unseal --input=./my-package-1.0.x86_64.dpm --output=./extract"); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, " # Unseal components in a stage directory:"); + dpm_con(LOG_INFO, " dpm build unseal --input=./my-package-1.0.x86_64 --components"); return 0; } @@ -515,7 +516,7 @@ int cmd_seal(int argc, char** argv) { // Validate that stage directory is provided if (stage_dir.empty()) { - dpm_log(LOG_ERROR, "Stage directory is required (--stage/-s)"); + dpm_con(LOG_ERROR, "Stage directory is required (--stage/-s)"); return cmd_seal_help(argc, argv); } @@ -524,7 +525,7 @@ int cmd_seal(int argc, char** argv) { // Check if stage directory exists if (!std::filesystem::exists(stage_dir)) { - dpm_log(LOG_ERROR, ("Stage directory does not exist: " + stage_dir).c_str()); + dpm_con(LOG_ERROR, ("Stage directory does not exist: " + stage_dir).c_str()); return 1; } @@ -542,22 +543,22 @@ int cmd_seal(int argc, char** argv) { } int cmd_seal_help(int argc, char** argv) { - dpm_log(LOG_INFO, "Usage: dpm build seal [options]"); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Seals a package stage directory by replacing contents, metadata,"); - dpm_log(LOG_INFO, "hooks, and signatures directories with gzipped tarballs."); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Options:"); - dpm_log(LOG_INFO, " -s, --stage DIR Package stage directory to seal (required)"); - dpm_log(LOG_INFO, " -o, --output DIR Output directory for the finalized package (optional)"); - dpm_log(LOG_INFO, " -f, --force Force sealing even if warnings occur"); - dpm_log(LOG_INFO, " -z, --finalize Also compress the entire stage as a final package"); - dpm_log(LOG_INFO, " -v, --verbose Enable verbose output"); - dpm_log(LOG_INFO, " -h, --help Display this help message"); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Examples:"); - dpm_log(LOG_INFO, " dpm build seal --stage=./my-package-1.0.x86_64"); - dpm_log(LOG_INFO, " dpm build seal --stage=./my-package-1.0.x86_64 --finalize"); - dpm_log(LOG_INFO, " dpm build seal --stage=./my-package-1.0.x86_64 --finalize --output=/tmp"); + dpm_con(LOG_INFO, "Usage: dpm build seal [options]"); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "Seals a package stage directory by replacing contents, metadata,"); + dpm_con(LOG_INFO, "hooks, and signatures directories with gzipped tarballs."); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "Options:"); + dpm_con(LOG_INFO, " -s, --stage DIR Package stage directory to seal (required)"); + dpm_con(LOG_INFO, " -o, --output DIR Output directory for the finalized package (optional)"); + dpm_con(LOG_INFO, " -f, --force Force sealing even if warnings occur"); + dpm_con(LOG_INFO, " -z, --finalize Also compress the entire stage as a final package"); + dpm_con(LOG_INFO, " -v, --verbose Enable verbose output"); + dpm_con(LOG_INFO, " -h, --help Display this help message"); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "Examples:"); + dpm_con(LOG_INFO, " dpm build seal --stage=./my-package-1.0.x86_64"); + dpm_con(LOG_INFO, " dpm build seal --stage=./my-package-1.0.x86_64 --finalize"); + dpm_con(LOG_INFO, " dpm build seal --stage=./my-package-1.0.x86_64 --finalize --output=/tmp"); return 0; -} \ No newline at end of file +} diff --git a/modules/info/src/infoFuncs.cpp b/modules/info/src/infoFuncs.cpp index 78b6856..2c0bf2b 100644 --- a/modules/info/src/infoFuncs.cpp +++ b/modules/info/src/infoFuncs.cpp @@ -82,16 +82,17 @@ std::string detect_os() { /** * Command handler for help command */ + int cmd_help(int argc, char** argv) { - dpm_log(LOG_INFO, "DPM Info Module - Provides information about the system."); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, "Available commands:"); - dpm_log(LOG_INFO, ""); - dpm_log(LOG_INFO, " version - Display DPM version information"); - dpm_log(LOG_INFO, " system - Display system information"); - dpm_log(LOG_INFO, " config - Display configuration information"); - dpm_log(LOG_INFO, " help - Display this help message"); - dpm_log(LOG_INFO, ""); + dpm_con(LOG_INFO, "DPM Info Module - Provides information about the system."); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, "Available commands:"); + dpm_con(LOG_INFO, ""); + dpm_con(LOG_INFO, " version - Display DPM version information"); + dpm_con(LOG_INFO, " system - Display system information"); + dpm_con(LOG_INFO, " config - Display configuration information"); + dpm_con(LOG_INFO, " help - Display this help message"); + dpm_con(LOG_INFO, ""); return 0; } @@ -102,15 +103,15 @@ int cmd_help(int argc, char** argv) { int cmd_version(int argc, char** argv) { std::string version_msg = "DPM Version: "; version_msg += DPM_VERSION; - dpm_log(LOG_INFO, version_msg.c_str()); + dpm_con(LOG_INFO, version_msg.c_str()); std::string date_msg = "Build Date: "; date_msg += __DATE__; - dpm_log(LOG_INFO, date_msg.c_str()); + dpm_con(LOG_INFO, date_msg.c_str()); std::string time_msg = "Build Time: "; time_msg += __TIME__; - dpm_log(LOG_INFO, time_msg.c_str()); + dpm_con(LOG_INFO, time_msg.c_str()); return 0; } @@ -119,15 +120,15 @@ int cmd_version(int argc, char** argv) { * Command handler for system command */ int cmd_system(int argc, char** argv) { - dpm_log(LOG_INFO, "System Information:"); + dpm_con(LOG_INFO, "System Information:"); std::string os_msg = " OS: "; os_msg += detect_os(); - dpm_log(LOG_INFO, os_msg.c_str()); + dpm_con(LOG_INFO, os_msg.c_str()); std::string arch_msg = " Architecture: "; arch_msg += detect_architecture(); - dpm_log(LOG_INFO, arch_msg.c_str()); + dpm_con(LOG_INFO, arch_msg.c_str()); return 0; } @@ -138,11 +139,11 @@ int cmd_system(int argc, char** argv) { int cmd_config(int argc, char** argv) { const char* module_path = dpm_get_config("modules", "module_path"); - dpm_log(LOG_INFO, "Configuration Information:"); + dpm_con(LOG_INFO, "Configuration Information:"); std::string path_msg = " Module Path: "; path_msg += (module_path ? module_path : "Not configured"); - dpm_log(LOG_INFO, path_msg.c_str()); + dpm_con(LOG_INFO, path_msg.c_str()); return 0; } @@ -153,8 +154,8 @@ int cmd_config(int argc, char** argv) { int cmd_unknown(const char* command, int argc, char** argv) { std::string msg = "Unknown command: "; msg += (command ? command : ""); - dpm_log(LOG_WARN, msg.c_str()); - dpm_log(LOG_WARN, "Run 'dpm info help' for a list of available commands"); + dpm_con(LOG_WARN, msg.c_str()); + dpm_con(LOG_WARN, "Run 'dpm info help' for a list of available commands"); return 1; } diff --git a/src/Logger.cpp b/src/Logger.cpp index 8cc746d..d7468d6 100644 --- a/src/Logger.cpp +++ b/src/Logger.cpp @@ -156,4 +156,24 @@ void Logger::log(LoggingLevels message_level, const std::string& message) } } } +} + +void Logger::log_console(LoggingLevels level, const std::string& message) +{ + // Only process if the message level is less than or equal to the configured level + if (level <= log_level) { + // Convert log level to string + std::string level_str = LogLevelToString(level); + + // Console output without timestamp + if (level == LoggingLevels::FATAL || + level == LoggingLevels::ERROR || + level == LoggingLevels::WARN) { + // Send to stderr + std::cerr << level_str << ": " << message << std::endl; + } else { + // Send to stdout + std::cout << message << std::endl; + } + } } \ No newline at end of file diff --git a/src/dpm.cpp b/src/dpm.cpp index a2b9ba2..a3225c4 100644 --- a/src/dpm.cpp +++ b/src/dpm.cpp @@ -37,6 +37,8 @@ #include "error.hpp" #include "ConfigManager.hpp" #include "Logger.hpp" +#include "LoggingLevels.hpp" +#include "module_interface.hpp" /* * DPM serves three functions: @@ -84,8 +86,7 @@ int main( int argc, char* argv[] ) if (!config_loaded) { // failed to load any configuration files, so alert the user - std::cerr << "Warning: No configuration files present or loaded from '" - << g_config_manager.getConfigDir() << "*.conf', reverting to defaults." << std::endl; + dpm_con( ERROR, ("Warning: No configuration files present or loaded from '" + g_config_manager.getConfigDir() + "*.conf', reverting to defaults.").c_str()); } // Configure logger (CLI args > config > defaults) diff --git a/src/dpm_interface.cpp b/src/dpm_interface.cpp index 504d200..3639d6f 100644 --- a/src/dpm_interface.cpp +++ b/src/dpm_interface.cpp @@ -30,7 +30,6 @@ #include "dpm_interface.hpp" -#include /* * DPM Interface methods. @@ -49,23 +48,23 @@ int main_check_module_path(const ModuleLoader& loader) loader.get_module_path(path); if (!std::filesystem::exists(path)) { - g_logger.log(LoggingLevels::FATAL, "modules.modules_path does not exist: " + path); + dpm_con(FATAL, ("modules.modules_path does not exist: " + path).c_str()); return 1; } if (!std::filesystem::is_directory(path)) { - g_logger.log(LoggingLevels::FATAL, "modules.modules_path is not a directory: " + path); + dpm_con(FATAL, ("modules.modules_path is not a directory: " + path).c_str()); return 1; } try { auto perms = std::filesystem::status(path).permissions(); if ((perms & std::filesystem::perms::owner_read) == std::filesystem::perms::none) { - g_logger.log(LoggingLevels::FATAL, "Permission denied: " + path); + dpm_con(FATAL, ("Permission denied: " + path).c_str()); return 1; } } catch (const std::filesystem::filesystem_error&) { - g_logger.log(LoggingLevels::FATAL, "Permission denied: " + path); + dpm_con(FATAL, ("Permission denied: " + path).c_str()); return 1; } @@ -82,18 +81,18 @@ int main_list_modules(const ModuleLoader& loader) { // set the module path DPMErrorCategory get_path_error = loader.get_module_path(path); if (get_path_error != DPMErrorCategory::SUCCESS) { - g_logger.log(LoggingLevels::FATAL, "Failed to get modules.modules_path"); + dpm_con(LoggingLevels::FATAL, "Failed to get modules.modules_path"); return 1; } DPMErrorCategory list_error = loader.list_available_modules(modules); if (list_error != DPMErrorCategory::SUCCESS) { - g_logger.log(LoggingLevels::FATAL, "No modules found in modules.modules_path: " + path); + dpm_con(LoggingLevels::FATAL, ("No modules found in modules.modules_path: " + path).c_str()); return 1; } if (modules.empty()) { - g_logger.log(LoggingLevels::FATAL, "No modules found in modules.modules_path: '" + path + "'."); + dpm_con(LoggingLevels::FATAL, ("No modules found in modules.modules_path: '" + path + "'.").c_str()); return 0; } @@ -115,7 +114,7 @@ int main_list_modules(const ModuleLoader& loader) { } if (valid_modules.empty()) { - g_logger.log(LoggingLevels::FATAL, "No valid DPM commands available."); + dpm_con(LoggingLevels::FATAL, "No valid DPM commands available."); return 0; } diff --git a/src/handlers.cpp b/src/handlers.cpp index a0116b6..8c01c83 100644 --- a/src/handlers.cpp +++ b/src/handlers.cpp @@ -30,12 +30,13 @@ #include "handlers.hpp" -// Helper function for validating required fields in a FlexDPMError void validate_field(FlexDPMError context, const char* field_name, const void* field_value) { if (!field_value) { - std::cerr << "Error: Incomplete error context. Missing required field: " << field_name; - std::cerr << " (Error category: " << static_cast(context.error) << ")" << std::endl; + std::string error_msg = "Error category " + std::to_string(static_cast(context.error)) + + ": Incomplete error context. Missing required field: " + field_name; + + dpm_log(FATAL, error_msg.c_str()); // Hard exit when a required field is missing exit(1); @@ -100,68 +101,78 @@ int handle_error(FlexDPMError context) { } // Now the individual handlers can be simplified since required fields are guaranteed -int handle_path_not_found( FlexDPMError context ) { - std::cerr << "Fatal error: The module directory '" << context.module_path << "' was not found. Exiting." << std::endl; +int handle_path_not_found(FlexDPMError context) { + std::string error_msg = "Fatal error: The module directory '" + std::string(context.module_path) + "' was not found. Exiting."; + dpm_log(FATAL, error_msg.c_str()); return 1; } -int handle_path_not_directory( FlexDPMError context ) { - std::cerr << "Fatal error: The module path '" << context.module_path << "' is not a directory. Exiting." << std::endl; +int handle_path_not_directory(FlexDPMError context) { + std::string error_msg = "Fatal error: The module path '" + std::string(context.module_path) + "' is not a directory. Exiting."; + dpm_log(FATAL, error_msg.c_str()); return 1; } -int handle_path_too_long( FlexDPMError context ) { - std::cerr << "Error: Module path is too long: '" << context.module_path << "'. Exiting." << std::endl; +int handle_path_too_long(FlexDPMError context) { + std::string error_msg = "Error: Module path is too long: '" + std::string(context.module_path) + "'. Exiting."; + dpm_log(ERROR, error_msg.c_str()); return 1; } -int handle_permission_denied( FlexDPMError context ) { - std::cerr << "Error: Permission denied accessing the modules path: '" << context.module_path << "'. Exiting." << std::endl; +int handle_permission_denied(FlexDPMError context) { + std::string error_msg = "Error: Permission denied accessing the modules path: '" + std::string(context.module_path) + "'. Exiting."; + dpm_log(ERROR, error_msg.c_str()); return 1; } -int handle_module_not_found( FlexDPMError context ) { - std::cerr << "Error: Module '"<< context.module_name << "' not found in '" << context.module_path << "'. Exiting." << std::endl; +int handle_module_not_found(FlexDPMError context) { + std::string error_msg = "Error: Module '" + std::string(context.module_name) + "' not found in '" + std::string(context.module_path) + "'. Exiting."; + dpm_log(ERROR, error_msg.c_str()); return 1; } -int handle_module_not_loaded( FlexDPMError context ) { - std::cerr << "Error: Attempted to execute module before loading it: " << context.module_name << std::endl; +int handle_module_not_loaded(FlexDPMError context) { + std::string error_msg = "Error: Attempted to execute module before loading it: " + std::string(context.module_name); + dpm_log(ERROR, error_msg.c_str()); return 1; } -int handle_module_load_failed( FlexDPMError context ) { - std::cerr << "Error: Failed to load module: " << context.module_name << std::endl; +int handle_module_load_failed(FlexDPMError context) { + std::string error_msg = "Error: Failed to load module: " + std::string(context.module_name); + dpm_log(ERROR, error_msg.c_str()); return 1; } -int handle_invalid_module( FlexDPMError context ) { - std::cerr << "Error: Invalid module format: " << context.module_name << std::endl; +int handle_invalid_module(FlexDPMError context) { + std::string error_msg = "Error: Invalid module format: " + std::string(context.module_name); + dpm_log(ERROR, error_msg.c_str()); return 1; } -int handle_symbol_not_found( FlexDPMError context ) { - std::cerr << "Error: Symbol not found in module: " << context.module_name; + +int handle_symbol_not_found(FlexDPMError context) { + std::string error_msg = "Error: Symbol not found in module: " + std::string(context.module_name); if (context.message) { - std::cerr << " (" << context.message << ")"; + error_msg += " (" + std::string(context.message) + ")"; } - std::cerr << std::endl; + dpm_log(ERROR, error_msg.c_str()); return 1; } int handle_symbol_execution_failed(FlexDPMError context) { - std::cerr << "Error: Module execution failed: " << context.module_name << std::endl; + std::string error_msg = "Error: Module execution failed: " + std::string(context.module_name); + dpm_log(ERROR, error_msg.c_str()); return 1; } int handle_undefined_error(FlexDPMError context) { - std::cerr << "Error: Undefined error occurred"; + std::string error_msg = "Error: Undefined error occurred"; if (context.module_name) { - std::cerr << " with module: " << context.module_name; + error_msg += " with module: " + std::string(context.module_name); } if (context.message) { - std::cerr << " (" << context.message << ")"; + error_msg += " (" + std::string(context.message) + ")"; } - std::cerr << std::endl; + dpm_log(ERROR, error_msg.c_str()); return 1; -} +} \ No newline at end of file diff --git a/src/module_interface.cpp b/src/module_interface.cpp index fc540db..3c8ce8a 100644 --- a/src/module_interface.cpp +++ b/src/module_interface.cpp @@ -64,6 +64,37 @@ extern "C" void dpm_log(int level, const char* message) { g_logger.log(log_level, message); } +extern "C" void dpm_con(int level, const char* message) { + if (!message) { + return; + } + + // Convert integer level to LoggingLevels enum + LoggingLevels log_level; + switch (level) { + case 0: + log_level = LoggingLevels::FATAL; + break; + case 1: + log_level = LoggingLevels::ERROR; + break; + case 2: + log_level = LoggingLevels::WARN; + break; + case 3: + log_level = LoggingLevels::INFO; + break; + case 4: + log_level = LoggingLevels::DEBUG; + break; + default: + log_level = LoggingLevels::INFO; + break; + } + + g_logger.log_console(log_level, message); +} + extern "C" void dpm_set_logging_level(int level) { // Convert integer level to LoggingLevels enum LoggingLevels log_level;