From ac20fcec3dd777f835f25a4f5189c56c3cd1abae Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 5 May 2025 22:19:04 +1200 Subject: [PATCH] Return more error codes as return value of exe. --- src/autocomplete.cpp | 27 ++++++------- src/autocomplete.hpp | 4 +- src/main.cpp | 24 +++++------- src/server_env_manager.cpp | 41 ++++++++++---------- src/servers.cpp | 7 ++-- src/servers.hpp | 2 +- src/templates.cpp | 14 +++---- src/templates.hpp | 2 +- templates/squashkiwi/config/service.env | 2 +- templates/test_template.sh | 50 ++++++++++++++++++++----- 10 files changed, 99 insertions(+), 74 deletions(-) diff --git a/src/autocomplete.cpp b/src/autocomplete.cpp index 0452435..985dbc1 100644 --- a/src/autocomplete.cpp +++ b/src/autocomplete.cpp @@ -9,12 +9,12 @@ #include #include -void dropshell::autocomplete(const std::vector &args) +bool dropshell::autocomplete(const std::vector &args) { if (args.size() < 3) // dropshell autocomplete ??? { autocomplete_list_commands(); - return; + return true; } ASSERT(args.size() >= 3); @@ -27,23 +27,23 @@ void dropshell::autocomplete(const std::vector &args) std::filesystem::directory_iterator dir_iter(std::filesystem::current_path()); for (const auto& entry : dir_iter) std::cout << entry.path().filename().string() << std::endl; - return; + return true; } std::string noargcmds[] = {"templates","autocomplete_list_servers","autocomplete_list_services","autocomplete_list_commands"}; if (std::find(std::begin(noargcmds), std::end(noargcmds), cmd) != std::end(noargcmds)) - return; + return true; if (!dropshell::gConfig().is_config_set()) - return; // can't help without working config. + return false; // can't help without working config. if (args.size()==3) // we have the command but nothing else. dropshell autocomplete command { auto servers = dropshell::get_configured_servers(); for (const auto& server : servers) - std::cout << server.name << std::endl; - return; + std::cout << server.name << std::endl; + return true; } if (args.size()==4) // we have the command and the server. dropshell autocomplete command server @@ -55,13 +55,13 @@ void dropshell::autocomplete(const std::vector &args) auto templates = dropshell::gTemplateManager().get_template_list(); for (const auto& t : templates) std::cout << t << std::endl; - return; + return true; } auto services = dropshell::get_server_services_info(server); for (const auto& service : services) std::cout << service.service_name << std::endl; - return; + return true; } if (args.size()==5) // we have the command and the server and the service. dropshell autocomplete command server service_name @@ -73,17 +73,17 @@ void dropshell::autocomplete(const std::vector &args) std::set backups = dropshell::list_backups(server_name, service_name); for (auto backup : backups) std::cout << backup << std::endl; - return; + return true; } - return; // no more autocompletion possible - don't know what the argument is for. + return false; // no more autocompletion possible - don't know what the argument is for. } // args>5 - no more autocompletion possible - don't know what the argument is for. - return; // catch-all. + return false; // catch-all. } -void dropshell::autocomplete_list_commands() +bool dropshell::autocomplete_list_commands() { std::set commands; dropshell::get_all_used_commands(commands); @@ -100,5 +100,6 @@ void dropshell::autocomplete_list_commands() for (const auto& command : commands) { std::cout << command << std::endl; } + return true; } diff --git a/src/autocomplete.hpp b/src/autocomplete.hpp index 5bd1f6f..8b30147 100644 --- a/src/autocomplete.hpp +++ b/src/autocomplete.hpp @@ -7,9 +7,9 @@ namespace dropshell { - void autocomplete(const std::vector &args); + bool autocomplete(const std::vector &args); - void autocomplete_list_commands(); + bool autocomplete_list_commands(); } // namespace dropshell diff --git a/src/main.cpp b/src/main.cpp index b243c9b..5c1711e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -24,7 +24,7 @@ extern const std::string RELEASE_DATE; extern const std::string AUTHOR; extern const std::string LICENSE; -void print_help() { +bool print_help() { std::cout << std::endl; maketitle("DropShell version " + VERSION); std::cout << std::endl; @@ -59,6 +59,7 @@ void print_help() { std::cout << std::endl; std::cout << "Other commands available once initialised." << std::endl; } + return true; } @@ -125,15 +126,11 @@ int main(int argc, char* argv[]) { argvec.push_back(argv[i]); - if (cmd == "autocomplete") { - autocomplete(argvec); - return 0; - } + if (cmd == "autocomplete") + return autocomplete(argvec) ? 0 : 1; - if (cmd == "help" || cmd == "-h" || cmd == "--help" || cmd== "h" || cmd=="halp") { - print_help(); - return 0; - } + if (cmd == "help" || cmd == "-h" || cmd == "--help" || cmd== "h" || cmd=="halp") + return print_help() ? 0 : 1; if (cmd == "edit" && argc < 3) { if (!gConfig().is_config_set()) @@ -190,20 +187,17 @@ int main(int argc, char* argv[]) { if (cmd == "create-template") { if (argc < 3) return die("Error: create-template requires a template name"); - gTemplateManager().create_template(argv[2]); - return 0; + return (gTemplateManager().create_template(argv[2])) ? 0 : 1; } if (cmd == "create-server") { if (argc < 3) return die("Error: create-server requires a server name"); - create_server(argv[2]); - return 0; + return (create_server(argv[2])) ? 0 : 1; } if (cmd == "create-service") { if (argc < 5) return die("Error: not enough arguments.\ndropshell create-service server template service"); - create_service(argv[2], argv[3], argv[4]); - return 0; + return (create_service(argv[2], argv[3], argv[4])) ? 0 : 1; } if (cmd == "ssh" && argc < 4) { diff --git a/src/server_env_manager.cpp b/src/server_env_manager.cpp index 979f8d3..6b914ef 100644 --- a/src/server_env_manager.cpp +++ b/src/server_env_manager.cpp @@ -161,9 +161,21 @@ bool server_env_manager::check_remote_items_exist(const std::vector return true; } +bool EXITSTATUSCHECK(int ret) { + return (ret != -1 && WIFEXITED(ret) && (WEXITSTATUS(ret) == 0)); // ret is -1 if the command failed to execute. +} + bool server_env_manager::execute_ssh_command(const sCommand& command, bool allocateTTY) const { std::string full_cmd = construct_ssh_cmd(allocateTTY) + " " + (allocateTTY ? halfquote(command.construct_rawcmd()) : quote(command.construct_safecmd())); - return (system(full_cmd.c_str()) == 0); + int ret = system(full_cmd.c_str()); + if (ret == -1) { + std::cerr << "Error: Failed to execute command: " << full_cmd << std::endl; + // system() failed to execute + return false; + } else { + // Check if the command exited normally and with status 0 + return EXITSTATUSCHECK(ret); + } } bool server_env_manager::execute_ssh_command_and_capture_output(const sCommand& command, std::string &output, bool allocateTTY) const @@ -187,12 +199,8 @@ bool server_env_manager::run_remote_template_command_and_capture_output(const st } bool server_env_manager::execute_local_command(const sCommand& command) { - auto status = system(command.construct_safecmd().c_str()); - if ( WIFEXITED(status) ) { - int returned = WEXITSTATUS(status); - return (returned == 0); - } - return false; + int ret = system(command.construct_safecmd().c_str()); + return EXITSTATUSCHECK(ret); } bool server_env_manager::execute_local_command_interactive(const sCommand &command) @@ -217,19 +225,14 @@ bool server_env_manager::execute_local_command_interactive(const sCommand &comma // If execvp returns, it means an error occurred perror("execvp failed"); exit(EXIT_FAILURE); // Exit child process on error - } else { // Parent process - int status; + int ret; // Wait for the child process to complete - waitpid(pid, &status, 0); + waitpid(pid, &ret, 0); - if (WIFEXITED(status)) { - return (WEXITSTATUS(status) == 0); - } - return false; // Child terminated abnormally + return EXITSTATUSCHECK(ret); } - } bool server_env_manager::execute_local_command_and_capture_output(const sCommand& command, std::string &output) @@ -243,12 +246,8 @@ bool server_env_manager::execute_local_command_and_capture_output(const sCommand while (fgets(buffer, sizeof(buffer), pipe) != nullptr) { output += buffer; } - int status = pclose(pipe); - if ( WIFEXITED(status) ) { - int returned = WEXITSTATUS(status); - return (returned == 0); - } - return false; + int ret = pclose(pipe); + return EXITSTATUSCHECK(ret); } diff --git a/src/servers.cpp b/src/servers.cpp index 579b9a4..551fa45 100644 --- a/src/servers.cpp +++ b/src/servers.cpp @@ -174,14 +174,14 @@ void show_server_details(const std::string& server_name) { } // end of list services } // end of show_server_details -void create_server(const std::string &server_name) +bool create_server(const std::string &server_name) { // 1. check if server name already exists std::string server_existing_dir = localpath::server(server_name); if (!server_existing_dir.empty()) { std::cerr << "Error: Server name already exists: " << server_name << std::endl; std::cerr << "Current server path: " << server_existing_dir << std::endl; - return; + return false; } // 2. create a new directory in the user config directory @@ -189,7 +189,7 @@ void create_server(const std::string &server_name) if (lsdp.empty() || lsdp[0].empty()) { std::cerr << "Error: Local server definition path not found" << std::endl; std::cerr << "Run 'dropshell edit' to configure DropShell" << std::endl; - return; + return false; } std::string server_dir = lsdp[0] + "/" + server_name; std::filesystem::create_directory(server_dir); @@ -214,6 +214,7 @@ void create_server(const std::string &server_name) std::cout << "2) test ssh is working: dropshell ssh " << server_name << std::endl; std::cout << "3) install dropshell-agent: dropshell install " << server_name << " dropshell-agent" << std::endl; std::cout << std::endl; + return true; } void get_all_used_commands(std::set &commands) diff --git a/src/servers.hpp b/src/servers.hpp index 2a40400..4afbf66 100644 --- a/src/servers.hpp +++ b/src/servers.hpp @@ -24,7 +24,7 @@ namespace dropshell { void list_servers(); void show_server_details(const std::string& server_name); - void create_server(const std::string& server_name); + bool create_server(const std::string& server_name); void get_all_used_commands(std::set &commands); diff --git a/src/templates.cpp b/src/templates.cpp index a58123b..1a94f5e 100644 --- a/src/templates.cpp +++ b/src/templates.cpp @@ -168,7 +168,7 @@ return source->template_command_exists(template_name, command); } - void template_manager::create_template(const std::string &template_name) const + bool template_manager::create_template(const std::string &template_name) const { // 1. Create a new directory in the user templates directory std::vector local_server_definition_paths = gConfig().get_local_server_definition_paths(); @@ -176,20 +176,20 @@ if (local_server_definition_paths.empty()) { std::cerr << "Error: No local server definition paths found" << std::endl; std::cerr << "Run 'dropshell edit' to configure DropShell" << std::endl; - return; + return false; } auto info = get_template_info(template_name); if (info.is_set()) { std::cerr << "Error: Template '" << template_name << "' already exists at " << info.locationID() << std::endl; - return; + return false; } auto local_template_paths = gConfig().get_template_local_paths(); if (local_template_paths.empty()) { std::cerr << "Error: No local template paths found" << std::endl; std::cerr << "Run 'dropshell edit' to add one to the DropShell config" << std::endl; - return; + return false; } std::string new_template_path = local_template_paths[0] + "/" + template_name; @@ -200,7 +200,7 @@ auto example_info = gTemplateManager().get_template_info("example-nginx"); if (!example_info.is_set()) { std::cerr << "Error: Example template not found" << std::endl; - return; + return false; } std::string example_template_path = example_info.local_template_path(); @@ -222,7 +222,7 @@ std::string service_env_path = new_template_path + "/config/.template_info.env"; if (!replace_line_in_file(service_env_path, search_string, replacement_line)) { std::cerr << "Error: Failed to replace TEMPLATE= line in the .template_info.env file" << std::endl; - return; + return false; } // 3. Print out the README.txt file and the path @@ -244,7 +244,7 @@ std::cout << std::endl; std::cout << "Template '" << template_name << "' created at " << new_template_path << std::endl; - test_template(new_template_path); + return test_template(new_template_path); } void template_manager::load_sources() diff --git a/src/templates.hpp b/src/templates.hpp index 867d9f8..89986b4 100644 --- a/src/templates.hpp +++ b/src/templates.hpp @@ -84,7 +84,7 @@ class template_manager { template_info get_template_info(const std::string& template_name) const; bool template_command_exists(const std::string& template_name,const std::string& command) const; - void create_template(const std::string& template_name) const; + bool create_template(const std::string& template_name) const; static bool test_template(const std::string& template_path); void list_templates() const; diff --git a/templates/squashkiwi/config/service.env b/templates/squashkiwi/config/service.env index 4e40a47..e9a710a 100644 --- a/templates/squashkiwi/config/service.env +++ b/templates/squashkiwi/config/service.env @@ -2,5 +2,5 @@ # (can also override anything in the _basic.env file in the template to make it specific to this server) HOST_PORT=80 -LOCAL_DATA_FOLDER="${HOME}/.sk" +LOCAL_DATA_FOLDER="/home/dropshell/example-squashkiwi" IMAGE_TAG="latest" diff --git a/templates/test_template.sh b/templates/test_template.sh index 4a873e6..4c86cc3 100755 --- a/templates/test_template.sh +++ b/templates/test_template.sh @@ -1,23 +1,49 @@ #!/bin/bash -# default config should always work for localhost - SCRIPT_DIR=$(dirname "$0") -TEMPLATE="$1" -# make sure TEMPLATE doesn't end with a / -TEMPLATE=$(basename "$TEMPLATE") +# default config should always work for localhost function die() { echo "$1" exit 1 } -function title() { - echo "----------------------------------------" - echo "$1" - echo "----------------------------------------" +function dashes() { + for ((i=0; i<$1; i++)); do + echo -n "-" + done + echo "" } +function centerprint() { + # print $1 centered + local width=$2 + local padding=$(( (width - ${#1}) / 2 )) + for ((i=0; i<$padding; i++)); do + echo -n " " + done + + echo "$1" +} + +function title() { + # determine terminal width + TERMINAL_WIDTH=$(tput cols) + + echo " " + dashes $TERMINAL_WIDTH + centerprint "$1" $TERMINAL_WIDTH + dashes $TERMINAL_WIDTH +} + +# do we have the first argument? +if [ -z "$1" ]; then + echo "Usage: $0