From a924a245df801ccf63bcead10c44c99e993f6ccf Mon Sep 17 00:00:00 2001 From: Chris Punches Date: Thu, 13 Mar 2025 23:03:37 -0400 Subject: [PATCH] fixed a cli arg parsing error --- modules/build/build.cpp | 2 +- modules/build/src/cli_parsers.cpp | 23 +++++++++--- modules/build/src/commands.cpp | 2 -- modules/info/info.cpp | 2 +- src/ModuleLoader.cpp | 58 ++++++++++++++++++++++--------- 5 files changed, 63 insertions(+), 24 deletions(-) diff --git a/modules/build/build.cpp b/modules/build/build.cpp index 09b480c..97da4d2 100644 --- a/modules/build/build.cpp +++ b/modules/build/build.cpp @@ -64,7 +64,7 @@ extern "C" const char* dpm_module_get_version(void) { * @return Const char pointer to the module description string */ extern "C" const char* dpm_get_description(void) { - return "DPM Build Module - Creates DPM packages according to specification"; + return "Creates DPM packages according to specification."; } /** diff --git a/modules/build/src/cli_parsers.cpp b/modules/build/src/cli_parsers.cpp index 6b54e93..4e9c1be 100644 --- a/modules/build/src/cli_parsers.cpp +++ b/modules/build/src/cli_parsers.cpp @@ -1,6 +1,15 @@ #include "cli_parsers.hpp" int parse_create_options(int argc, char** argv, BuildOptions& options) { + // Check for help flags directly before any other parsing + for (int i = 0; i < argc; i++) { + if (argv[i] && (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "help") == 0)) { + options.show_help = true; + // Skip all other parsing for help flag + return 0; + } + } + // Track which options were explicitly provided on command line bool output_dir_provided = false; bool contents_dir_provided = false; @@ -190,12 +199,16 @@ int parse_create_options(int argc, char** argv, BuildOptions& options) { return 0; } - Command parse_command(const char* cmd_str) { if (cmd_str == nullptr || strlen(cmd_str) == 0) { return CMD_HELP; } + // Check for stage command, including when it has additional arguments + if (strncmp(cmd_str, "stage", 5) == 0) { + return CMD_STAGE; + } + // Check if cmd_str is a help option if (strcmp(cmd_str, "-h") == 0 || strcmp(cmd_str, "--help") == 0) { return CMD_HELP; @@ -203,14 +216,16 @@ Command parse_command(const char* cmd_str) { else if (strcmp(cmd_str, "help") == 0) { return CMD_HELP; } - else if (strcmp(cmd_str, "stage") == 0) { - return CMD_STAGE; - } return CMD_UNKNOWN; } int validate_build_options(const BuildOptions& options) { + // Check if help was requested - skip validation in this case + if (options.show_help) { + return 0; + } + // Check if contents directory is provided and exists if (options.contents_dir.empty()) { dpm_log(LOG_ERROR, "Contents directory is required (--contents)"); diff --git a/modules/build/src/commands.cpp b/modules/build/src/commands.cpp index f0a2cfa..abe7618 100644 --- a/modules/build/src/commands.cpp +++ b/modules/build/src/commands.cpp @@ -27,8 +27,6 @@ int cmd_stage(int argc, char** argv) { // Validate options int validate_result = validate_build_options(options); if (validate_result != 0) { - // Show help when validation fails - //cmd_help(argc, argv); return validate_result; } diff --git a/modules/info/info.cpp b/modules/info/info.cpp index 03b4e5c..d91e9b1 100644 --- a/modules/info/info.cpp +++ b/modules/info/info.cpp @@ -68,7 +68,7 @@ extern "C" const char* dpm_module_get_version(void) { * @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"; + return "Provides information about the DPM system."; } diff --git a/src/ModuleLoader.cpp b/src/ModuleLoader.cpp index a3c110c..b59bb26 100644 --- a/src/ModuleLoader.cpp +++ b/src/ModuleLoader.cpp @@ -234,51 +234,77 @@ DPMErrorCategory ModuleLoader::load_module(const std::string& module_name, void* return validate_error; } -DPMErrorCategory ModuleLoader::execute_module( const std::string& module_name, const std::string& command ) const -{ +DPMErrorCategory ModuleLoader::execute_module(const std::string& module_name, const std::string& command) const { // declare a module_handle void * module_handle; // attempt to load the module - DPMErrorCategory load_error = load_module( module_name, module_handle ); - if ( load_error != DPMErrorCategory::SUCCESS ) { + DPMErrorCategory load_error = load_module(module_name, module_handle); + if (load_error != DPMErrorCategory::SUCCESS) { return load_error; } // Clear any previous error state and handle any residual failure const char* pre_error = dlerror(); - if ( pre_error != nullptr ) { - dlclose( module_handle ); + if (pre_error != nullptr) { + dlclose(module_handle); return DPMErrorCategory::UNDEFINED_ERROR; } // declare a function pointer type to hold the module symbol to execute - typedef int (*ExecuteFn) ( const char*, int, char** ); + typedef int (*ExecuteFn) (const char*, int, char** ); // populate that void pointer to the execute symbol in the module with - ExecuteFn execute_fn = (ExecuteFn) dlsym( module_handle, "dpm_module_execute" ); + ExecuteFn execute_fn = (ExecuteFn) dlsym(module_handle, "dpm_module_execute"); // do basic error handling to detect if the symbol look up was successful const char * dlsym_error = dlerror(); - if ( dlsym_error != nullptr ) { - dlclose( module_handle ); + if (dlsym_error != nullptr) { + dlclose(module_handle); return DPMErrorCategory::SYMBOL_NOT_FOUND; } // check if the void pointer was populated - if ( execute_fn == nullptr ) { - dlclose( module_handle ); + if (execute_fn == nullptr) { + dlclose(module_handle); return DPMErrorCategory::SYMBOL_NOT_FOUND; } - // execute the symbol that was loaded and supply the command string being routed from DPM - int exec_error = execute_fn( command.c_str(), 0, nullptr ); + // Split the command by spaces to get arguments + std::vector args; + std::string arg; + std::istringstream iss(command); + while (iss >> arg) { + args.push_back(arg); + } + + // Create argc and argv for all arguments + int argc = args.size(); + char** argv = new char*[argc]; + for (int i = 0; i < argc; i++) { + argv[i] = strdup(args[i].c_str()); + } + + // Get the first argument as the command (or empty string if no arguments) + const char* cmd = ""; + if (!args.empty()) { + cmd = args[0].c_str(); + } + + // execute the function with all arguments + int exec_error = execute_fn(cmd, argc, argv); + + // Clean up + for (int i = 0; i < argc; i++) { + free(argv[i]); + } + delete[] argv; // irregardless of result, this is the time to close the module handle - dlclose( module_handle ); + dlclose(module_handle); // if the result of execution was not 0, return an error - if ( exec_error != 0 ) { + if (exec_error != 0) { return DPMErrorCategory::SYMBOL_EXECUTION_FAILED; }