modules now can access config entries in a new conf.d dir pulled by DPM core (ini file format)

master
Chris Punches 2025-03-02 00:29:26 -05:00
parent 6220653d10
commit 299b8dd989
17 changed files with 775 additions and 138 deletions

View File

@ -6,16 +6,15 @@ set(CMAKE_CXX_STANDARD 20)
# Create modules directory
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/modules)
add_executable(
dpm
add_executable(dpm
src/dpm.cpp
src/ModuleLoader.cpp
src/dpm_interface.cpp
src/error.cpp
include/dpm_interface_helpers.hpp
src/dpm_interface_helpers.cpp
src/handlers.cpp
src/module_interface.cpp
src/ConfigManager.cpp
)
target_include_directories(dpm PRIVATE include)

88
include/ConfigManager.hpp Normal file
View File

@ -0,0 +1,88 @@
/**
* @file ConfigManager.hpp
* @brief Configuration management system for the DPM utility
*
* Defines the ConfigManager class which is responsible for loading, parsing,
* and providing access to configuration values from INI-style files in the
* /etc/dpm/conf.d/ directory. Supports the configuration needs of both the
* DPM core and its modules.
*
* @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 <string>
#include <map>
#include <vector>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <optional>
#include <string.h>
#include <dirent.h>
class ConfigManager {
public:
// Constructor
ConfigManager(const std::string& config_dir = "/etc/dpm/conf.d/");
// Load all configuration files from the config directory
bool loadConfigurations();
// Get configuration values with type conversion
const char* getConfigValue(const char* section, const char* key) const;
std::string getConfigString(const char* section, const char* key, const std::string& defaultValue = "") const;
int getConfigInt(const char* section, const char* key, int defaultValue = 0) const;
double getConfigDouble(const char* section, const char* key, double defaultValue = 0.0) const;
bool getConfigBool(const char* section, const char* key, bool defaultValue = false) const;
// Check if configuration directory exists
bool configDirExists() const;
// Check if a configuration key exists
bool hasConfigKey(const char* section, const char* key) const;
private:
// Default section name to use when none is specified
static constexpr const char* DEFAULT_SECTION = "MAIN";
// Parse a single configuration file
bool parseConfigFile(const std::filesystem::path& config_file);
// Trim whitespace from a string
std::string trimWhitespace(const std::string& str) const;
// Find a key in the given section or in the default section
std::optional<std::reference_wrapper<const std::string>> findConfigValue(const std::string& section, const std::string& key) const;
// Configuration directory path
std::string _config_dir;
// 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;

View File

@ -1,31 +1,31 @@
/**
* @file ModuleLoader.hpp
* @brief Dynamic module loading and management for DPM
*
* Defines the ModuleLoader class which is responsible for finding, loading,
* validating, and executing DPM modules. It handles the dynamic loading of
* shared objects and ensures they conform to the expected module interface.
*
* @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
* @file ModuleLoader.hpp
* @brief Dynamic module loading and management for DPM
*
* Defines the ModuleLoader class which is responsible for finding, loading,
* validating, and executing DPM modules. It handles the dynamic loading of
* shared objects and ensures they conform to the expected module interface.
*
* @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
@ -33,16 +33,15 @@
#include <string>
#include <vector>
#include <filesystem>
#include <dlfcn.h>
#include <iostream>
#include <cstring>
#include <dlfcn.h>
#include <dirent.h>
#include <sys/stat.h>
#include "error.hpp"
#include "module_interface.hpp"
class ModuleLoader {
public:
// initializer

View File

@ -1,5 +1,5 @@
/**
* @file dpm_interface.hpp
* @file dpm_interface.hpp
* @brief Interface declarations for the DPM command-line functionality
*
* Defines the public interface methods that provide human-readable interaction
@ -30,11 +30,11 @@
#pragma once
#include <iostream>
#include <getopt.h>
#include <vector>
#include <dlfcn.h>
#include <iomanip>
#include <filesystem>
#include <dlfcn.h>
#include <getopt.h>
#include "error.hpp"
#include "ModuleLoader.hpp"

View File

@ -1,5 +1,5 @@
/**
* @file dpm_interface_helpers.hpp
* @file dpm_interface_helpers.hpp
* @brief Helper functions for DPM command-line interface
*
* Provides utility functions for command-line argument parsing and
@ -29,6 +29,7 @@
*/
#pragma once
#include <string>
#include <iostream>
#include <getopt.h>

View File

@ -1,5 +1,5 @@
/**
* @file error.hpp
* @file error.hpp
* @brief Error handling system for the DPM utility
*
* Defines the error categories, error context structure, and utility
@ -29,6 +29,7 @@
*/
#pragma once
#include <iostream>
// global errors for the core DPM routing/execution component
@ -59,4 +60,3 @@ typedef struct {
// shorthand for creating a FlexDPMError instance
FlexDPMError make_error( DPMErrorCategory error_category );

View File

@ -1,5 +1,5 @@
/**
* @file handlers.hpp
* @file handlers.hpp
* @brief Error handling functions for the DPM system
*
* Defines specialized handler functions for each error category in the DPM
@ -29,8 +29,8 @@
*/
#pragma once
#include <iostream>
#include <iostream>
#include "error.hpp"
// fatal error routing method

View File

@ -1,36 +1,41 @@
/**
* @file module_interface.hpp
* @brief Defines the interface for DPM modules
*
* Establishes the required symbols and common interface that all DPM modules
* must implement to be loadable and executable by the core DPM system.
* This forms the contract between the main DPM application and its modules.
*
* @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
* @file module_interface.hpp
* @brief Defines the interface for DPM modules
*
* Establishes the required symbols and common interface that all DPM modules
* must implement to be loadable and executable by the core DPM system.
* This forms the contract between the main DPM application and its modules.
*
* @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 <string>
#include <vector>
#include <iostream>
#include "ConfigManager.hpp"
/*
* Provides reserved symbol names we look for in modules.
@ -59,4 +64,7 @@ extern "C" {
// Callback function exposed by DPM core for modules to use
int dpm_core_callback(const char* action, const char* data);
}
// Direct configuration access function
const char* dpm_get_config(const char* section, const char* key);
}

View File

@ -1,11 +1,40 @@
// info.cpp
/**
* @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
*/
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
// Declaration of the DPM core function we want to call
extern "C" int dpm_core_callback(const char* action, const char* data);
// Declaration of the DPM config function we want to call
extern "C" const char* dpm_get_config(const char* section, const char* key);
// Implementation of the info module
// This module provides information about the DPM system
@ -29,9 +58,8 @@ extern "C" int dpm_module_execute(const char* command, int argc, char** argv) {
std::cout << "Available commands:\n";
std::cout << " version - Display DPM version information\n";
std::cout << " system - Display system information\n";
std::cout << " config - Display configuration information\n";
std::cout << " help - Display this help message\n";
dpm_core_callback("log", "No command specified, displayed help");
return 0;
}
@ -39,18 +67,14 @@ extern "C" int dpm_module_execute(const char* command, int argc, char** argv) {
std::string cmd(command);
if (cmd == "version") {
dpm_core_callback("log", "Executing 'version' command");
std::cout << "DPM Version: 0.1.0\n";
std::cout << "Build Date: " << __DATE__ << "\n";
std::cout << "Build Time: " << __TIME__ << "\n";
return 0;
}
else if (cmd == "system") {
dpm_core_callback("log", "Executing 'system' command");
// Request config information
dpm_core_callback("get_config", "system.arch");
// Request config information using the direct method
const char* module_path = dpm_get_config("modules", "module_path");
std::cout << "System Information:\n";
std::cout << " OS: "
@ -77,24 +101,29 @@ extern "C" int dpm_module_execute(const char* command, int argc, char** argv) {
"Unknown"
#endif
<< "\n";
std::cout << " Module Path: " << (module_path ? module_path : "Not configured") << "\n";
return 0;
}
else if (cmd == "config") {
// Retrieve module path configuration
const char* module_path = dpm_get_config("modules", "module_path");
std::cout << "Configuration Information:\n";
std::cout << " Module Path: " << (module_path ? module_path : "Not configured") << "\n";
return 0;
}
else if (cmd == "help") {
dpm_core_callback("log", "Executing 'help' command");
std::cout << "DPM Info Module - Provides information about the DPM system\n";
std::cout << "Available commands:\n";
std::cout << " version - Display DPM version information\n";
std::cout << " system - Display system information\n";
std::cout << " config - Display configuration information\n";
std::cout << " help - Display this help message\n";
return 0;
}
else {
std::string error_msg = "Unknown command: " + cmd;
dpm_core_callback("log", error_msg.c_str());
std::cerr << "Unknown command: " << cmd << "\n";
std::cerr << "Run 'dpm info help' for a list of available commands\n";
return 1;
}
}
}

307
src/ConfigManager.cpp Normal file
View File

@ -0,0 +1,307 @@
/**
* @file ConfigManager.cpp
* @brief Implementation of the configuration management system
*
* Implements the ConfigManager class methods for loading and parsing configuration
* files from the /etc/dpm/conf.d/ directory, and providing access to configuration
* values through a consistent interface. Handles INI-style files with sections
* and key-value pairs.
*
* @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 "ConfigManager.hpp"
// Global configuration manager instance
ConfigManager g_config_manager;
ConfigManager::ConfigManager(const std::string& config_dir)
: _config_dir(config_dir)
{
// Ensure the config directory ends with a slash
if (!_config_dir.empty() && _config_dir.back() != '/') {
_config_dir += '/';
}
}
std::string ConfigManager::trimWhitespace(const std::string& str) const
{
const std::string whitespace = " \t\n\r\f\v";
size_t start = str.find_first_not_of(whitespace);
// Return empty string if there are only whitespace characters
if (start == std::string::npos) {
return "";
}
size_t end = str.find_last_not_of(whitespace);
return str.substr(start, end - start + 1);
}
bool ConfigManager::configDirExists() const
{
DIR* dir = opendir(_config_dir.c_str());
if (dir) {
closedir(dir);
return true;
}
return false;
}
bool ConfigManager::loadConfigurations()
{
// Clear existing configuration data
_config_data.clear();
// Ensure DEFAULT_SECTION exists in the configuration data
_config_data[DEFAULT_SECTION] = std::map<std::string, std::string>();
// Check if the configuration directory exists
if (!configDirExists()) {
std::cerr << "Warning: Configuration directory does not exist: " << _config_dir << std::endl;
return false;
}
// Open the directory
DIR* dir = opendir(_config_dir.c_str());
if (!dir) {
std::cerr << "Error: Failed to open configuration directory: " << _config_dir << std::endl;
return false;
}
bool success = true;
struct dirent* entry;
// Iterate through directory entries
while ((entry = readdir(dir)) != NULL) {
std::string filename = entry->d_name;
// Skip . and .. directories
if (filename == "." || filename == "..") {
continue;
}
// Check if file ends with .conf
if (filename.length() >= 5 &&
filename.substr(filename.length() - 5) == ".conf") {
std::string filepath = _config_dir + filename;
if (!parseConfigFile(filepath)) {
std::cerr << "Warning: Failed to parse config file: " << filepath << std::endl;
success = false;
}
}
}
closedir(dir);
return success;
}
bool ConfigManager::parseConfigFile(const std::filesystem::path& config_file)
{
std::ifstream file(config_file);
if (!file.is_open()) {
std::cerr << "Error: Could not open config file: " << config_file << std::endl;
return false;
}
std::string line;
std::string current_section = DEFAULT_SECTION;
// Process each line in the file
while (std::getline(file, line)) {
// Trim whitespace
line = trimWhitespace(line);
// Skip empty lines and comments
if (line.empty() || line[0] == '#' || line[0] == ';') {
continue;
}
// Check for section header
if (line[0] == '[' && line.back() == ']') {
current_section = line.substr(1, line.length() - 2);
// Trim whitespace from section name
current_section = trimWhitespace(current_section);
// Skip empty section names, use default instead
if (current_section.empty()) {
current_section = DEFAULT_SECTION;
}
// Ensure section exists in the map
if (_config_data.find(current_section) == _config_data.end()) {
_config_data[current_section] = std::map<std::string, std::string>();
}
continue;
}
// Parse key-value pair
size_t delimiter_pos = line.find('=');
if (delimiter_pos != std::string::npos) {
std::string key = trimWhitespace(line.substr(0, delimiter_pos));
std::string value = trimWhitespace(line.substr(delimiter_pos + 1));
// Skip empty keys
if (key.empty()) {
continue;
}
// Store in configuration map
_config_data[current_section][key] = value;
}
}
file.close();
return true;
}
std::optional<std::reference_wrapper<const std::string>> ConfigManager::findConfigValue(
const std::string& section, const std::string& key) const
{
// Check if section exists
auto section_it = _config_data.find(section);
if (section_it != _config_data.end()) {
// Check if key exists in section
auto key_it = section_it->second.find(key);
if (key_it != section_it->second.end()) {
return key_it->second;
}
}
// If section is not DEFAULT_SECTION and key was not found,
// try looking in the DEFAULT_SECTION
if (section != DEFAULT_SECTION) {
auto default_section_it = _config_data.find(DEFAULT_SECTION);
if (default_section_it != _config_data.end()) {
auto default_key_it = default_section_it->second.find(key);
if (default_key_it != default_section_it->second.end()) {
return default_key_it->second;
}
}
}
// Key not found in specified section or DEFAULT_SECTION
return std::nullopt;
}
bool ConfigManager::hasConfigKey(const char* section, const char* key) const
{
if (!key) {
return false;
}
// Use the default section if none is provided
std::string section_str = section ? section : DEFAULT_SECTION;
std::string key_str(key);
return findConfigValue(section_str, key_str).has_value();
}
const char* ConfigManager::getConfigValue(const char* section, const char* key) const
{
if (!key) {
return nullptr;
}
// Use the default section if none is provided
std::string section_str = section ? section : DEFAULT_SECTION;
std::string key_str(key);
auto value_opt = findConfigValue(section_str, key_str);
if (value_opt.has_value()) {
return value_opt.value().get().c_str();
}
return nullptr;
}
std::string ConfigManager::getConfigString(const char* section, const char* key, const std::string& defaultValue) const
{
const char* value = getConfigValue(section, key);
return value ? value : defaultValue;
}
int ConfigManager::getConfigInt(const char* section, const char* key, int defaultValue) const
{
const char* value = getConfigValue(section, key);
if (!value) {
return defaultValue;
}
char* endptr;
int result = strtol(value, &endptr, 10);
// If conversion failed or didn't consume the entire string, return default
if (*endptr != '\0') {
return defaultValue;
}
return result;
}
double ConfigManager::getConfigDouble(const char* section, const char* key, double defaultValue) const
{
const char* value = getConfigValue(section, key);
if (!value) {
return defaultValue;
}
char* endptr;
double result = strtod(value, &endptr);
// If conversion failed or didn't consume the entire string, return default
if (*endptr != '\0') {
return defaultValue;
}
return result;
}
bool ConfigManager::getConfigBool(const char* section, const char* key, bool defaultValue) const
{
const char* value = getConfigValue(section, key);
if (!value) {
return defaultValue;
}
std::string value_lower = value;
std::transform(value_lower.begin(), value_lower.end(), value_lower.begin(),
[](unsigned char c) { return std::tolower(c); });
// Check for common true values
if (value_lower == "true" || value_lower == "yes" || value_lower == "1" ||
value_lower == "on" || value_lower == "enabled") {
return true;
}
// Check for common false values
if (value_lower == "false" || value_lower == "no" || value_lower == "0" ||
value_lower == "off" || value_lower == "disabled") {
return false;
}
// If not recognized, return default
return defaultValue;
}

View File

@ -1,3 +1,33 @@
/**
* @file ModuleLoader.cpp
* @brief Implementation of dynamic module loading and management for DPM
*
* Implements the ModuleLoader class methods for finding, loading, validating,
* and executing DPM modules. It handles the dynamic loading of shared objects
* and ensures they conform to the expected module interface.
*
* @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 "ModuleLoader.hpp"
namespace fs = std::filesystem;

View File

@ -1,5 +1,5 @@
/**
* @file dpm.cpp
* @file dpm.cpp
* @brief Main entry point for the Dark Horse Package Manager (DPM)
*
* Implements the core command-line interface and module routing functionality
@ -28,13 +28,14 @@
*/
#include <iostream>
#include <handlers.hpp>
#include <dlfcn.h>
#include <handlers.hpp>
#include "ModuleLoader.hpp"
#include "dpm_interface.hpp"
#include "dpm_interface_helpers.hpp"
#include "error.hpp"
#include "ConfigManager.hpp"
/*
* DPM serves three functions:
@ -59,19 +60,44 @@ int default_behavior(const ModuleLoader& loader)
* @param argv Array of C-style strings containing the arguments
* @return Exit code indicating success (0) or failure (non-zero)
*/
int main( int argc, char* argv[] )
int main(int argc, char* argv[])
{
// Load configuration files
if (!g_config_manager.loadConfigurations()) {
std::cerr << "Warning: Some configuration files could not be loaded." << std::endl;
// Continue execution, as we might be able to use default values
}
// process the arguments suppplied to DPM and provide
// an object that contains them for command and routing
// processing
auto args = parse_args( argc, argv );
// processing - this will include any module_path from CLI
auto args = parse_args(argc, argv);
// create a module loader object at the supplied or default path
ModuleLoader loader( args.module_path );
// Determine the module path (CLI arg > config > default)
std::string module_path;
// If CLI argument was provided, use it
if (!args.module_path.empty()) {
module_path = args.module_path;
}
// Otherwise, check configuration file
else {
const char* config_module_path = g_config_manager.getConfigValue("modules", "module_path");
if (config_module_path) {
module_path = config_module_path;
}
// Finally, use default if nothing else is available
else {
module_path = "/usr/lib/dpm/modules/";
}
}
// create a module loader object with the determined path
ModuleLoader loader(module_path);
// check the module path for the loader object
int path_check_result = main_check_module_path( loader );
if ( path_check_result != 0 ) {
int path_check_result = main_check_module_path(loader);
if (path_check_result != 0) {
// exit if there's an error and ensure
// it has an appropriate return code
return 1;
@ -79,8 +105,8 @@ int main( int argc, char* argv[] )
// if no module is provided to execute, then trigger the default
// dpm behaviour
if ( args.module_name.empty() ) {
return default_behavior( loader );
if (args.module_name.empty()) {
return default_behavior(loader);
}
// execute the module
@ -94,5 +120,5 @@ int main( int argc, char* argv[] )
result.module_path = extracted_path.c_str();
// pair result with a message and exit with the appropriate error code
return handle_error( result );
}
return handle_error(result);
}

View File

@ -1,3 +1,33 @@
/**
* @file dpm_interface.cpp
* @brief Implementation of DPM command-line interface functions
*
* Implements the functions that provide human-readable interaction with the
* DPM core functionality, including module path validation and module listing
* capabilities.
*
* @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 "dpm_interface.hpp"
/*
@ -177,5 +207,3 @@ int main_list_modules(const ModuleLoader& loader)
return 0;
}

View File

@ -1,3 +1,33 @@
/**
* @file dpm_interface_helpers.cpp
* @brief Implementation of helper functions for DPM command-line interface
*
* Implements utility functions for command-line argument parsing and provides
* data structures for representing command arguments in a structured format.
* These helpers are used by the main DPM interface to process user input.
*
* @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 "dpm_interface_helpers.hpp"
/**
@ -26,7 +56,7 @@
CommandArgs parse_args(int argc, char* argv[])
{
CommandArgs args;
args.module_path = "/usr/lib/dpm/modules/"; // Set to same default as ModuleLoader
args.module_path = ""; // Start with empty path to allow for config fallback
static struct option long_options[] = {
{"module-path", required_argument, 0, 'm'},
@ -42,11 +72,10 @@ CommandArgs parse_args(int argc, char* argv[])
args.module_path = optarg;
break;
case 'h':
std::cout << "Usage: dpm [options] [module-name] [module args...]\n\n"
std::cout << "Usage: dpm [options] [module-name] [module args...] [module-command] [command-args]\n\n"
<< "Options:\n\n"
<< " -m, --module-path PATH Path to DPM modules\n"
<< " -h, --help Show this help message\n\n"
<< "If no module is specified, available modules will be listed.\n\n";
<< " -m, --module-path PATH Path to DPM modules (overrides config)\n"
<< " -h, --help Show this help message\n\n";
exit(0);
case '?':
exit(1);
@ -71,4 +100,4 @@ CommandArgs parse_args(int argc, char* argv[])
}
return args;
}
}

View File

@ -1,3 +1,33 @@
/**
* @file error.cpp
* @brief Implementation of error handling system for the DPM utility
*
* Implements the utility functions for error handling defined in error.hpp.
* Provides functionality for creating error context structures to ensure
* consistent error reporting throughout the DPM system.
*
* @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 "error.hpp"
// Simple helper function that takes only the required error category

View File

@ -1,3 +1,33 @@
/**
* @file handlers.cpp
* @brief Implementation of error handling functions for the DPM system
*
* Implements specialized handler functions for each error category in the DPM
* error system. These handlers translate error codes into user-friendly
* messages and provide appropriate exit behavior for different error conditions.
*
* @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 "handlers.hpp"
// Helper function for validating required fields in a FlexDPMError
@ -134,4 +164,4 @@ int handle_undefined_error(FlexDPMError context) {
}
std::cerr << std::endl;
return 1;
}
}

View File

@ -1,35 +1,33 @@
/**
* @file module_interface.cpp
* @brief Implementation of the module interface functions
*
* Provides the implementation of functions declared in the module interface
* that are part of the DPM core, such as callback functions available to modules.
*
* @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
* @file module_interface.cpp
* @brief Implementation of the module interface functions
*
* Provides the implementation of functions declared in the module interface
* that are part of the DPM core, such as callback functions available to modules.
*
* @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_interface.hpp"
#include <iostream>
#include <string>
/**
* @brief Function that modules can call to access DPM core functionality
@ -62,12 +60,47 @@ extern "C" int dpm_core_callback(const char* action, const char* data) {
return 0;
}
else if (action_str == "get_config") {
if (data) {
std::cout << "Module requested config: " << data << std::endl;
if (!data) {
std::cerr << "Error: get_config requires section.key format" << std::endl;
return 1;
}
// Parse the section.key format
std::string data_str(data);
size_t dot_pos = data_str.find('.');
if (dot_pos == std::string::npos) {
std::cerr << "Error: Invalid config format. Use section.key" << std::endl;
return 1;
}
std::string section = data_str.substr(0, dot_pos);
std::string key = data_str.substr(dot_pos + 1);
// Get the configuration value
const char* value = g_config_manager.getConfigValue(section.c_str(), key.c_str());
// Log the request for debugging purposes
std::cout << "Module requested config: " << data << " = "
<< (value ? value : "not found") << std::endl;
return 0;
}
std::cerr << "Error: Unknown module callback action: " << action_str << std::endl;
return 1;
}
}
/**
* @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);
}