directory restructure and documentation cleanup

master
Chris Punches 2025-03-08 04:56:07 -05:00
parent 34bab86b69
commit f0859c93c3
19 changed files with 1180 additions and 271 deletions

View File

@ -25,8 +25,13 @@ target_link_libraries(dpm dl)
# Export symbols for dynamic loading
target_link_options(dpm PRIVATE -rdynamic)
# Add the info module
add_library(info MODULE modules/info.cpp)
# Add the info module with specific source files
add_library(info MODULE
modules/info/info.cpp
modules/info/src/infoFuncs.cpp
# DO NOT include dpmdk sources which have different include requirements
)
set_target_properties(
info PROPERTIES
PREFIX ""
@ -34,6 +39,13 @@ set_target_properties(
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/modules"
)
# Add include directories for the info module
target_include_directories(info PRIVATE
include
modules/info
modules/info/include # Add this to find infoFuncs.hpp
)
# Installation rules
install(TARGETS dpm DESTINATION bin)
install(DIRECTORY DESTINATION /etc/dpm/conf.d)

View File

@ -45,52 +45,166 @@
#include "dpm_interface_helpers.hpp"
/**
* @class ConfigManager
* @brief Manages and provides access to configuration settings
*
* This class handles loading, parsing, and providing access to configuration
* values from INI-style files. It supports sections, key-value pairs, and
* provides type-conversion methods for different value types.
*/
class ConfigManager {
public:
// Constructor
/**
* @brief Constructor
*
* Initializes a new ConfigManager instance with the default
* configuration directory.
*/
ConfigManager();
// Set the configuration directory
/**
* @brief Sets the configuration directory path
*
* @param config_dir The directory path where configuration files are located
*/
void setConfigDir(const std::string& config_dir);
// Get the current configuration directory
/**
* @brief Gets the current configuration directory path
*
* @return The current configuration directory path
*/
std::string getConfigDir() const;
// Load all configuration files from the config directory
/**
* @brief Loads all configuration files from the config directory
*
* Scans the configuration directory for .conf files, parses them,
* and populates the internal configuration data structure.
*
* @return true if at least one configuration file was loaded successfully,
* false otherwise
*/
bool loadConfigurations();
// Get configuration values with type conversion
/**
* @brief Gets a configuration value as a C-style string
*
* @param section The section name (uses DEFAULT_SECTION if NULL)
* @param key The configuration key
* @return The configuration value as a C-style string, or NULL if not found
*/
const char* getConfigValue(const char* section, const char* key) const;
/**
* @brief Gets a configuration value as a C++ string with default
*
* @param section The section name (uses DEFAULT_SECTION if NULL)
* @param key The configuration key
* @param defaultValue The default value to return if the key is not found
* @return The configuration value as a string, or defaultValue if not found
*/
std::string getConfigString(const char* section, const char* key, const std::string& defaultValue = "") const;
/**
* @brief Gets a configuration value as an integer with default
*
* @param section The section name (uses DEFAULT_SECTION if NULL)
* @param key The configuration key
* @param defaultValue The default value to return if the key is not found or conversion fails
* @return The configuration value as an integer, or defaultValue if not found or conversion fails
*/
int getConfigInt(const char* section, const char* key, int defaultValue = 0) const;
/**
* @brief Gets a configuration value as a double with default
*
* @param section The section name (uses DEFAULT_SECTION if NULL)
* @param key The configuration key
* @param defaultValue The default value to return if the key is not found or conversion fails
* @return The configuration value as a double, or defaultValue if not found or conversion fails
*/
double getConfigDouble(const char* section, const char* key, double defaultValue = 0.0) const;
/**
* @brief Gets a configuration value as a boolean with default
*
* Recognizes "true", "yes", "1", "on", "enabled" as true values and
* "false", "no", "0", "off", "disabled" as false values (case-insensitive).
*
* @param section The section name (uses DEFAULT_SECTION if NULL)
* @param key The configuration key
* @param defaultValue The default value to return if the key is not found or conversion fails
* @return The configuration value as a boolean, or defaultValue if not found or conversion fails
*/
bool getConfigBool(const char* section, const char* key, bool defaultValue = false) const;
// Check if configuration directory exists
/**
* @brief Checks if the configuration directory exists
*
* @return true if the configuration directory exists, false otherwise
*/
bool configDirExists() const;
// Check if a configuration key exists
/**
* @brief Checks if a configuration key exists
*
* @param section The section name (uses DEFAULT_SECTION if NULL)
* @param key The configuration key
* @return true if the key exists in the specified section or DEFAULT_SECTION, false otherwise
*/
bool hasConfigKey(const char* section, const char* key) const;
private:
// Default section name to use when none is specified
/**
* @brief Default section name to use when none is specified
*/
static constexpr const char* DEFAULT_SECTION = "MAIN";
// Parse a single configuration file
/**
* @brief Parses a single configuration file
*
* @param config_file Path to the configuration file to parse
* @return true if the file was parsed successfully, false otherwise
*/
bool parseConfigFile(const std::filesystem::path& config_file);
// Trim whitespace from a string
/**
* @brief Removes leading and trailing whitespace from a string
*
* @param str The string to trim
* @return The trimmed string
*/
std::string trimWhitespace(const std::string& str) const;
// Find a key in the given section or in the default section
/**
* @brief Finds a configuration value by section and key
*
* Searches for the key in the specified section. If not found and the
* section is not DEFAULT_SECTION, tries to find the key in DEFAULT_SECTION.
*
* @param section The section name
* @param key The configuration key
* @return Optional reference to the configuration value if found, empty optional otherwise
*/
std::optional<std::reference_wrapper<const std::string>> findConfigValue(const std::string& section, const std::string& key) const;
// Configuration directory path
/**
* @brief Configuration directory path
*/
std::string _config_dir;
// Configuration data structure: section -> key -> value
/**
* @brief Configuration data structure: section -> key -> value
*/
std::map<std::string, std::map<std::string, std::string>> _config_data;
};
// Global configuration manager instance
extern ConfigManager g_config_manager;
/**
* @brief Global configuration manager instance
*
* Provides a single instance of the ConfigManager that can be accessed
* from anywhere in the application.
*/
extern ConfigManager g_config_manager;

View File

@ -33,20 +33,87 @@
#include <string>
#include "LoggingLevels.hpp"
// default system configuration
/**
* @struct DPMDefaults
* @brief Default configuration values for DPM
*
* Provides system-wide default values for paths, logging settings, and
* other configuration options used when explicit configuration is not provided.
*/
struct DPMDefaults {
/**
* @brief Default path to the directory containing DPM modules
*
* Directory where DPM looks for module shared objects (.so files)
* when no explicit module path is provided.
*/
static const char* const MODULE_PATH;
/**
* @brief Default path to the directory containing configuration files
*
* Directory where DPM looks for configuration files (.conf files)
* when no explicit configuration directory is provided.
*/
static const char* const CONFIG_DIR;
/**
* @brief Default path to the log file
*
* File where DPM writes log messages when logging to file is enabled
* and no explicit log file path is provided.
*/
static const char* const LOG_FILE;
/**
* @brief Default setting for whether to write to log file
*
* Determines whether DPM writes log messages to a file by default.
*/
static const bool write_to_log;
/**
* @brief Default log level
*
* Determines which log messages are recorded based on their severity.
* Messages with a level less than or equal to this value are logged.
*/
static const LoggingLevels LOG_LEVEL;
};
// Initialize static constants
/**
* @brief Default module path initialization
*
* Sets the default module path to the standard system location.
*/
inline const char * const DPMDefaults::MODULE_PATH = "/usr/lib/dpm/modules/";
/**
* @brief Default configuration directory initialization
*
* Sets the default configuration directory to the standard system location.
*/
inline const char * const DPMDefaults::CONFIG_DIR = "/etc/dpm/conf.d/";
/**
* @brief Default log file path initialization
*
* Sets the default log file path to the standard system location.
*/
inline const char * const DPMDefaults::LOG_FILE = "/var/log/dpm.log";
/**
* @brief Default write to log setting initialization
*
* By default, logging to file is disabled.
*/
inline const bool DPMDefaults::write_to_log = false;
/**
* @brief Default log level initialization
*
* By default, only messages with level INFO or lower (FATAL, ERROR, WARN, INFO)
* are logged, while DEBUG messages are not.
*/
inline const LoggingLevels DPMDefaults::LOG_LEVEL = LoggingLevels::INFO;

View File

@ -1,3 +1,33 @@
/**
* @file Logger.hpp
* @brief Logging system for the DPM utility
*
* Defines the Logger class which provides a centralized logging facility
* for the DPM utility. Supports multiple log levels, console output, and
* optional file logging with timestamps.
*
* @copyright Copyright (c) 2025 SILO GROUP LLC
* @author Chris Punches <chris.punches@silogroup.org>
*
* Part of the Dark Horse Linux Package Manager (DPM)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* For bug reports or contributions, please contact the dhlp-contributors
* mailing list at: https://lists.darkhorselinux.org/mailman/listinfo/dhlp-contributors
*/
#pragma once
#include <fstream>
@ -11,38 +41,116 @@
#include "LoggingLevels.hpp"
#include "DPMDefaults.hpp"
/**
* @class Logger
* @brief Provides logging capabilities for the DPM system
*
* Implements a configurable logging system that can write messages to
* both console and file outputs. Supports different log levels to
* control verbosity and includes automatic timestamp generation for
* log file entries.
*/
class Logger {
public:
// constructor
/**
* @brief Constructor
*
* Initializes a new Logger instance with default settings from DPMDefaults.
*/
Logger();
// destructor
/**
* @brief Destructor
*/
~Logger();
// Log method that accepts a string
/**
* @brief Logs a message with the specified log level
*
* Writes a log message to the console and optionally to a log file
* if the message level is less than or equal to the configured log level.
* Messages with levels FATAL, ERROR, or WARN are written to stderr,
* while others go to stdout. File logging includes timestamps.
*
* @param log_level The severity level of the message
* @param message The message to log
*/
void log(LoggingLevels log_level, const std::string& message);
// Configuration setters
/**
* @brief Sets the log file path
*
* Changes the file path where log messages are written when file
* logging is enabled. Ensures the log directory exists and is writable.
*
* @param log_file The path to the log file
*/
void setLogFile(const std::string& log_file);
/**
* @brief Enables or disables file logging
*
* Controls whether log messages are written to a file in addition
* to console output. If enabled, validates that the log file is writable.
*
* @param write_to_log true to enable file logging, false to disable
*/
void setWriteToLog(bool write_to_log);
/**
* @brief Sets the log level threshold
*
* Sets the maximum log level that will be processed. Messages with
* a level higher than this threshold will be ignored.
*
* @param log_level The new log level threshold
*/
void setLogLevel(LoggingLevels log_level);
// String to LoggingLevels conversion
/**
* @brief Converts a log level string to the corresponding enum value
*
* Parses a string representation of a log level (e.g., "INFO", "DEBUG")
* and returns the corresponding LoggingLevels enum value.
*
* @param level_str The string representation of the log level
* @param default_level The default level to return if parsing fails
* @return The corresponding LoggingLevels enum value
*/
static LoggingLevels stringToLogLevel(const std::string& level_str, LoggingLevels default_level = LoggingLevels::INFO);
// Convert LoggingLevels enum to string
/**
* @brief Converts a LoggingLevels enum value to its string representation
*
* Returns the string representation of a log level (e.g., "INFO", "DEBUG")
* for the given LoggingLevels enum value.
*
* @param level The LoggingLevels enum value
* @return The string representation of the log level
*/
static std::string LogLevelToString(LoggingLevels level);
private:
// the logging level to stay initialized to
/**
* @brief The current log level threshold
*/
LoggingLevels log_level;
// whether or not to log to file
/**
* @brief Whether to write log messages to a file
*/
bool log_to_file;
// log file path
/**
* @brief The path to the log file
*/
std::string log_file;
};
// Global logger instance
extern Logger g_logger;
/**
* @brief Global logger instance
*
* Provides a single instance of the Logger that can be accessed
* from anywhere in the application.
*/
extern Logger g_logger;

View File

@ -1,12 +1,48 @@
/**
* @file LoggingLevels.hpp
* @brief Defines log level enumeration for DPM logging system
*
* Provides a standardized set of logging levels used throughout the DPM system
* to classify messages by severity and control logging verbosity.
*
* @copyright Copyright (c) 2025 SILO GROUP LLC
* @author Chris Punches <chris.punches@silogroup.org>
*
* Part of the Dark Horse Linux Package Manager (DPM)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* For bug reports or contributions, please contact the dhlp-contributors
* mailing list at: https://lists.darkhorselinux.org/mailman/listinfo/dhlp-contributors
*/
#pragma once
extern "C" {
// Log level enum that will be accessible to modules
/**
* @enum LoggingLevels
* @brief Enumeration of logging severity levels
*
* Defines the various severity levels for log messages in the DPM system.
* Lower values represent higher severity. This allows for filtering log
* messages based on their importance.
*/
enum LoggingLevels {
FATAL = 0,
ERROR = 1,
WARN = 2,
INFO = 3,
DEBUG = 4
FATAL = 0, /**< Critical errors that cause immediate program termination */
ERROR = 1, /**< Errors that prevent an operation from completing but allow program to continue */
WARN = 2, /**< Warning conditions that don't prevent operation but indicate potential issues */
INFO = 3, /**< Informational messages about normal program operation */
DEBUG = 4 /**< Detailed debug information for troubleshooting */
};
}

View File

@ -42,29 +42,115 @@
#include "error.hpp"
#include "module_interface.hpp"
/**
* @class ModuleLoader
* @brief Handles dynamic loading and management of DPM modules
*
* Provides functionality for discovering, loading, validating, and executing
* DPM modules from shared object files. Ensures that modules conform to the
* required interface before allowing their execution.
*/
class ModuleLoader {
public:
// initializer
/**
* @brief Constructor
*
* Initializes a new ModuleLoader with the specified module path.
*
* @param module_path Directory path where DPM modules are located (defaults to /usr/lib/dpm/modules/)
*/
explicit ModuleLoader(std::string module_path = "/usr/lib/dpm/modules/");
/**
* @brief Lists available modules in the module path
*
* Populates a vector with the names of available modules found in
* the configured module path.
*
* @param modules Vector to populate with module names
* @return DPMErrorCategory indicating success or failure
*/
DPMErrorCategory list_available_modules(std::vector<std::string>& modules) const;
/**
* @brief Gets the configured module path
*
* Retrieves the directory path where modules are located.
*
* @param path Reference to store the module path
* @return DPMErrorCategory indicating success or failure
*/
DPMErrorCategory get_module_path(std::string& path) const;
// Load and execute methods
/**
* @brief Loads a module by name
*
* Attempts to dynamically load a module from the configured module path.
*
* @param module_name Name of the module to load
* @param module_handle Reference to store the loaded module handle
* @return DPMErrorCategory indicating success or failure
*/
DPMErrorCategory load_module(const std::string& module_name, void*& module_handle) const;
/**
* @brief Executes a module with the specified command
*
* Loads a module and executes its main entry point with the given command.
*
* @param module_name Name of the module to execute
* @param command Command string to pass to the module
* @return DPMErrorCategory indicating success or failure
*/
DPMErrorCategory execute_module(const std::string& module_name, const std::string& command) const;
// Get module version
/**
* @brief Gets a module's version information
*
* Retrieves the version string from a loaded module.
*
* @param module_handle Handle to a loaded module
* @param version Reference to store the version string
* @return DPMErrorCategory indicating success or failure
*/
DPMErrorCategory get_module_version(void* module_handle, std::string& version) const;
// Get module description
/**
* @brief Gets a module's description
*
* Retrieves the description string from a loaded module.
*
* @param module_handle Handle to a loaded module
* @param description Reference to store the description string
* @return DPMErrorCategory indicating success or failure
*/
DPMErrorCategory get_module_description(void* module_handle, std::string& description) const;
// Check if all required symbols from module_interface.hpp are exported by the module
/**
* @brief Validates a module's interface
*
* Checks if a loaded module exports all required symbols as defined
* in the module_interface.
*
* @param module_handle Handle to a loaded module
* @param missing_symbols Reference to store names of any missing required symbols
* @return DPMErrorCategory indicating success or failure
*/
DPMErrorCategory validate_module_interface(void* module_handle, std::vector<std::string>& missing_symbols) const;
// Helper method to check module path validity
/**
* @brief Checks module path validity
*
* Verifies that the configured module path exists, is a directory,
* and has the necessary permissions.
*
* @return DPMErrorCategory indicating success or failure
*/
DPMErrorCategory check_module_path() const;
private:
/**
* @brief Directory path where modules are located
*/
std::string _module_path;
};

View File

@ -41,16 +41,39 @@
#include "dpm_interface_helpers.hpp"
#include "Logger.hpp"
/*
*
* DPM Interface methods. These are wrappers of DPM functionality that are meant to handle user view, turning
* error codes into human-presentable information, etc. Features are defined internally, these will only ever be
* wrappers of existing features to provide the human/cli interface.
/**
* @defgroup dpm_interface DPM Interface Methods
* @brief Interface methods for the DPM command-line tool
*
* These functions provide the human-readable interface for the DPM utility,
* transforming error codes into user-friendly messages and implementing
* commands that report system information.
* @{
*/
// check if the module path exists
/**
* @brief Verifies that the module path exists and is accessible
*
* Checks if the configured module path exists, is a directory, and has
* the necessary read permissions. If any check fails, an appropriate
* error message is displayed.
*
* @param loader Reference to a ModuleLoader object that provides the module path
* @return 0 if the path exists and is accessible, 1 otherwise
*/
int main_check_module_path(const ModuleLoader& loader);
// list the modules
/**
* @brief Lists all available and valid DPM modules
*
* Retrieves and displays a formatted table of available DPM modules
* from the specified module path, including their versions and descriptions.
* Validates each module by checking for required symbols before including
* it in the list.
*
* @param loader Reference to a ModuleLoader object that provides access to modules
* @return 0 on success, 1 on failure
*/
int main_list_modules(const ModuleLoader& loader);
/** @} */ // end of dpm_interface group

View File

@ -38,13 +38,31 @@
#include "LoggingLevels.hpp"
#include "DPMDefaults.hpp"
// data structure for supplied arguments
/**
* @struct CommandArgs
* @brief Structure for storing parsed command-line arguments
*
* Contains fields for all command-line arguments that can be passed to
* the DPM utility, providing a structured way to access them throughout
* the application.
*/
struct CommandArgs {
std::string module_path;
std::string config_dir;
std::string module_name;
std::string command;
std::string module_path; /**< Path to the directory containing DPM modules */
std::string config_dir; /**< Path to the directory containing configuration files */
std::string module_name; /**< Name of the module to execute */
std::string command; /**< Command string to pass to the module */
};
// parse dpm cli arguments into a serialized structure
CommandArgs parse_args( int argc, char * argv[] );
/**
* @brief Parses command-line arguments into a CommandArgs structure
*
* Processes the arguments provided to DPM and organizes them into a
* CommandArgs structure for easier access. Handles options like
* --module-path, --config-dir, and --help, as well as module names
* and module-specific arguments.
*
* @param argc Number of command-line arguments
* @param argv Array of C-style strings containing the arguments
* @return A CommandArgs structure containing the parsed arguments
*/
CommandArgs parse_args(int argc, char* argv[]);

View File

@ -32,31 +32,52 @@
#include <iostream>
// global errors for the core DPM routing/execution component
/**
* @enum DPMErrorCategory
* @brief Defines error categories for the DPM system
*
* Enumeration of all possible error conditions that can occur during
* DPM operations, particularly related to module loading and execution.
*/
enum class DPMErrorCategory {
SUCCESS,
PATH_NOT_FOUND,
PATH_NOT_DIRECTORY,
PATH_TOO_LONG,
PERMISSION_DENIED,
MODULE_NOT_FOUND,
MODULE_NOT_LOADED,
MODULE_LOAD_FAILED,
INVALID_MODULE,
SYMBOL_NOT_FOUND,
SYMBOL_EXECUTION_FAILED,
UNDEFINED_ERROR
SUCCESS, /**< Operation completed successfully */
PATH_NOT_FOUND, /**< The specified path does not exist */
PATH_NOT_DIRECTORY, /**< The specified path exists but is not a directory */
PATH_TOO_LONG, /**< The specified path exceeds the system's path length limit */
PERMISSION_DENIED, /**< Insufficient permissions to access the path */
MODULE_NOT_FOUND, /**< The specified module was not found in the module path */
MODULE_NOT_LOADED, /**< Failed to load the module (e.g., before executing it) */
MODULE_LOAD_FAILED, /**< Dynamic loading of the module failed */
INVALID_MODULE, /**< The module does not conform to the required interface */
SYMBOL_NOT_FOUND, /**< A required symbol was not found in the loaded module */
SYMBOL_EXECUTION_FAILED, /**< Execution of a module function failed */
UNDEFINED_ERROR /**< An undefined or unexpected error occurred */
};
// A generic context object that can hold any error-specific data
// only DPMErrorCategory is required, all other fields are optional
/**
* @struct FlexDPMError
* @brief Error context structure for DPM operations
*
* Provides context information for errors that occur during DPM operations.
* Only the error field is required; other fields can be populated as needed
* depending on the specific error condition.
*/
typedef struct {
DPMErrorCategory error;
const char * module_name;
const char * module_path;
const char * message;
DPMErrorCategory error; /**< The error category (required) */
const char * module_name; /**< Name of the module involved in the error (optional) */
const char * module_path; /**< Path to the modules directory (optional) */
const char * message; /**< Additional error message or context (optional) */
// Add other potential fields as needed as all fields beyond error are optional
} FlexDPMError;
// shorthand for creating a FlexDPMError instance
FlexDPMError make_error( DPMErrorCategory error_category );
/**
* @brief Creates a new FlexDPMError instance with the specified error category
*
* Utility function to simplify the creation of FlexDPMError structures.
* Initializes a new error context with the given error category and
* sets all other fields to NULL.
*
* @param error_category The error category to assign to the new error context
* @return A FlexDPMError structure with the specified error category
*/
FlexDPMError make_error(DPMErrorCategory error_category);

View File

@ -33,21 +33,137 @@
#include <iostream>
#include "error.hpp"
// fatal error routing method
/**
* @brief Main error handler that dispatches to specific handlers
*
* Routes an error to the appropriate specialized handler based on the
* error category in the context. Validates required fields before calling
* the specialized handler.
*
* @param context Error context containing the error category and related information
* @return Exit code appropriate for the error condition (0 for success, non-zero for errors)
*/
int handle_error(FlexDPMError context);
// declare a required field
/**
* @brief Validates that a required field is present in the error context
*
* Checks if a field that is required for a specific error category is
* present in the error context. If the field is missing, outputs an
* error message and exits the program.
*
* @param context Error context to validate
* @param field_name Name of the field being validated (for error reporting)
* @param field_value Pointer to the field value
*/
void validate_field(FlexDPMError context, const char* field_name, const void* field_value);
// Individual error handler prototypes
/**
* @brief Handler for PATH_NOT_FOUND errors
*
* Reports that a specified path does not exist.
*
* @param context Error context with module_path field populated
* @return Exit code for the error condition
*/
int handle_path_not_found(FlexDPMError context);
/**
* @brief Handler for PATH_NOT_DIRECTORY errors
*
* Reports that a specified path exists but is not a directory.
*
* @param context Error context with module_path field populated
* @return Exit code for the error condition
*/
int handle_path_not_directory(FlexDPMError context);
/**
* @brief Handler for PATH_TOO_LONG errors
*
* Reports that a specified path exceeds the system's path length limit.
*
* @param context Error context with module_path field populated
* @return Exit code for the error condition
*/
int handle_path_too_long(FlexDPMError context);
/**
* @brief Handler for PERMISSION_DENIED errors
*
* Reports insufficient permissions to access a path.
*
* @param context Error context with module_path field populated
* @return Exit code for the error condition
*/
int handle_permission_denied(FlexDPMError context);
/**
* @brief Handler for MODULE_NOT_FOUND errors
*
* Reports that a specified module was not found in the module path.
*
* @param context Error context with module_name and module_path fields populated
* @return Exit code for the error condition
*/
int handle_module_not_found(FlexDPMError context);
/**
* @brief Handler for MODULE_NOT_LOADED errors
*
* Reports that a module could not be loaded.
*
* @param context Error context with module_name field populated
* @return Exit code for the error condition
*/
int handle_module_not_loaded(FlexDPMError context);
/**
* @brief Handler for MODULE_LOAD_FAILED errors
*
* Reports that dynamic loading of a module failed.
*
* @param context Error context with module_name field populated
* @return Exit code for the error condition
*/
int handle_module_load_failed(FlexDPMError context);
/**
* @brief Handler for INVALID_MODULE errors
*
* Reports that a module does not conform to the required interface.
*
* @param context Error context with module_name field populated
* @return Exit code for the error condition
*/
int handle_invalid_module(FlexDPMError context);
/**
* @brief Handler for SYMBOL_NOT_FOUND errors
*
* Reports that a required symbol was not found in a loaded module.
*
* @param context Error context with module_name field populated
* @return Exit code for the error condition
*/
int handle_symbol_not_found(FlexDPMError context);
/**
* @brief Handler for SYMBOL_EXECUTION_FAILED errors
*
* Reports that execution of a module function failed.
*
* @param context Error context with module_name field populated
* @return Exit code for the error condition
*/
int handle_symbol_execution_failed(FlexDPMError context);
int handle_undefined_error(FlexDPMError context);
/**
* @brief Handler for UNDEFINED_ERROR errors
*
* Reports an undefined or unexpected error.
*
* @param context Error context with optional module_name and message fields
* @return Exit code for the error condition
*/
int handle_undefined_error(FlexDPMError context);

View File

@ -38,13 +38,19 @@
#include "LoggingLevels.hpp"
#include "Logger.hpp"
/*
* Provides reserved symbol names we look for in modules.
/**
* @namespace module_interface
* @brief Namespace containing module interface definitions
*
* Provides reserved symbol names and interface definitions for DPM modules.
*/
// Define required symbols in one place
namespace module_interface {
// This is the single source of truth for required module symbols
/**
* @brief List of required symbols that every valid DPM module must export
*
* These function names must be exported by a module for the module to be
* considered valid and loadable by the DPM core system.
*/
static const std::vector<std::string> required_symbols = {
"dpm_module_execute",
"dpm_module_get_version",
@ -52,20 +58,67 @@ namespace module_interface {
};
}
// Common interface for all DPM modules
/**
* @defgroup module_interface Common Interface for DPM Modules
* @brief Functions that modules must implement and core functions available to modules
* @{
*/
extern "C" {
// Module must export this symbol to be considered valid
/**
* @brief Main entry point for module execution
*
* This function must be implemented by all modules and serves as the
* primary execution point when the module is invoked by DPM.
*
* @param command The command string to execute
* @param argc Number of arguments provided
* @param argv Array of argument strings
* @return 0 on success, non-zero on failure
*/
int dpm_module_execute(const char* command, int argc, char** argv);
// Module version information
/**
* @brief Provides module version information
*
* Returns a string containing the module's version information.
* This is displayed when listing available modules.
*
* @return String containing the module's version
*/
const char* dpm_module_get_version(void);
// Module description information
/**
* @brief Provides module description
*
* Returns a human-readable description of the module's functionality.
* This is displayed when listing available modules.
*
* @return String containing the module's description
*/
const char* dpm_get_description(void);
// Direct configuration access function
/**
* @brief Accesses configuration values
*
* Allows modules to retrieve configuration values from the DPM
* configuration system. Implemented by the DPM core and available
* to all modules.
*
* @param section The configuration section name
* @param key The configuration key within the section
* @return The configuration value as a string, or NULL if not found
*/
const char* dpm_get_config(const char* section, const char* key);
// Direct logging function
/**
* @brief Logs messages through the DPM logging system
*
* Allows modules to log messages using the centralized DPM logging
* system. Implemented by the DPM core and available to all modules.
*
* @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_log(int level, const char* message);
}
/** @} */

View File

@ -0,0 +1,137 @@
/**
* @file CommonModuleAPI.hpp
* @brief Common module interface for DPM modules
*
* Defines the required interface that all DPM modules must implement,
* including the function declarations and constants that every module needs.
*
* @copyright Copyright (c) 2025 SILO GROUP LLC
* @author Chris Punches <chris.punches@silogroup.org>
*
* Part of the Dark Horse Linux Package Manager (DPM)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* For bug reports or contributions, please contact the dhlp-contributors
* mailing list at: https://lists.darkhorselinux.org/mailman/listinfo/dhlp-contributors
*/
#pragma once
/**
* @brief Fatal log level constant
*
* Used for critical errors that require immediate attention and
* typically result in program termination.
*/
const int LOG_FATAL = 0;
/**
* @brief Error log level constant
*
* Used for error conditions that may allow the program to continue
* execution but indicate a failure in some operation.
*/
const int LOG_ERROR = 1;
/**
* @brief Warning log level constant
*
* Used for potentially harmful situations that don't affect normal
* program execution but may indicate problems.
*/
const int LOG_WARN = 2;
/**
* @brief Informational log level constant
*
* Used for general informational messages about program execution.
*/
const int LOG_INFO = 3;
/**
* @brief Debug log level constant
*
* Used for detailed debugging information during development or
* troubleshooting.
*/
const int LOG_DEBUG = 4;
// Required functions that every DPM module must implement
extern "C" {
/**
* @brief Required module execution entry point
*
* Main entry point that is called by the DPM core when the module
* is executed. Modules must implement this function to handle
* commands and perform their specific functionality.
*
* @param command The command string to execute
* @param argc Number of arguments
* @param argv Array of argument strings
* @return 0 on success, non-zero on failure
*/
int dpm_module_execute(const char* command, int argc, char** argv);
/**
* @brief Module version information function
*
* Returns the version information for the module. This information
* is displayed when listing available modules.
*
* @return A string containing the module's version
*/
const char* dpm_module_get_version(void);
/**
* @brief Module description function
*
* Returns a human-readable description of the module's functionality.
* This information is displayed when listing available modules.
*
* @return A string containing the module's description
*/
const char* dpm_get_description(void);
}
// DPM core functions available for modules to call
extern "C" {
/**
* @brief Configuration access function
*
* Allows modules to access DPM's configuration values by section and key.
*
* @param section The configuration section name
* @param key The configuration key within the section
* @return The configuration value as a string, or NULL if not found
*/
const char* dpm_get_config(const char* section, const char* key);
/**
* @brief Logging function
*
* Allows modules to log messages through DPM's logging system.
*
* @param level The log level (LOG_FATAL, LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DEBUG)
* @param message The message to log
*/
void dpm_log(int level, const char* message);
}
/**
* @brief DPM core version definition
*
* Defines the version string for the DPM core system.
*/
#define DPM_VERSION "0.1.0"

View File

@ -0,0 +1,37 @@
/**
* @file CommonModuleAPI.cpp
* @brief Implementation stub for DPM module interface
*
* This file serves primarily as a documentation reference for the module
* interface. The actual implementations of dpm_get_config and dpm_log are
* provided by the DPM core, while dpm_module_execute, dpm_module_get_version,
* and dpm_get_description must be implemented by each module.
*
* @copyright Copyright (c) 2025 SILO GROUP LLC
* @author Chris Punches <chris.punches@silogroup.org>
*
* Part of the Dark Horse Linux Package Manager (DPM)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* For bug reports or contributions, please contact the dhlp-contributors
* mailing list at: https://lists.darkhorselinux.org/mailman/listinfo/dhlp-contributors
*/
#include "module.hpp"
/**
* @note The implementation of dpm_get_config and dpm_log are provided by the DPM core.
* Each module must implement dpm_module_execute, dpm_module_get_version, and dpm_get_description.
*/

View File

@ -0,0 +1,119 @@
/**
* @file infoFuncs.hpp
* @brief Header file for the info module support functions
*
* Defines functions and enumerations for the info module which provides
* information about the DPM system, including version, system details,
* and configuration information.
*
* @copyright Copyright (c) 2025 SILO GROUP LLC
* @author Chris Punches <chris.punches@silogroup.org>
*
* Part of the Dark Horse Linux Package Manager (DPM)
*/
#pragma once
#include <string>
#include <cstring>
#include <fstream>
#include <sys/utsname.h>
#include "dpmdk/include/CommonModuleAPI.hpp"
/**
* @enum Command
* @brief Enumeration of supported commands for the info module
*/
enum Command {
CMD_UNKNOWN, /**< Unknown or unsupported command */
CMD_HELP, /**< Display help information */
CMD_VERSION, /**< Display version information */
CMD_SYSTEM, /**< Display system information */
CMD_CONFIG /**< Display configuration information */
};
/**
* @brief Detects the system architecture
*
* Uses the uname system call to determine the current system architecture.
*
* @return String representation of the system architecture
*/
std::string detect_architecture();
/**
* @brief Detects the operating system information
*
* Uses the uname system call to determine the OS, and on Linux systems,
* attempts to get distribution information from /etc/os-release.
*
* @return Detailed string of the operating system
*/
std::string detect_os();
/**
* @brief Handler for the help command
*
* Displays information about available commands in the info module.
*
* @param argc Number of arguments
* @param argv Array of arguments
* @return 0 on success, non-zero on failure
*/
int cmd_help(int argc, char** argv);
/**
* @brief Handler for the version command
*
* Displays DPM version information, build date, and build time.
*
* @param argc Number of arguments
* @param argv Array of arguments
* @return 0 on success, non-zero on failure
*/
int cmd_version(int argc, char** argv);
/**
* @brief Handler for the system command
*
* Displays information about the system on which DPM is running,
* including OS details and architecture.
*
* @param argc Number of arguments
* @param argv Array of arguments
* @return 0 on success, non-zero on failure
*/
int cmd_system(int argc, char** argv);
/**
* @brief Handler for the config command
*
* Displays configuration information about the DPM system.
*
* @param argc Number of arguments
* @param argv Array of arguments
* @return 0 on success, non-zero on failure
*/
int cmd_config(int argc, char** argv);
/**
* @brief Handler for unknown commands
*
* Displays an error message for unrecognized commands.
*
* @param command The unrecognized command string
* @param argc Number of arguments
* @param argv Array of arguments
* @return 1 to indicate failure
*/
int cmd_unknown(const char* command, int argc, char** argv);
/**
* @brief Parses a command string into a Command enum value
*
* Converts a command string to the appropriate Command enum value
* for internal routing.
*
* @param cmd_str The command string to parse
* @return The corresponding Command enum value
*/
Command parse_command(const char* cmd_str);

111
modules/info/info.cpp Normal file
View File

@ -0,0 +1,111 @@
/**
* @file info.cpp
* @brief Example DPM info module implementation
*
* Implements a simple DPM module that provides information about the DPM system.
* This module demonstrates how to implement the required module interface and
* interact with the DPM core through configuration functions.
*
* @copyright Copyright (c) 2025 SILO GROUP LLC
* @author Chris Punches <chris.punches@silogroup.org>
*
* Part of the Dark Horse Linux Package Manager (DPM)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* For bug reports or contributions, please contact the dhlp-contributors
* mailing list at: https://lists.darkhorselinux.org/mailman/listinfo/dhlp-contributors
*/
// Implementation of the info module
// This module provides information about the DPM system
#include <string>
#include <cstring>
#include <vector>
#include <fstream>
#include <sys/utsname.h>
#include "dpmdk/include/CommonModuleAPI.hpp"
#include "include/infoFuncs.hpp"
/**
* @def MODULE_VERSION
* @brief Version information for the info module
*
* Defines the version string that will be returned by dpm_module_get_version()
*/
#define MODULE_VERSION "0.1.0"
/**
* @brief Returns the module version string
*
* Required implementation of the DPM module interface that provides
* version information for the info module.
*
* @return Const char pointer to the module version string
*/
extern "C" const char* dpm_module_get_version(void) {
return MODULE_VERSION;
}
/**
* @brief Returns the module description string
*
* Required implementation of the DPM module interface that provides
* a human-readable description of the info module and its functionality.
*
* @return Const char pointer to the module description string
*/
extern "C" const char* dpm_get_description(void) {
return "DPM Info Module - Provides information about the DPM system";
}
/**
* @brief Main entry point for the info module
*
* Required implementation of the DPM module interface that serves as the
* primary execution point for the module. Parses the command and routes
* execution to the appropriate handler function.
*
* @param command The command string to execute
* @param argc Number of arguments
* @param argv Array of argument strings
* @return 0 on success, non-zero on failure
*/
extern "C" int dpm_module_execute(const char* command, int argc, char** argv) {
dpm_log(LOG_INFO, "Info module execution started");
Command cmd = parse_command(command);
switch (cmd) {
case CMD_VERSION:
return cmd_version(argc, argv);
case CMD_SYSTEM:
return cmd_system(argc, argv);
case CMD_CONFIG:
return cmd_config(argc, argv);
case CMD_HELP:
return cmd_help(argc, argv);
case CMD_UNKNOWN:
default:
return cmd_unknown(command, argc, argv);
}
}

View File

@ -1,80 +1,22 @@
/**
* @file info.cpp
* @brief Example DPM info module implementation
* @file infoFuncs.cpp
* @brief Implementation of the info module support functions
*
* Implements a simple DPM module that provides information about the DPM system.
* This module demonstrates how to implement the required module interface and
* interact with the DPM core through configuration functions.
* Implements functions for the info module that provide information about
* the DPM system, including version, system details, and configuration.
*
* @copyright Copyright (c) 2025 SILO GROUP LLC
* @author Chris Punches <chris.punches@silogroup.org>
*
* Part of the Dark Horse Linux Package Manager (DPM)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* For bug reports or contributions, please contact the dhlp-contributors
* mailing list at: https://lists.darkhorselinux.org/mailman/listinfo/dhlp-contributors
*/
// Implementation of the info module
// This module provides information about the DPM system
#include "infoFuncs.hpp"
#include <string>
#include <cstring>
#include <vector>
#include <fstream>
#include <sys/utsname.h>
// Define version macros
#define MODULE_VERSION "0.1.0"
#define DPM_VERSION "0.1.0"
// Define constants for logging levels
// These must match.
const int LOG_FATAL = 0;
const int LOG_ERROR = 1;
const int LOG_WARN = 2;
const int LOG_INFO = 3;
const int LOG_DEBUG = 4;
// Declaration of the DPM config function we want to call
extern "C" const char* dpm_get_config(const char* section, const char* key);
// Declaration of the DPM log function
extern "C" void dpm_log(int level, const char* message);
// Version information
extern "C" const char* dpm_module_get_version(void) {
return MODULE_VERSION;
}
// Module description
extern "C" const char* dpm_get_description(void) {
return "DPM Info Module - Provides information about the DPM system";
}
// Command enum for switch case
enum Command {
CMD_UNKNOWN,
CMD_HELP,
CMD_VERSION,
CMD_SYSTEM,
CMD_CONFIG
};
// Function to detect architecture using uname
/**
* Function to detect architecture using uname
*/
std::string detect_architecture() {
struct utsname system_info;
@ -86,7 +28,9 @@ std::string detect_architecture() {
return system_info.machine;
}
// Function to detect OS
/**
* Function to detect OS details
*/
std::string detect_os() {
struct utsname system_info;
@ -135,7 +79,9 @@ std::string detect_os() {
return os;
}
// Command handler functions
/**
* Command handler for help command
*/
int cmd_help(int argc, char** argv) {
dpm_log(LOG_INFO, "DPM Info Module - Provides information about the DPM system");
dpm_log(LOG_INFO, "Available commands:");
@ -146,6 +92,9 @@ int cmd_help(int argc, char** argv) {
return 0;
}
/**
* Command handler for version command
*/
int cmd_version(int argc, char** argv) {
std::string version_msg = "DPM Version: ";
version_msg += DPM_VERSION;
@ -162,6 +111,9 @@ int cmd_version(int argc, char** argv) {
return 0;
}
/**
* Command handler for system command
*/
int cmd_system(int argc, char** argv) {
dpm_log(LOG_INFO, "System Information:");
@ -176,6 +128,9 @@ int cmd_system(int argc, char** argv) {
return 0;
}
/**
* Command handler for config command
*/
int cmd_config(int argc, char** argv) {
const char* module_path = dpm_get_config("modules", "module_path");
@ -188,6 +143,9 @@ int cmd_config(int argc, char** argv) {
return 0;
}
/**
* Command handler for unknown commands
*/
int cmd_unknown(const char* command, int argc, char** argv) {
std::string msg = "Unknown command: ";
msg += (command ? command : "");
@ -196,7 +154,9 @@ int cmd_unknown(const char* command, int argc, char** argv) {
return 1;
}
// Function to parse command string to enum
/**
* Function to parse command string to enum
*/
Command parse_command(const char* cmd_str) {
if (cmd_str == nullptr || strlen(cmd_str) == 0) {
return CMD_HELP;
@ -217,28 +177,3 @@ Command parse_command(const char* cmd_str) {
return CMD_UNKNOWN;
}
// Main entry point that will be called by DPM
extern "C" int dpm_module_execute(const char* command, int argc, char** argv) {
dpm_log(LOG_INFO, "Info module execution started");
Command cmd = parse_command(command);
switch (cmd) {
case CMD_VERSION:
return cmd_version(argc, argv);
case CMD_SYSTEM:
return cmd_system(argc, argv);
case CMD_CONFIG:
return cmd_config(argc, argv);
case CMD_HELP:
return cmd_help(argc, argv);
case CMD_UNKNOWN:
default:
return cmd_unknown(command, argc, argv);
}
}

View File

@ -41,24 +41,6 @@
* Also includes helpers related to the CLI.
*/
/**
* Verify that the module path exists and is accessible.
*
* This function checks if the configured module path exists, is a directory,
* and has the necessary read permissions.
*
* @param loader Reference to a ModuleLoader object that provides the module path
*
* @return 0 if the path exists and is accessible, 1 otherwise
*
* The function performs the following checks:
* 1. Retrieves the module path from the loader
* 2. Verifies that the path exists in the filesystem
* 3. Confirms that the path is a directory
* 4. Checks that the directory has read permissions
*
* If any check fails, an appropriate error message is displayed to stderr.
*/
int main_check_module_path(const ModuleLoader& loader)
{
std::string path;
@ -88,29 +70,7 @@ int main_check_module_path(const ModuleLoader& loader)
return 0;
}
/**
* List all available and valid DPM modules.
*
* This function retrieves and displays a formatted table of available DPM modules
* from the specified module path, including their versions and descriptions.
*
* @param loader Reference to a ModuleLoader object that provides access to modules
*
* @return 0 on success, 1 on failure
*
* The function performs the following operations:
* 1. Gets the configured module path from the loader
* 2. Retrieves a list of all potential modules in that path
* 3. Validates each module by checking for required symbols
* 4. Collects version and description information from valid modules
* 5. Formats and displays the information in a tabular format
*
* If no modules are found or if no valid modules are found, appropriate
* messages are displayed.
*
* Modules are considered valid if they expose all required interface
* symbols as defined in module_interface.hpp.
*/
int main_list_modules(const ModuleLoader& loader)
{
// initialize an empty modules list

View File

@ -30,32 +30,6 @@
#include "dpm_interface_helpers.hpp"
/**
* Parse command line arguments for DPM.
*
* This function parses the command line arguments provided to DPM
* and builds a CommandArgs structure containing the parsed values.
*
* @param argc The number of arguments provided to the program
* @param argv Array of C-style strings containing the arguments
*
* @return CommandArgs structure containing the parsed command line arguments
*
* The function handles the following arguments:
* - ``-m, --module-path PATH``: Sets the directory path where DPM modules are located
* - ``-c, --config-dir PATH``: Sets the directory path where DPM configuration files are located
* - ``-h, --help``: Displays a help message and exits
*
* Additional arguments are processed as follows:
* - First non-option argument is treated as the module name
* - All remaining arguments are combined into a single command string for the module
*
* If the argument contains spaces, it will be quoted in the command string.
*
* If no module name is provided, the module_name field will be empty.
*/
CommandArgs parse_args(int argc, char* argv[])
{
CommandArgs args;

View File

@ -29,28 +29,10 @@
#include "module_interface.hpp"
/**
* @brief Function that provides direct access to configuration values
*
* This function allows modules to get configuration values directly.
* It returns the string value from the configuration or nullptr if not found.
*
* @param section The configuration section name
* @param key The configuration key within the section
* @return The configuration value or nullptr if not found
*/
extern "C" const char* dpm_get_config(const char* section, const char* key) {
return g_config_manager.getConfigValue(section, key);
}
/**
* @brief Direct logging function for modules
*
* This function allows modules to log messages directly through the DPM logger.
*
* @param level The log level as an integer (0=FATAL, 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG)
* @param message The message to log
*/
extern "C" void dpm_log(int level, const char* message) {
if (!message) {
return;
@ -80,4 +62,4 @@ extern "C" void dpm_log(int level, const char* message) {
}
g_logger.log(log_level, message);
}
}