Tidy
Some checks failed
Dropshell Test / Build_and_Test (push) Failing after 18s

This commit is contained in:
Your Name 2025-05-12 20:11:08 +12:00
parent df281d2f91
commit 8fc3384c03
13 changed files with 80 additions and 474 deletions

View File

@ -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);
}
// ------------------------------------------------------------------------------------------------

View File

@ -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) );
}
// ------------------------------------------------------------------------------------------------

View File

@ -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<int> 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)

View File

@ -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);

View File

@ -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 <algorithm>
#include <stdexcept>
//
// 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 <typename String, unsigned int line_length>
static std::string encode_with_line_breaks(String s) {
return insert_linebreaks(base64_encode(s, false), line_length);
}
template <typename String>
static std::string encode_pem(String s) {
return encode_with_line_breaks<String, 64>(s);
}
template <typename String>
static std::string encode_mime(String s) {
return encode_with_line_breaks<String, 76>(s);
}
template <typename String>
static std::string encode(String s, bool url) {
return base64_encode(reinterpret_cast<const unsigned char*>(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 <typename String>
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<std::string::value_type>( ( (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<std::string::value_type>( (( 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<std::string::value_type>( ( (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

View File

@ -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 <string>
#if __cplusplus >= 201703L
#include <string_view>
#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 */

View File

@ -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);
}

View File

@ -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<std::st
return false;
}
if (command == "uninstall")
return uninstall();
// if (command == "uninstall")
// return uninstall();
if (command == "ssh") {
interactive_ssh_service();
@ -263,66 +228,6 @@ std::map<std::string, ServiceStatus> 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;
}

View File

@ -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<std::string, ServiceStatus> get_all_services_status(std::string server_name);
static std::string HealthStatus2String(HealthStatus status);
private:
std::string mServer;

42
src/utils/b64ed.cpp Normal file
View File

@ -0,0 +1,42 @@
#include "b64ed.hpp"
#include <vector>
// 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<int> 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;
}

9
src/utils/b64ed.hpp Normal file
View File

@ -0,0 +1,9 @@
#ifndef B64ED_HPP
#define B64ED_HPP
#include <string>
std::string base64_decode(const std::string &in);
std::string base64_encode(const std::string &in);
#endif

View File

@ -9,8 +9,8 @@
#include <libassert/assert.hpp>
#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;
}

View File

@ -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<cMode>(static_cast<int>(lhs) & static_cast<int>(rhs));}
@ -27,10 +22,6 @@ inline cMode operator-(cMode lhs, cMode rhs) {return static_cast<cMode>(static_c
inline cMode operator|(cMode lhs, cMode rhs) {return static_cast<cMode>(static_cast<int>(lhs) | static_cast<int>(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<std::string, std::string>& 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;