From 8fc3384c03a399f00143e07835c862e5382d91e9 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 12 May 2025 20:11:08 +1200 Subject: [PATCH] Tidy --- src/commands/edit.cpp | 2 +- src/commands/install.cpp | 2 +- src/commands/list.cpp | 4 +- src/commands/shared_commands.hpp | 1 + src/contrib/base64.cpp | 282 ------------------------------- src/contrib/base64.hpp | 35 ---- src/server_env_manager.cpp | 4 +- src/service_runner.cpp | 113 +------------ src/service_runner.hpp | 9 - src/utils/b64ed.cpp | 42 +++++ src/utils/b64ed.hpp | 9 + src/utils/execute.cpp | 35 ++-- src/utils/execute.hpp | 16 +- 13 files changed, 80 insertions(+), 474 deletions(-) delete mode 100644 src/contrib/base64.cpp delete mode 100644 src/contrib/base64.hpp create mode 100644 src/utils/b64ed.cpp create mode 100644 src/utils/b64ed.hpp diff --git a/src/commands/edit.cpp b/src/commands/edit.cpp index cb623d4..2df6c2e 100644 --- a/src/commands/edit.cpp +++ b/src/commands/edit.cpp @@ -72,7 +72,7 @@ bool edit_file(const std::string &file_path) } std::cout << "Editing file: " << file_path << std::endl; - return execute_local_command(editor_cmd, nullptr, cMode::Interactive | cMode::RawCommand); + return execute_local_command(editor_cmd, nullptr, cMode::Interactive); } // ------------------------------------------------------------------------------------------------ diff --git a/src/commands/install.cpp b/src/commands/install.cpp index b57a47e..16db0be 100644 --- a/src/commands/install.cpp +++ b/src/commands/install.cpp @@ -60,7 +60,7 @@ bool rsync_tree_to_remote( quote(local_path + "/") + " "+ quote(server_env.get_SSH_USER() + "@" + server_env.get_SSH_HOST() + ":" + remote_path + "/"); - return execute_local_command(rsync_cmd, nullptr, (silent ? cMode::Silent : cMode::None) + cMode::RawCommand); + return execute_local_command(rsync_cmd, nullptr, (silent ? cMode::Silent : cMode::None) ); } // ------------------------------------------------------------------------------------------------ diff --git a/src/commands/list.cpp b/src/commands/list.cpp index 64b0684..728cac1 100644 --- a/src/commands/list.cpp +++ b/src/commands/list.cpp @@ -91,7 +91,7 @@ void list_servers() { std::string serviceticks = ""; for (const auto& [service_name, service_status] : status) { ports_used.insert(service_status.ports.begin(), service_status.ports.end()); - serviceticks += service_runner::HealthStatus2String(service_status.health) + " "; + serviceticks += HealthStatus2String(service_status.health) + " "; } std::string ports_used_str = ""; for (const auto& port : ports_used) @@ -167,7 +167,7 @@ void show_server_details(const std::string& server_name) { std::set ports_used; std::string serviceticks = ""; for (const auto& [service_name, service_status] : status) { - std::string healthy = service_runner::HealthStatus2String(service_status.health); + std::string healthy = HealthStatus2String(service_status.health); std::string ports_str = ""; for (const auto& port : service_status.ports) diff --git a/src/commands/shared_commands.hpp b/src/commands/shared_commands.hpp index 4e71c91..c1880bc 100644 --- a/src/commands/shared_commands.hpp +++ b/src/commands/shared_commands.hpp @@ -19,6 +19,7 @@ namespace dropshell { // defined in health.cpp std::string healthtick(const std::string& server, const std::string& service); + std::string HealthStatus2String(HealthStatus status); // defined in standard_autocomplete.cpp void std_autocomplete(const CommandContext& ctx); diff --git a/src/contrib/base64.cpp b/src/contrib/base64.cpp deleted file mode 100644 index 494742f..0000000 --- a/src/contrib/base64.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/* - base64.cpp and base64.h - - base64 encoding and decoding with C++. - More information at - https://renenyffenegger.ch/notes/development/Base64/Encoding-and-decoding-base-64-with-cpp - - Version: 2.rc.09 (release candidate) - - Copyright (C) 2004-2017, 2020-2022 René Nyffenegger - - This source code is provided 'as-is', without any express or implied - warranty. In no event will the author be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this source code must not be misrepresented; you must not - claim that you wrote the original source code. If you use this source code - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original source code. - - 3. This notice may not be removed or altered from any source distribution. - - René Nyffenegger rene.nyffenegger@adp-gmbh.ch - -*/ - -#include "contrib/base64.hpp" - -#include -#include - - // - // Depending on the url parameter in base64_chars, one of - // two sets of base64 characters needs to be chosen. - // They differ in their last two characters. - // -static const char* base64_chars[2] = { - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789" - "+/", - - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789" - "-_"}; - -static unsigned int pos_of_char(const unsigned char chr) { - // - // Return the position of chr within base64_encode() - // - - if (chr >= 'A' && chr <= 'Z') return chr - 'A'; - else if (chr >= 'a' && chr <= 'z') return chr - 'a' + ('Z' - 'A') + 1; - else if (chr >= '0' && chr <= '9') return chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2; - else if (chr == '+' || chr == '-') return 62; // Be liberal with input and accept both url ('-') and non-url ('+') base 64 characters ( - else if (chr == '/' || chr == '_') return 63; // Ditto for '/' and '_' - else - // - // 2020-10-23: Throw std::exception rather than const char* - //(Pablo Martin-Gomez, https://github.com/Bouska) - // - throw std::runtime_error("Input is not valid base64-encoded data."); -} - -static std::string insert_linebreaks(std::string str, size_t distance) { - // - // Provided by https://github.com/JomaCorpFX, adapted by me. - // - if (!str.length()) { - return ""; - } - - size_t pos = distance; - - while (pos < str.size()) { - str.insert(pos, "\n"); - pos += distance + 1; - } - - return str; -} - -template -static std::string encode_with_line_breaks(String s) { - return insert_linebreaks(base64_encode(s, false), line_length); -} - -template -static std::string encode_pem(String s) { - return encode_with_line_breaks(s); -} - -template -static std::string encode_mime(String s) { - return encode_with_line_breaks(s); -} - -template -static std::string encode(String s, bool url) { - return base64_encode(reinterpret_cast(s.data()), s.length(), url); -} - -std::string base64_encode(unsigned char const* bytes_to_encode, size_t in_len, bool url) { - - size_t len_encoded = (in_len +2) / 3 * 4; - - unsigned char trailing_char = url ? '.' : '='; - - // - // Choose set of base64 characters. They differ - // for the last two positions, depending on the url - // parameter. - // A bool (as is the parameter url) is guaranteed - // to evaluate to either 0 or 1 in C++ therefore, - // the correct character set is chosen by subscripting - // base64_chars with url. - // - const char* base64_chars_ = base64_chars[url]; - - std::string ret; - ret.reserve(len_encoded); - - unsigned int pos = 0; - - while (pos < in_len) { - ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0xfc) >> 2]); - - if (pos+1 < in_len) { - ret.push_back(base64_chars_[((bytes_to_encode[pos + 0] & 0x03) << 4) + ((bytes_to_encode[pos + 1] & 0xf0) >> 4)]); - - if (pos+2 < in_len) { - ret.push_back(base64_chars_[((bytes_to_encode[pos + 1] & 0x0f) << 2) + ((bytes_to_encode[pos + 2] & 0xc0) >> 6)]); - ret.push_back(base64_chars_[ bytes_to_encode[pos + 2] & 0x3f]); - } - else { - ret.push_back(base64_chars_[(bytes_to_encode[pos + 1] & 0x0f) << 2]); - ret.push_back(trailing_char); - } - } - else { - - ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0x03) << 4]); - ret.push_back(trailing_char); - ret.push_back(trailing_char); - } - - pos += 3; - } - - - return ret; -} - -template -static std::string decode(String const& encoded_string, bool remove_linebreaks) { - // - // decode(…) is templated so that it can be used with String = const std::string& - // or std::string_view (requires at least C++17) - // - - if (encoded_string.empty()) return std::string(); - - if (remove_linebreaks) { - - std::string copy(encoded_string); - - copy.erase(std::remove(copy.begin(), copy.end(), '\n'), copy.end()); - - return base64_decode(copy, false); - } - - size_t length_of_string = encoded_string.length(); - size_t pos = 0; - - // - // The approximate length (bytes) of the decoded string might be one or - // two bytes smaller, depending on the amount of trailing equal signs - // in the encoded string. This approximation is needed to reserve - // enough space in the string to be returned. - // - size_t approx_length_of_decoded_string = length_of_string / 4 * 3; - std::string ret; - ret.reserve(approx_length_of_decoded_string); - - while (pos < length_of_string) { - // - // Iterate over encoded input string in chunks. The size of all - // chunks except the last one is 4 bytes. - // - // The last chunk might be padded with equal signs or dots - // in order to make it 4 bytes in size as well, but this - // is not required as per RFC 2045. - // - // All chunks except the last one produce three output bytes. - // - // The last chunk produces at least one and up to three bytes. - // - - size_t pos_of_char_1 = pos_of_char(encoded_string.at(pos+1) ); - - // - // Emit the first output byte that is produced in each chunk: - // - ret.push_back(static_cast( ( (pos_of_char(encoded_string.at(pos+0)) ) << 2 ) + ( (pos_of_char_1 & 0x30 ) >> 4))); - - if ( ( pos + 2 < length_of_string ) && // Check for data that is not padded with equal signs (which is allowed by RFC 2045) - encoded_string.at(pos+2) != '=' && - encoded_string.at(pos+2) != '.' // accept URL-safe base 64 strings, too, so check for '.' also. - ) - { - // - // Emit a chunk's second byte (which might not be produced in the last chunk). - // - unsigned int pos_of_char_2 = pos_of_char(encoded_string.at(pos+2) ); - ret.push_back(static_cast( (( pos_of_char_1 & 0x0f) << 4) + (( pos_of_char_2 & 0x3c) >> 2))); - - if ( ( pos + 3 < length_of_string ) && - encoded_string.at(pos+3) != '=' && - encoded_string.at(pos+3) != '.' - ) - { - // - // Emit a chunk's third byte (which might not be produced in the last chunk). - // - ret.push_back(static_cast( ( (pos_of_char_2 & 0x03 ) << 6 ) + pos_of_char(encoded_string.at(pos+3)) )); - } - } - - pos += 4; - } - - return ret; -} - -std::string base64_decode(std::string const& s, bool remove_linebreaks) { - return decode(s, remove_linebreaks); -} - -std::string base64_encode(std::string const& s, bool url) { - return encode(s, url); -} - -std::string base64_encode_pem (std::string const& s) { - return encode_pem(s); -} - -std::string base64_encode_mime(std::string const& s) { - return encode_mime(s); -} - -#if __cplusplus >= 201703L -// -// Interface with std::string_view rather than const std::string& -// Requires C++17 -// Provided by Yannic Bonenberger (https://github.com/Yannic) -// - -std::string base64_encode(std::string_view s, bool url) { - return encode(s, url); -} - -std::string base64_encode_pem(std::string_view s) { - return encode_pem(s); -} - -std::string base64_encode_mime(std::string_view s) { - return encode_mime(s); -} - -std::string base64_decode(std::string_view s, bool remove_linebreaks) { - return decode(s, remove_linebreaks); -} - -#endif // __cplusplus >= 201703L diff --git a/src/contrib/base64.hpp b/src/contrib/base64.hpp deleted file mode 100644 index 4860d63..0000000 --- a/src/contrib/base64.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// -// base64 encoding and decoding with C++. -// Version: 2.rc.09 (release candidate) -// - -#ifndef BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A -#define BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A - -#include - -#if __cplusplus >= 201703L -#include -#endif // __cplusplus >= 201703L - -std::string base64_encode (std::string const& s, bool url = false); -std::string base64_encode_pem (std::string const& s); -std::string base64_encode_mime(std::string const& s); - -std::string base64_decode(std::string const& s, bool remove_linebreaks = false); -std::string base64_encode(unsigned char const*, size_t len, bool url = false); - -#if __cplusplus >= 201703L -// -// Interface with std::string_view rather than const std::string& -// Requires C++17 -// Provided by Yannic Bonenberger (https://github.com/Yannic) -// -std::string base64_encode (std::string_view s, bool url = false); -std::string base64_encode_pem (std::string_view s); -std::string base64_encode_mime(std::string_view s); - -std::string base64_decode(std::string_view s, bool remove_linebreaks = false); -#endif // __cplusplus >= 201703L - -#endif /* BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A */ diff --git a/src/server_env_manager.cpp b/src/server_env_manager.cpp index f56d829..7f30dd8 100644 --- a/src/server_env_manager.cpp +++ b/src/server_env_manager.cpp @@ -198,7 +198,7 @@ bool server_env_manager::run_remote_template_command(const std::string &service_ if (scommand.get_command_to_run().empty()) return false; - cMode mode = (command=="ssh") ? (cMode::Interactive | cMode::RawCommand) : cMode::Silent; + cMode mode = (command=="ssh") ? (cMode::Interactive) : cMode::Silent; return execute_ssh_command(get_SSH_INFO(), scommand, mode); } @@ -212,7 +212,7 @@ bool server_env_manager::run_remote_template_command_and_capture_output(const st for (const auto& [key, value] : extra_env_vars) scommand.add_env_var(key, value); - cMode mode = cMode::CaptureOutput | cMode::RawCommand; + cMode mode = cMode::CaptureOutput; return execute_ssh_command(get_SSH_INFO(), scommand, mode, &output); } diff --git a/src/service_runner.cpp b/src/service_runner.cpp index 4403450..b879293 100644 --- a/src/service_runner.cpp +++ b/src/service_runner.cpp @@ -45,41 +45,6 @@ service_runner::service_runner(const std::string& server_name, const std::string } -bool service_runner::uninstall(bool silent) { - maketitle("Uninstalling " + mService + " (" + mServiceInfo.template_name + ") on " + mServer); - - if (!mServerEnv.is_valid()) return false; // should never hit this. - - // 2. Check if service directory exists on server - if (!mServerEnv.check_remote_dir_exists(remotepath::service(mServer, mService))) { - std::cerr << "Service is not installed: " << mService << std::endl; - return true; // Nothing to uninstall - } - - // 3. Run uninstall script if it exists - std::string uninstall_script = remotepath::service_template(mServer, mService) + "/uninstall.sh"; - bool script_exists = mServerEnv.check_remote_file_exists(uninstall_script); - - if (script_exists) { - if (!mServerEnv.run_remote_template_command(mService, "uninstall", {}, silent, {})) { - std::cerr << "Warning: Uninstall script failed, but continuing with directory removal" << std::endl; - } - - } else { - std::cerr << "Warning: No uninstall script found. Unable to uninstall service." << std::endl; - return false; - } - - // 4. Remove the service directory from the server - std::string rm_cmd = "rm -rf " + quote(remotepath::service(mServer, mService)); - if (!execute_ssh_command(mServerEnv.get_SSH_INFO(), sCommand(rm_cmd), cMode::Silent)) { - std::cerr << "Failed to remove service directory" << std::endl; - return false; - } - - std::cout << "Service " << mService << " successfully uninstalled from " << mServer << std::endl; - return true; -} bool service_runner::nuke(bool silent) { @@ -181,8 +146,8 @@ bool service_runner::run_command(const std::string& command, std::vector service_runner::get_all_services_status(std return status; } -HealthStatus service_runner::is_healthy() -{ - if (!mServerEnv.is_valid()) { - std::cerr << "Error: Server service not initialized" << std::endl; - return HealthStatus::ERROR; - } - - if (!mServerEnv.check_remote_dir_exists(remotepath::service(mServer, mService))) { - return HealthStatus::NOTINSTALLED; - } - - std::string script_path = remotepath::service_template(mServer, mService) + "/status.sh"; - if (!mServerEnv.check_remote_file_exists(script_path)) { - return HealthStatus::UNKNOWN; - } - - // Run status script, does not display output. - if (!mServerEnv.run_remote_template_command(mService, "status", {}, true, {})) - return HealthStatus::UNHEALTHY; - return HealthStatus::HEALTHY; -} - -std::string service_runner::healthtick() -{ - std::string green_tick = "\033[32m✓\033[0m"; - std::string red_cross = "\033[31m✗\033[0m"; - std::string yellow_exclamation = "\033[33m!\033[0m"; - std::string unknown = "\033[37m✓\033[0m"; - - HealthStatus status = is_healthy(); - if (status == HealthStatus::HEALTHY) - return green_tick; - else if (status == HealthStatus::UNHEALTHY) - return red_cross; - else if (status == HealthStatus::UNKNOWN) - return unknown; - else - return yellow_exclamation; -} - -std::string service_runner::HealthStatus2String(HealthStatus status) -{ - if (status == HealthStatus::HEALTHY) - return ":tick:"; - else if (status == HealthStatus::UNHEALTHY) - return ":cross:"; - else if (status == HealthStatus::UNKNOWN) - return ":greytick:"; - else if (status == HealthStatus::NOTINSTALLED) - return ":warning:"; - else - return ":error:"; -} - - -std::string service_runner::healthmark() -{ - HealthStatus status = is_healthy(); - return HealthStatus2String(status); -} bool service_runner::interactive_ssh(const std::string & server_name, const std::string & command) { std::string serverpath = localpath::server(server_name); @@ -337,7 +242,7 @@ bool service_runner::interactive_ssh(const std::string & server_name, const std: std::cerr << "Error: Invalid server environment file: " << server_name << std::endl; return false; } - return execute_ssh_command(env.get_SSH_INFO(), scommand, cMode::Interactive | cMode::RawCommand); + return execute_ssh_command(env.get_SSH_INFO(), scommand, cMode::Interactive); } @@ -357,13 +262,13 @@ bool service_runner::interactive_ssh_service() bool service_runner::scp_file_to_remote(const std::string &local_path, const std::string &remote_path, bool silent) { std::string scp_cmd = "scp -P " + mServerEnv.get_SSH_PORT() + " " + quote(local_path) + " " + mServerEnv.get_SSH_USER() + "@" + mServerEnv.get_SSH_HOST() + ":" + quote(remote_path) + (silent ? " > /dev/null 2>&1" : ""); - return execute_local_command(scp_cmd, nullptr, (silent ? cMode::Silent : cMode::None) + cMode::RawCommand); + return execute_local_command(scp_cmd, nullptr, (silent ? cMode::Silent : cMode::None)); } bool service_runner::scp_file_from_remote(const std::string &remote_path, const std::string &local_path, bool silent) { std::string scp_cmd = "scp -P " + mServerEnv.get_SSH_PORT() + " " + mServerEnv.get_SSH_USER() + "@" + mServerEnv.get_SSH_HOST() + ":" + quote(remote_path) + " " + quote(local_path) + (silent ? " > /dev/null 2>&1" : ""); - return execute_local_command(scp_cmd, nullptr, (silent ? cMode::Silent : cMode::None) + cMode::RawCommand); + return execute_local_command(scp_cmd, nullptr, (silent ? cMode::Silent : cMode::None)); } bool service_runner::restore(std::string backup_file, bool silent) @@ -428,12 +333,12 @@ bool service_runner::restore(std::string backup_file, bool silent) { // uninstall service, then nuke it. maketitle("2) Uninstalling old service..."); - if (!uninstall(true)) - return false; + // if (!uninstall(true)) + // return false; maketitle("3) Nuking old service..."); - if (!nuke(true)) - return false; + // if (!nuke(true)) + // return false; } diff --git a/src/service_runner.hpp b/src/service_runner.hpp index ef5a7d8..048c009 100644 --- a/src/service_runner.hpp +++ b/src/service_runner.hpp @@ -56,13 +56,6 @@ class service_runner { std::string healthmark(); public: - // uninstall the service over ssh, using the credentials from server.env (via server_env.hpp) - // 1. check if the server_name exists, and the service_name refers to a valid template - // 2. check if service_name is valid for the server_name - // 3. run the uninstall.sh script on the server, passing the {service_name}.env file as an argument - // 4. remove the service directory from the server - bool uninstall(bool silent=false); - // backup and restore bool backup(bool silent=false); bool restore(std::string backup_file, bool silent=false); @@ -75,7 +68,6 @@ class service_runner { // replaces the current dropshell process with the ssh process bool interactive_ssh_service(); - bool rsync_tree_to_remote(const std::string& local_path, const std::string& remote_path, bool silent=false); bool scp_file_to_remote(const std::string& local_path, const std::string& remote_path, bool silent=false); bool scp_file_from_remote(const std::string& remote_path, const std::string& local_path, bool silent=false); public: @@ -83,7 +75,6 @@ class service_runner { static std::string get_latest_backup_file(const std::string& server, const std::string& service); static bool interactive_ssh(const std::string & server_name, const std::string & command); static std::map get_all_services_status(std::string server_name); - static std::string HealthStatus2String(HealthStatus status); private: std::string mServer; diff --git a/src/utils/b64ed.cpp b/src/utils/b64ed.cpp new file mode 100644 index 0000000..cec8e1f --- /dev/null +++ b/src/utils/b64ed.cpp @@ -0,0 +1,42 @@ +#include "b64ed.hpp" + +#include + +// Custom base64 encoding/decoding tables +static const std::string custom_base64_chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+_"; + +std::string base64_encode(const std::string &in) { + std::string out; + int val = 0, valb = -6; + for (unsigned char c : in) { + val = (val << 8) + c; + valb += 8; + while (valb >= 0) { + out.push_back(custom_base64_chars[(val >> valb) & 0x3F]); + valb -= 6; + } + } + if (valb > -6) out.push_back(custom_base64_chars[((val << 8) >> (valb + 8)) & 0x3F]); + while (out.size() % 4) out.push_back('='); + return out; +} + +std::string base64_decode(const std::string &in) { + std::vector T(256, -1); + for (int i = 0; i < 64; i++) T[custom_base64_chars[i]] = i; + std::string out; + int val = 0, valb = -8; + for (unsigned char c : in) { + if (T[c] == -1) break; + val = (val << 6) + T[c]; + valb += 6; + if (valb >= 0) { + out.push_back(char((val >> valb) & 0xFF)); + valb -= 8; + } + } + return out; +} \ No newline at end of file diff --git a/src/utils/b64ed.hpp b/src/utils/b64ed.hpp new file mode 100644 index 0000000..fa71d44 --- /dev/null +++ b/src/utils/b64ed.hpp @@ -0,0 +1,9 @@ +#ifndef B64ED_HPP +#define B64ED_HPP + +#include + +std::string base64_decode(const std::string &in); +std::string base64_encode(const std::string &in); + +#endif diff --git a/src/utils/execute.cpp b/src/utils/execute.cpp index 1d0d90a..52311ec 100644 --- a/src/utils/execute.cpp +++ b/src/utils/execute.cpp @@ -9,8 +9,8 @@ #include #include "execute.hpp" -#include "contrib/base64.hpp" #include "utils/utils.hpp" +#include "utils/b64ed.hpp" bool EXITSTATUSCHECK(int ret) { @@ -23,7 +23,7 @@ namespace dropshell { if (command.get_command_to_run().empty()) return false; - std::string full_command = command.construct_cmd(cStyle::Raw); // Get the command string + std::string full_command = command.construct_cmd(); // Get the command string pid_t pid = fork(); @@ -54,8 +54,7 @@ namespace dropshell ASSERT(output != nullptr, "Output string must be provided"); if (command.get_command_to_run().empty()) return false; - cStyle style = cStyle::Raw; - std::string full_cmd = command.construct_cmd(style) + " 2>&1"; + std::string full_cmd = command.construct_cmd() + " 2>&1"; FILE *pipe = popen(full_cmd.c_str(), "r"); if (!pipe) { @@ -72,13 +71,10 @@ namespace dropshell bool execute_local_command(const sCommand &command, std::string *output /* = nullptr */, cMode mode /* = cMode::None */) { - ASSERT(hasFlag(mode, cMode::RawCommand), "Raw command mode is required for local command execution"); - if (hasFlag(mode, cMode::Interactive)) { ASSERT(!hasFlag(mode, cMode::CaptureOutput), "Interactive mode and capture output mode cannot be used together"); ASSERT(output == nullptr, "Interactive mode and an output string cannot be used together"); - ASSERT(is_raw(mode), "Interactive mode requires raw command mode"); return execute_local_command_interactive(command); } @@ -86,7 +82,6 @@ namespace dropshell if (hasFlag(mode, cMode::CaptureOutput)) { ASSERT(output != nullptr, "Capture output mode requires an output string to be provided"); - ASSERT(is_raw(mode), "Capture output mode requires raw command mode"); ASSERT(!hasFlag(mode, cMode::Silent), "Silent mode is not allowed with capture output mode"); return execute_local_command_and_capture_output(command, output); @@ -94,9 +89,8 @@ namespace dropshell if (command.get_command_to_run().empty()) return false; - cStyle style = cStyle::Raw; bool silent = hasFlag(mode, cMode::Silent); - std::string full_cmd = command.construct_cmd(style) + " 2>&1" + (silent ? " > /dev/null" : ""); + std::string full_cmd = command.construct_cmd() + " 2>&1" + (silent ? " > /dev/null" : ""); int ret = system(full_cmd.c_str()); bool ok = EXITSTATUSCHECK(ret); @@ -113,18 +107,16 @@ namespace dropshell if (command.get_command_to_run().empty()) return false; - ASSERT(!(hasFlag(mode, cMode::Interactive) && !is_raw(mode)), "Interactive mode requires raw command mode"); ASSERT(!(hasFlag(mode, cMode::CaptureOutput) && output == nullptr), "Capture output mode must be used with an output string"); std::stringstream ssh_cmd; ssh_cmd << "ssh -p " << ssh_info.port << " " << (hasFlag(mode, cMode::Interactive) ? "-tt " : "") << ssh_info.user << "@" << ssh_info.host; - std::string cmdstr = command.construct_cmd(is_raw(mode) ? cStyle::Raw : cStyle::Safe); + std::string cmdstr = command.construct_cmd(); sCommand ssh_command(ssh_cmd.str() + " " + cmdstr); - cMode localmode = mode + cMode::RawCommand; - bool rval = execute_local_command(ssh_command, output, localmode); + bool rval = execute_local_command(ssh_command, output, mode); if (!rval && !hasFlag(mode, cMode::Silent)) { @@ -143,24 +135,20 @@ namespace dropshell if (command.empty()) return ""; std::string encoded = base64_encode(dequote(trim(command))); - std::string commandstr = "echo " + encoded + " | base64 -d | bash"; + std::string commandstr = "bb64 " + encoded; return commandstr; } - std::string sCommand::construct_cmd(cStyle style) const + std::string sCommand::construct_cmd() const { if (mCmd.empty()) return ""; - if (mDir.empty() && mVars.empty()) - return (is_safe(style) ? makesafecmd(mCmd) : mCmd); - - // need to construct to change directory and set environment variables std::string cmdstr; if (!mDir.empty()) - cmdstr += "cd " + quote(mDir) + " ; "; + cmdstr += "cd " + quote(mDir) + " && "; if (!mVars.empty()) for (const auto &env_var : mVars) @@ -168,10 +156,7 @@ namespace dropshell cmdstr += mCmd; - if (is_safe(style)) - cmdstr = makesafecmd(cmdstr); - else - cmdstr = "bash -c '" + cmdstr + "'"; + cmdstr = makesafecmd(cmdstr); return cmdstr; } diff --git a/src/utils/execute.hpp b/src/utils/execute.hpp index 987b209..b50bc57 100644 --- a/src/utils/execute.hpp +++ b/src/utils/execute.hpp @@ -13,12 +13,7 @@ enum class cMode { None = 0, Interactive = 1, Silent = 2, - CaptureOutput = 4, - RawCommand = 8 -}; -enum class cStyle { - Safe = 0, - Raw = 1 + CaptureOutput = 4 }; inline cMode operator&(cMode lhs, cMode rhs) {return static_cast(static_cast(lhs) & static_cast(rhs));} @@ -27,10 +22,6 @@ inline cMode operator-(cMode lhs, cMode rhs) {return static_cast(static_c inline cMode operator|(cMode lhs, cMode rhs) {return static_cast(static_cast(lhs) | static_cast(rhs));} inline cMode operator|=(cMode & lhs, cMode rhs) {return lhs = lhs | rhs;} inline bool hasFlag(cMode mode, cMode flag) {return (mode & flag) == flag;} -inline bool is_safe(cStyle style) { return style == cStyle::Safe; } -inline bool is_raw(cStyle style) { return style == cStyle::Raw; } -inline bool is_raw(cMode mode) { return hasFlag(mode, cMode::RawCommand); } -inline cStyle getStyle(cMode mode) { return is_raw(mode) ? cStyle::Raw : cStyle::Safe; } typedef struct sSSHInfo { @@ -63,12 +54,11 @@ class sCommand { const std::map& get_env_vars() const { return mVars; } void add_env_var(const std::string& key, const std::string& value) { mVars[key] = value; } - - - std::string construct_cmd(cStyle style) const; bool empty() const { return mCmd.empty(); } + std::string construct_cmd() const; + private: std::string mDir; std::string mCmd;