Compare commits

..

6 Commits

Author SHA1 Message Date
d8236a58df dropshell release 2025.0519.1727
Some checks failed
Dropshell Test / Build_and_Test (push) Has been cancelled
2025-05-19 17:28:01 +12:00
625de98890 Fix generated files in build, so they don't have to exist when the build starts.
Some checks failed
Dropshell Test / Build_and_Test (push) Has been cancelled
2025-05-19 11:24:42 +12:00
7c1b51a93c Don't include autogen in commits
Some checks failed
Dropshell Test / Build_and_Test (push) Has been cancelled
2025-05-19 11:19:47 +12:00
1be7af571f Remove autogen files. 2025-05-19 11:18:36 +12:00
1439ec2f79 Add dehydrate to build prereq's.
Some checks failed
Dropshell Test / Build_and_Test (push) Has been cancelled
2025-05-19 11:16:57 +12:00
6c3c35bf89 dropshell release 2025.0519.0021
Some checks failed
Dropshell Test / Build_and_Test (push) Has been cancelled
2025-05-19 00:21:34 +12:00
19 changed files with 278 additions and 576 deletions

1
.gitignore vendored
View File

@ -7,6 +7,7 @@ out/
bin/
lib/
output/
autogen/
# Compiled Object files
*.o

View File

@ -48,6 +48,19 @@ add_custom_target(run_createagent ALL
add_executable(dropshell ${SOURCES})
add_dependencies(dropshell run_createagent)
# Mark the generated files as GENERATED so CMake knows they'll be created during build
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/src/autogen/_agent-remote.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/autogen/_agent-local.cpp
PROPERTIES GENERATED TRUE
)
# Explicitly add the generated agent files, as they might not be in the source directory when globbed at the start.
target_sources(dropshell PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/autogen/_agent-remote.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/autogen/_agent-local.cpp
)
# Set include directories
# build dir goes first so that we can use the generated version.hpp
target_include_directories(dropshell PRIVATE

View File

@ -0,0 +1,83 @@
#!/bin/bash
SCRIPT_DIR=$(dirname "$0")
echo "Installing dropshell host agent on this computer..."
# Prints an error message in red and exits with status code 1.
_die() {
echo -e "Error: $1"
exit 1
}
# Checks if listed environment variables are set; calls _die() if any are missing.
_check_required_env_vars() {
local required_vars=("$@")
for var in "${required_vars[@]}"; do
if [ -z "${!var}" ]; then
_die "Required environment variable $var is not set"
fi
done
}
# Checks if Docker is installed, running, and user has permission. Returns 1 on failure.
_check_docker_installed() {
if ! command -v docker &> /dev/null; then
echo "Docker is not installed"
return 1
fi
# check if docker daemon is running
if ! docker info &> /dev/null; then
echo "Docker daemon is not running"
return 1
fi
# check if user has permission to run docker
if ! docker run --rm hello-world &> /dev/null; then
echo "User does not have permission to run docker"
return 1
fi
return 0
}
function install_bb64() {
# check curl installed
if ! command -v curl &> /dev/null; then
_die "Curl is not installed. Curl is required for agent installation."
fi
curl -fsSL "https://gitea.jde.nz/public/bb64/releases/download/latest/install.sh" | bash -s -- "$AGENT_PATH" "$(id -u $USER):$(id -g $USER)"
# test result code from curl
if [ $? -ne 0 ]; then
_die "Failed to install bb64. Curl returned non-zero exit code."
fi
# test if bb64 is installed
"$AGENT_PATH/bb64" -v
if [ $? -ne 0 ]; then
_die "bb64 did not install correctly."
fi
echo "bb64 installed successfully."
return 0;
}
#-------------------------------------------------------------------------
set -a
AGENT_PATH="$SCRIPT_DIR"
set +a
_check_required_env_vars "AGENT_PATH"
echo "Installing host agent into $AGENT_PATH"
_check_docker_installed || _die "Docker is required."
install_bb64

View File

@ -0,0 +1,87 @@
#!/bin/bash
# This script is used to install the dropshell agent on a remote server.
SCRIPT_DIR=$(dirname "$0")
set -a
AGENT_PATH="$SCRIPT_DIR"
set +a
if [ -f "$SCRIPT_DIR/common.sh" ]; then
source "$SCRIPT_DIR/common.sh"
else
echo "Error: common.sh not found in $SCRIPT_DIR"
exit 1
fi
_check_required_env_vars "AGENT_PATH"
function install_bb64() {
curl -fsSL "https://gitea.jde.nz/public/bb64/releases/download/latest/install.sh" | bash -s -- "$AGENT_PATH" "$(id -u $USER):$(id -g $USER)"
# test result code from curl
if [ $? -ne 0 ]; then
_die "Failed to install bb64. Curl returned non-zero exit code."
fi
# test if bb64 is installed
VER=$("$AGENT_PATH/bb64" -v)
if [ $? -ne 0 ]; then
_die "bb64 did not install correctly."
fi
echo "bb64 v$VER installed."
return 0;
}
#-------------------------------------------------------------------------
# Check pre-requisites
# Check if curl is installed
if ! command -v curl &> /dev/null; then
_die "Curl is not installed. Curl is required for agent installation."
fi
# check docker installation
if ! command -v docker &> /dev/null; then
echo "Docker is not installed. Docker is required for agent installation."
exit 1
fi
#-------------------------------------------------------------------------
echo "Installing dropshell agent..."
install_bb64
#-------------------------------------------------------------------------
# confirm we're in a good state.
required_files=(
"$AGENT_PATH/bb64"
"$AGENT_PATH/_allservicesstatus.sh"
"$AGENT_PATH/common.sh"
"$AGENT_PATH/datacommands.sh"
)
# check if all files exist
for file in "${required_files[@]}"; do
if [ ! -f "$file" ]; then
_die "$file does not exist. Please check the installation."
fi
done
#-------------------------------------------------------------------------
echo "Completed dropshell agent installation."
#-------------------------------------------------------------------------
exit 0

View File

@ -1,7 +0,0 @@
#!/bin/bash
echo "Running remote agent self-test..."
echo "Completed remote agent self-test."
exit 0

View File

@ -142,8 +142,12 @@ if [ -n "$SUDO_USER" ] && [ "$SUDO_USER" != "root" ]; then
fi
fi
# check if dehydrate command is installed
if ! command -v dehydrate &> /dev/null; then
curl -fsSL https://gitea.jde.nz/public/dehydrate/releases/download/latest/install.sh | bash
fi
dehydrate -u
print_status "All dependencies installed successfully!"

View File

@ -14,6 +14,7 @@ if ! command -v dehydrate &> /dev/null; then
curl -fsSL https://gitea.jde.nz/public/dehydrate/releases/download/latest/install.sh | bash
fi
SCRIPT_DIR=$(dirname "$0")
mkdir -p "${SCRIPT_DIR}/src/autogen"
dehydrate "${SCRIPT_DIR}/agent" "${SCRIPT_DIR}/src/autogen"
dehydrate "${SCRIPT_DIR}/agent-remote" "${SCRIPT_DIR}/src/autogen"
dehydrate "${SCRIPT_DIR}/agent-local" "${SCRIPT_DIR}/src/autogen"

View File

@ -1,452 +0,0 @@
#include <fstream>
#include <filesystem>
#include <string>
#include <iostream>
#include <cstring>
/*
THIS FILE IS AUTO-GENERATED BY DEHYDRATE.
DO NOT EDIT THIS FILE.
*/
#include "_agent.hpp"
namespace recreate_agent {
// Tiny dependency-free FNV-1a 64-bit hash
static uint64_t fnv1a_64(const void* data, size_t len) {
const uint8_t* p = static_cast<const uint8_t*>(data);
uint64_t h = 0xcbf29ce484222325ULL;
for (size_t i = 0; i < len; ++i)
h = (h ^ p[i]) * 0x100000001b3ULL;
return h;
}
// Base64 decoding function - no dependencies
static void base64_decode(const char* encoded_data, size_t encoded_len, unsigned char* output, size_t* output_len) {
const char* base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
size_t out_pos = 0;
int val = 0, valb = -8;
for (size_t i = 0; i < encoded_len; i++) {
char c = encoded_data[i];
if (c == '=') break;
// Find position in base64_chars
const char* pos = strchr(base64_chars, c);
if (pos == nullptr) continue; // Skip invalid characters
val = (val << 6) + static_cast<int>(pos - base64_chars);
valb += 6;
if (valb >= 0) {
output[out_pos++] = static_cast<unsigned char>((val >> valb) & 0xFF);
valb -= 8;
}
}
*output_len = out_pos;
}
// Utility function to recreate a file with proper permissions
static bool _recreate_file_(const std::filesystem::path& outpath, uint64_t file_hash, std::filesystem::perms file_perms, const unsigned char* filedata, size_t filedata_len) {
namespace fs = std::filesystem;
bool needs_write = false;
// Check if file exists and has correct hash
if (fs::exists(outpath)) {
// Check content hash
std::ifstream in(outpath, std::ios::binary);
std::ostringstream oss;
oss << in.rdbuf();
std::string data = oss.str();
uint64_t existing_hash = fnv1a_64(data.data(), data.size());
needs_write = existing_hash != file_hash;
} else {
needs_write = true; // File doesn't exist, need to create it
}
bool needs_permission_update = true;
if (!needs_write) { // we always update permissions if the file is written or changed. Othewise we check.
fs::perms current_perms = fs::status(outpath).permissions();
needs_permission_update = current_perms != file_perms;
}
if (needs_write) {
fs::create_directories(outpath.parent_path());
std::ofstream out(outpath, std::ios::binary);
out.write(reinterpret_cast<const char*>(filedata), filedata_len);
out.close();
// Set the file permissions
fs::permissions(outpath, file_perms);
if (!fs::exists(outpath)) {
std::cout << "[dehydrate] " << outpath.filename() << ": created\n";
} else {
std::cout << "[dehydrate] " << outpath.filename() << ": updated (hash changed)\n";
}
return true;
}
if (needs_permission_update) {
// Update only permissions
fs::permissions(outpath, file_perms);
std::cout << "[dehydrate] " << outpath.filename() << ": updated (permissions changed)\n";
return true;
}
return false;
}
bool recreate_tree(std::string destination_folder) {
namespace fs = std::filesystem;
bool any_written = false;
{
// File: selftest.sh
fs::path outpath = fs::path(destination_folder) / "selftest.sh";
static const char filedata_base64[] = "IyEvYmluL2Jhc2gKCmVjaG8gIlJ1bm5pbmcgcmVtb3RlIGFnZW50IHNlbGYtdGVzdC4uLiIKCmVj"\
"aG8gIkNvbXBsZXRlZCByZW1vdGUgYWdlbnQgc2VsZi10ZXN0LiIKCmV4aXQgMAo=";
// Decode Base64 data
size_t decoded_size = (strlen(filedata_base64) * 3) / 4;
unsigned char* decoded_data = new unsigned char[decoded_size];
size_t actual_size;
base64_decode(filedata_base64, strlen(filedata_base64), decoded_data, &actual_size);
bool file_written = _recreate_file_(outpath, 11594895391899191874ULL, std::filesystem::perms(493), decoded_data, actual_size);
delete[] decoded_data;
any_written = any_written || file_written;
}
{
// File: datacommands.sh
fs::path outpath = fs::path(destination_folder) / "datacommands.sh";
static const char filedata_base64[] = "IyEvYmluL2Jhc2gKCiMgVGhpcyBzY3JpcHQgY29udGFpbnMgdGhlIGNvbW1vbiBjb2RlIGZvciB0"\
"aGUgYXV0b2NvbW1hbmRzLgoKTVlJRD0kKGlkIC11KQpNWUdSUD0kKGlkIC1nKQoKX2F1dG9jb21t"\
"YW5kcnVuX3ZvbHVtZSgpIHsKICAgIGxvY2FsIGNvbW1hbmQ9IiQxIgogICAgbG9jYWwgdm9sdW1l"\
"X25hbWU9IiQyIgogICAgbG9jYWwgYmFja3VwX2ZvbGRlcj0iJDMiCgogICAgY2FzZSAiJGNvbW1h"\
"bmQiIGluCiAgICAgICAgY3JlYXRlKQogICAgICAgICAgICBlY2hvICJDcmVhdGluZyB2b2x1bWUg"\
"JHt2b2x1bWVfbmFtZX0iCiAgICAgICAgICAgIGRvY2tlciB2b2x1bWUgY3JlYXRlICR7dm9sdW1l"\
"X25hbWV9CiAgICAgICAgICAgIDs7CiAgICAgICAgbnVrZSkKICAgICAgICAgICAgZWNobyAiTnVr"\
"aW5nIHZvbHVtZSAke3ZvbHVtZV9uYW1lfSIKICAgICAgICAgICAgZG9ja2VyIHZvbHVtZSBybSAk"\
"e3ZvbHVtZV9uYW1lfQogICAgICAgICAgICA7OwogICAgICAgIGJhY2t1cCkKICAgICAgICAgICAg"\
"ZWNobyAiQmFja2luZyB1cCB2b2x1bWUgJHt2b2x1bWVfbmFtZX0iCiAgICAgICAgICAgIGRvY2tl"\
"ciBydW4gLS1ybSAtdiAke3ZvbHVtZV9uYW1lfTovdm9sdW1lIC12ICR7YmFja3VwX2ZvbGRlcn06"\
"L2JhY2t1cCBkZWJpYW4gYmFzaCAtYyAidGFyIC1jenZmIC9iYWNrdXAvYmFja3VwLnRneiAtQyAv"\
"dm9sdW1lIC4gJiYgY2hvd24gLVIgJE1ZSUQ6JE1ZR1JQIC9iYWNrdXAiCiAgICAgICAgICAgIDs7"\
"CiAgICAgICAgcmVzdG9yZSkKICAgICAgICAgICAgZWNobyAiUmVzdG9yaW5nIHZvbHVtZSAke3Zv"\
"bHVtZV9uYW1lfSIKICAgICAgICAgICAgZG9ja2VyIHZvbHVtZSBybSAke3ZvbHVtZV9uYW1lfQog"\
"ICAgICAgICAgICBkb2NrZXIgdm9sdW1lIGNyZWF0ZSAke3ZvbHVtZV9uYW1lfQogICAgICAgICAg"\
"ICBkb2NrZXIgcnVuIC0tcm0gLXYgJHt2b2x1bWVfbmFtZX06L3ZvbHVtZSAtdiAke2JhY2t1cF9m"\
"b2xkZXJ9Oi9iYWNrdXAgZGViaWFuIGJhc2ggLWMgInRhciAteHp2ZiAvYmFja3VwL2JhY2t1cC50"\
"Z3ogLUMgL3ZvbHVtZSAtLXN0cmlwLWNvbXBvbmVudHM9MSIKICAgICAgICAgICAgOzsKICAgIGVz"\
"YWMKfSAgIAoKX2F1dG9jb21tYW5kcnVuX3BhdGgoKSB7CiAgICBsb2NhbCBjb21tYW5kPSIkMSIK"\
"ICAgIGxvY2FsIHBhdGg9IiQyIgogICAgbG9jYWwgYmFja3VwX2ZvbGRlcj0iJDMiCgogICAgY2Fz"\
"ZSAiJGNvbW1hbmQiIGluCiAgICAgICAgY3JlYXRlKQogICAgICAgICAgICBlY2hvICJDcmVhdGlu"\
"ZyBwYXRoICR7cGF0aH0iCiAgICAgICAgICAgIG1rZGlyIC1wICR7cGF0aH0KICAgICAgICAgICAg"\
"OzsKICAgICAgICBudWtlKQogICAgICAgICAgICBlY2hvICJOdWtpbmcgcGF0aCAke3BhdGh9Igog"\
"ICAgICAgICAgICBsb2NhbCBwYXRoX3BhcmVudD0kKGRpcm5hbWUgJHtwYXRofSkKICAgICAgICAg"\
"ICAgbG9jYWwgcGF0aF9jaGlsZD0kKGJhc2VuYW1lICR7cGF0aH0pCiAgICAgICAgICAgIGlmIFsg"\
"LWQgIiR7cGF0aF9wYXJlbnR9LyR7cGF0aF9jaGlsZH0iIF07IHRoZW4KICAgICAgICAgICAgICAg"\
"IGRvY2tlciBydW4gLS1ybSAtdiAke3BhdGhfcGFyZW50fTovdm9sdW1lIGRlYmlhbiBiYXNoIC1j"\
"ICJybSAtcmZ2IC92b2x1bWUvJHtwYXRoX2NoaWxkfSIgfHwgZWNobyAiRmFpbGVkIHRvIG51a2Ug"\
"cGF0aCAke3BhdGh9IgogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICBlY2hvICJQYXRo"\
"ICR7cGF0aH0gZG9lcyBub3QgZXhpc3QgLSBub3RoaW5nIHRvIG51a2UiCiAgICAgICAgICAgIGZp"\
"CiAgICAgICAgICAgIDs7CiAgICAgICAgYmFja3VwKQogICAgICAgICAgICBlY2hvICJCYWNraW5n"\
"IHVwIHBhdGggJHtwYXRofSIKICAgICAgICAgICAgaWYgWyAtZCAiJHtwYXRofSIgXTsgdGhlbgog"\
"ICAgICAgICAgICAgICAgZG9ja2VyIHJ1biAtLXJtIC12ICR7cGF0aH06L3BhdGggLXYgJHtiYWNr"\
"dXBfZm9sZGVyfTovYmFja3VwIGRlYmlhbiBiYXNoIC1jICJ0YXIgLWN6dmYgL2JhY2t1cC9iYWNr"\
"dXAudGd6IC1DIC9wYXRoIC4gJiYgY2hvd24gLVIgJE1ZSUQ6JE1ZR1JQIC9iYWNrdXAiCiAgICAg"\
"ICAgICAgIGVsc2UKICAgICAgICAgICAgICAgIGVjaG8gIlBhdGggJHtwYXRofSBkb2VzIG5vdCBl"\
"eGlzdCAtIG5vdGhpbmcgdG8gYmFja3VwIgogICAgICAgICAgICBmaQogICAgICAgICAgICA7Owog"\
"ICAgICAgIHJlc3RvcmUpCiAgICAgICAgICAgIGlmIFsgISAtZiAiJHtiYWNrdXBfZm9sZGVyfS9i"\
"YWNrdXAudGd6IiBdOyB0aGVuCiAgICAgICAgICAgICAgICBlY2hvICJCYWNrdXAgZmlsZSAke2Jh"\
"Y2t1cF9mb2xkZXJ9L2JhY2t1cC50Z3ogZG9lcyBub3QgZXhpc3QgLSBub3RoaW5nIHRvIHJlc3Rv"\
"cmUiCiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgIGVjaG8gIkNsZWFyaW5nIGV4aXN0"\
"aW5nIGRhdGEgaW4gcGF0aCAke3BhdGh9IgogICAgICAgICAgICAgICAgZG9ja2VyIHJ1biAtLXJt"\
"IC12ICR7cGF0aH06L3BhdGggZGViaWFuIGJhc2ggLWMgInJtIC1yZnYgL3BhdGgveyosLip9Igog"\
"ICAgICAgICAgICAgICAgZWNobyAiUmVzdG9yaW5nIHBhdGggJHtwYXRofSBmcm9tIGJhY2t1cCBm"\
"aWxlICR7YmFja3VwX2ZvbGRlcn0vYmFja3VwLnRneiIKICAgICAgICAgICAgICAgIHRhciAteHp2"\
"ZiAke2JhY2t1cF9mb2xkZXJ9L2JhY2t1cC50Z3ogLUMgJHtwYXRofSAtLXN0cmlwLWNvbXBvbmVu"\
"dHM9MQogICAgICAgICAgICBmaQogICAgICAgICAgICA7OwogICAgZXNhYwp9CgpfYXV0b2NvbW1h"\
"bmRydW5fZmlsZSgpIHsKICAgIGxvY2FsIGNvbW1hbmQ9IiQxIgogICAgbG9jYWwgZmlsZXBhdGg9"\
"IiQyIgogICAgbG9jYWwgYmFja3VwX2ZvbGRlcj0iJDMiCgogICAgY2FzZSAiJGNvbW1hbmQiIGlu"\
"CiAgICAgICAgY3JlYXRlKQogICAgICAgICAgICA7OwogICAgICAgIG51a2UpCiAgICAgICAgICAg"\
"IHJtIC1mICR7ZmlsZXBhdGh9CiAgICAgICAgICAgIDs7CiAgICAgICAgYmFja3VwKQogICAgICAg"\
"ICAgICBlY2hvICJCYWNraW5nIHVwIGZpbGUgJHtmaWxlcGF0aH0iCiAgICAgICAgICAgIGxvY2Fs"\
"IGZpbGVfcGFyZW50PSQoZGlybmFtZSAke2ZpbGVwYXRofSkKICAgICAgICAgICAgbG9jYWwgZmls"\
"ZV9uYW1lPSQoYmFzZW5hbWUgJHtmaWxlcGF0aH0pCiAgICAgICAgICAgIGlmIFsgLWYgIiR7Zmls"\
"ZV9wYXJlbnR9LyR7ZmlsZV9uYW1lfSIgXTsgdGhlbgogICAgICAgICAgICAgICAgZG9ja2VyIHJ1"\
"biAtLXJtIC12ICR7ZmlsZV9wYXJlbnR9Oi92b2x1bWUgLXYgJHtiYWNrdXBfZm9sZGVyfTovYmFj"\
"a3VwIGRlYmlhbiBiYXNoIC1jICJjcCAvdm9sdW1lLyR7ZmlsZV9uYW1lfSAvYmFja3VwLyR7Zmls"\
"ZV9uYW1lfSAmJiBjaG93biAtUiAkTVlJRDokTVlHUlAgL2JhY2t1cCIKICAgICAgICAgICAgZWxz"\
"ZQogICAgICAgICAgICAgICAgZWNobyAiRmlsZSAke2ZpbGVwYXRofSBkb2VzIG5vdCBleGlzdCAt"\
"IG5vdGhpbmcgdG8gYmFja3VwIgogICAgICAgICAgICBmaQogICAgICAgICAgICA7OwogICAgICAg"\
"IHJlc3RvcmUpCiAgICAgICAgICAgIGVjaG8gIlJlc3RvcmluZyBmaWxlICR7ZmlsZXBhdGh9Igog"\
"ICAgICAgICAgICBsb2NhbCBmaWxlX25hbWU9JChiYXNlbmFtZSAke2ZpbGVwYXRofSkKICAgICAg"\
"ICAgICAgcm0gLWYgJHtmaWxlcGF0aH0gfHwgZGllICJVbmFibGUgdG8gcmVtb3ZlIGV4aXN0aW5n"\
"IGZpbGUgJHtmaWxlcGF0aH0sIHJlc3RvcmUgZmFpbGVkLiIKICAgICAgICAgICAgY3AgJHtiYWNr"\
"dXBfZm9sZGVyfS8ke2ZpbGVfbmFtZX0gJHtmaWxlcGF0aH0gfHwgZGllICJVbmFibGUgdG8gY29w"\
"eSBmaWxlICR7YmFja3VwX2ZvbGRlcn0vJHtmaWxlX25hbWV9IHRvICR7ZmlsZXBhdGh9LCByZXN0"\
"b3JlIGZhaWxlZC4iCiAgICAgICAgICAgIDs7CiAgICBlc2FjCn0KCl9hdXRvY29tbWFuZHBhcnNl"\
"KCkgewogICAgIyBmaXJzdCBhcmd1bWVudCBpcyB0aGUgY29tbWFuZAogICAgIyBpZiB0aGUgY29t"\
"bWFuZCBpcyBiYWNrdXAgb3IgcmVzdG9yZSwgdGhlbiB0aGUgbGFzdCB0d28gYXJndW1lbnRzIGFy"\
"ZSB0aGUgYmFja3VwIGZpbGUgYW5kIHRoZSB0ZW1wb3JhcnkgcGF0aAogICAgIyBhbGwgb3RoZXIg"\
"YXJndW1lbnRzIGFyZSBvZiBmb3JtOgogICAgIyBrZXk9dmFsdWUKICAgICMgd2hlcmUga2V5IGNh"\
"biBiZSBvbmUgb2Ygdm9sdW1lLCBwYXRoIG9yIGZpbGUuCiAgICAjIHZhbHVlIGlzIHRoZSBwYXRo"\
"IG9yIHZvbHVtZSBuYW1lLgoKICAgICMgd2UgaXRlcmF0ZSBvdmVyIHRoZSBrZXk9dmFsdWUgYXJn"\
"dW1lbnRzLCBhbmQgZm9yIGVhY2ggd2UgY2FsbDoKICAgICMgICAgYXV0b3J1biA8Y29tbWFuZD4g"\
"PGJhY2t1cGZpbGU+IDxrZXk+IDx2YWx1ZT4KCiAgICBsb2NhbCBjb21tYW5kPSIkMSIKICAgIHNo"\
"aWZ0CgogICAgbG9jYWwgYmFja3VwX3RlbXBfcGF0aD0iJDEiCiAgICBzaGlmdAoKICAgIGVjaG8g"\
"ImF1dG9jb21tYW5kcGFyc2U6IGNvbW1hbmQ9JGNvbW1hbmQgYmFja3VwX3RlbXBfcGF0aD0kYmFj"\
"a3VwX3RlbXBfcGF0aCIKCiAgICAjIEV4dHJhY3QgdGhlIGJhY2t1cCBmaWxlIGFuZCB0ZW1wIHBh"\
"dGggKGxhc3QgdHdvIGFyZ3VtZW50cykKICAgIGxvY2FsIGFyZ3M9KCIkQCIpCiAgICBsb2NhbCBh"\
"cmdfY291bnQ9JHsjYXJnc1tAXX0KICAgIAogICAgIyBQcm9jZXNzIGFsbCBrZXk9dmFsdWUgcGFp"\
"cnMKICAgIGZvciAoKGk9MDsgaTwkYXJnX2NvdW50OyBpKyspKTsgZG8KICAgICAgICBsb2NhbCBw"\
"YWlyPSIke2FyZ3NbJGldfSIKICAgICAgICAKICAgICAgICAjIFNraXAgaWYgbm90IGluIGtleT12"\
"YWx1ZSBmb3JtYXQKICAgICAgICBpZiBbWyAiJHBhaXIiICE9ICoiPSIqIF1dOyB0aGVuCiAgICAg"\
"ICAgICAgIGNvbnRpbnVlCiAgICAgICAgZmkKICAgICAgICAKICAgICAgICBsb2NhbCBrZXk9IiR7"\
"cGFpciUlPSp9IgogICAgICAgIGxvY2FsIHZhbHVlPSIke3BhaXIjKj19IgoKICAgICAgICAjIGNy"\
"ZWF0ZSBiYWNrdXAgZm9sZGVyIHVuaXF1ZSB0byBrZXkvdmFsdWUuCiAgICAgICAgbG9jYWwgYmZv"\
"bGRlcj0kKGVjaG8gIiR7a2V5fV8ke3ZhbHVlfSIgfCB0ciAtY2QgJ1s6YWxudW06XV8tJykKICAg"\
"ICAgICBsb2NhbCB0YXJnZXRwYXRoPSIke2JhY2t1cF90ZW1wX3BhdGh9LyR7YmZvbGRlcn0iCiAg"\
"ICAgICAgbWtkaXIgLXAgJHt0YXJnZXRwYXRofQoKICAgICAgICAjIEtleSBtdXN0IGJlIG9uZSBv"\
"ZiB2b2x1bWUsIHBhdGggb3IgZmlsZQogICAgICAgIGNhc2UgIiRrZXkiIGluCiAgICAgICAgICAg"\
"IHZvbHVtZSkKICAgICAgICAgICAgICAgIF9hdXRvY29tbWFuZHJ1bl92b2x1bWUgIiRjb21tYW5k"\
"IiAiJHZhbHVlIiAiJHRhcmdldHBhdGgiCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBw"\
"YXRoKQogICAgICAgICAgICAgICAgX2F1dG9jb21tYW5kcnVuX3BhdGggIiRjb21tYW5kIiAiJHZh"\
"bHVlIiAiJHRhcmdldHBhdGgiCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBmaWxlKQog"\
"ICAgICAgICAgICAgICAgX2F1dG9jb21tYW5kcnVuX2ZpbGUgIiRjb21tYW5kIiAiJHZhbHVlIiAi"\
"JHRhcmdldHBhdGgiCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICAqKQogICAgICAgICAg"\
"ICAgICAgX2RpZSAiVW5rbm93biBrZXkgJGtleSBwYXNzZWQgdG8gYXV0byR7Y29tbWFuZH0uIFdl"\
"IG9ubHkgc3VwcG9ydCB2b2x1bWUsIHBhdGggYW5kIGZpbGUuIgogICAgICAgICAgICAgICAgOzsK"\
"ICAgICAgICBlc2FjCiAgICBkb25lCn0KCgpkYXRhY3JlYXRlKCkgewogICAgX2F1dG9jb21tYW5k"\
"cGFyc2UgY3JlYXRlIG5vbmUgIiRAIgp9CgoKZGF0YW51a2UoKSB7CiAgICBfYXV0b2NvbW1hbmRw"\
"YXJzZSBudWtlIG5vbmUgIiRAIgp9CgpkYXRhYmFja3VwKCkgewogICAgX2NoZWNrX3JlcXVpcmVk"\
"X2Vudl92YXJzICJCQUNLVVBfRklMRSIgIlRFTVBfRElSIgogICAgQkFDS1VQX1RFTVBfUEFUSD0i"\
"JFRFTVBfRElSL2JhY2t1cCIKCgogICAgbWtkaXIgLXAgIiRCQUNLVVBfVEVNUF9QQVRIIgogICAg"\
"ZWNobyAiX2F1dG9jb21tYW5kcGFyc2UgW2JhY2t1cF0gWyRCQUNLVVBfVEVNUF9QQVRIXSBbJEBd"\
"IgogICAgX2F1dG9jb21tYW5kcGFyc2UgYmFja3VwICIkQkFDS1VQX1RFTVBfUEFUSCIgIiRAIgoK"\
"ICAgIHRhciB6Y3ZmICIkQkFDS1VQX0ZJTEUiIC1DICIkQkFDS1VQX1RFTVBfUEFUSCIgLgp9Cgpk"\
"YXRhcmVzdG9yZSgpIHsKICAgIF9jaGVja19yZXF1aXJlZF9lbnZfdmFycyAiQkFDS1VQX0ZJTEUi"\
"ICJURU1QX0RJUiIKICAgIEJBQ0tVUF9URU1QX1BBVEg9IiRURU1QX0RJUi9yZXN0b3JlIgoKICAg"\
"IGVjaG8gIl9hdXRvY29tbWFuZHBhcnNlIFtyZXN0b3JlXSBbJEJBQ0tVUF9URU1QX1BBVEhdIFsk"\
"QF0iCgogICAgbWtkaXIgLXAgIiRCQUNLVVBfVEVNUF9QQVRIIgogICAgdGFyIHp4dmYgIiRCQUNL"\
"VVBfRklMRSIgLUMgIiRCQUNLVVBfVEVNUF9QQVRIIiAtLXN0cmlwLWNvbXBvbmVudHM9MQoKICAg"\
"IF9hdXRvY29tbWFuZHBhcnNlIHJlc3RvcmUgIiRCQUNLVVBfVEVNUF9QQVRIIiAiJEAiCn0K";
// Decode Base64 data
size_t decoded_size = (strlen(filedata_base64) * 3) / 4;
unsigned char* decoded_data = new unsigned char[decoded_size];
size_t actual_size;
base64_decode(filedata_base64, strlen(filedata_base64), decoded_data, &actual_size);
bool file_written = _recreate_file_(outpath, 12213965674971673660ULL, std::filesystem::perms(493), decoded_data, actual_size);
delete[] decoded_data;
any_written = any_written || file_written;
}
{
// File: _allservicesstatus.sh
fs::path outpath = fs::path(destination_folder) / "_allservicesstatus.sh";
static const char filedata_base64[] = "IyEvYmluL2Jhc2gKCiMgVGhpcyBzY3JpcHQgY2hlY2tzIEFMTCBzZXJ2aWNlcyBvbiB0aGUgc2Vy"\
"dmVyIGFuZCByZXR1cm5zIGEgc3RhdHVzIGZvciBlYWNoLgoKIyBSZXR1cm4gZm9ybWF0IGlzIHNp"\
"bXBsZSBFTlYgd2l0aCB0aGUgZm9sbG93aW5nIGZvcm1hdDoKIyBTRVJWSUNFX05BTUVfSEVBTFRI"\
"PWhlYWx0aHl8dW5oZWFsdGh5fHVua25vd24KIyBTRVJWSUNFX05BTUVfUE9SVFM9cG9ydDEscG9y"\
"dDIscG9ydDMKCiMgR2V0IGFsbCBzZXJ2aWNlcyBvbiB0aGUgc2VydmVyClNDUklQVF9ESVI9IiQo"\
"ZGlybmFtZSAiJDAiKSIKCiAgICAjIC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t"\
"LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t"\
"LS0tLS0tCiAgICAjIC8vIHJlbW90ZSBwYXRocwogICAgIyAvLyBEUk9QU0hFTExfRElSCiAgICAj"\
"IC8vICAgfC0tIGJhY2t1cHMKICAgICMgLy8gICB8LS0gdGVtcF9maWxlcwogICAgIyAvLyAgIHwt"\
"LSBhZ2VudAogICAgIyAvLyAgIHwgICB8LS0gYmI2NAogICAgIyAvLyAgIHwgICB8LS0gKG90aGVy"\
"IGFnZW50IGZpbGVzLCBpbmNsdWRpbmcgX2FsbHNlcnZpY2Vzc3RhdHVzLnNoKQogICAgIyAvLyAg"\
"IHwtLSBzZXJ2aWNlcwogICAgIyAvLyAgICAgICB8LS0gc2VydmljZSBuYW1lCiAgICAjIC8vICAg"\
"ICAgICAgICB8LS0gY29uZmlnCiAgICAjIC8vICAgICAgICAgICAgICAgfC0tIHNlcnZpY2UuZW52"\
"IChhY3R1YWwgc2VydmljZSBjb25maWcpCiAgICAjIC8vICAgICAgICAgICAgICAgfC0tIC50ZW1w"\
"bGF0ZV9pbmZvLmVudgogICAgIyAvLyAgICAgICAgICAgfC0tIHRlbXBsYXRlCiAgICAjIC8vICAg"\
"ICAgICAgICAgICAgfC0tIF9kZWZhdWx0LmVudgogICAgIyAvLyAgICAgICAgICAgICAgIHwtLSAo"\
"c2NyaXB0IGZpbGVzKQogICAgIyAvLyAgICAgICAgICAgICAgIHwtLSBjb25maWcKICAgICMgLy8g"\
"ICAgICAgICAgICAgICAgICAgfC0tIHNlcnZpY2UuZW52IChkZWZhdWx0IHNlcnZpY2UgY29uZmln"\
"KQogICAgIyAvLyAgICAgICAgICAgICAgICAgICB8LS0gLnRlbXBsYXRlX2luZm8uZW52CiAgICAj"\
"IC8vICAgICAgICAgICAgICAgICAgIHwtLSAob3RoZXIgY29uZmlnIGZpbGVzIGZvciBzcGVjaWZp"\
"YyBzZXJ2ZXImc2VydmljZSkKCiMgR2V0IGFsbCBzZXJ2aWNlcyBvbiB0aGUgc2VydmVyClNFUlZJ"\
"Q0VTX1BBVEg9JChyZWFscGF0aCAiJHtTQ1JJUFRfRElSfS8uLi9zZXJ2aWNlcy8iKQoKQ1VSUkVO"\
"VF9PVVRQVVQ9IiIKQ1VSUkVOVF9FWElUX0NPREU9MAoKbG9hZF9kb3RlbnYoKXsKICAgIGxvY2Fs"\
"IGZpbGVfcGF0aD0kMQogICAgaWYgWyAtZiAiJHtmaWxlX3BhdGh9IiBdOyB0aGVuCiAgICAgICAg"\
"c291cmNlICIke2ZpbGVfcGF0aH0iCiAgICBmaQp9CgpfY2hlY2tfcmVxdWlyZWRfZW52X3ZhcnNf"\
"YWxsc2VydmljZXNzdGF0dXMoKSB7CiAgICBsb2NhbCByZXF1aXJlZF92YXJzPSgiJEAiKQogICAg"\
"Zm9yIHZhciBpbiAiJHtyZXF1aXJlZF92YXJzW0BdfSI7IGRvCiAgICAgICAgaWYgWyAteiAiJHsh"\
"dmFyfSIgXTsgdGhlbgogICAgICAgICAgICBfZGllICJSZXF1aXJlZCBlbnZpcm9ubWVudCB2YXJp"\
"YWJsZSAkdmFyIGlzIG5vdCBzZXQiCiAgICAgICAgZmkKICAgIGRvbmUKfQoKZnVuY3Rpb24gcnVu"\
"X2NvbW1hbmQoKSB7CiAgICBsb2NhbCBzZXJ2aWNlX3BhdGg9JDEKICAgIGxvY2FsIGNvbW1hbmQ9"\
"JDIKICAgIGxvY2FsIGNhcHR1cmVfb3V0cHV0PSR7MzotZmFsc2V9ICAjIGRlZmF1bHQgdG8gZmFs"\
"c2UgaWYgbm90IHNwZWNpZmllZAoKICAgICMgY2hlY2sgaWYgdGhlIGNvbW1hbmQgaXMgYSBmaWxl"\
"CiAgICBpZiBbICEgLWYgIiR7c2VydmljZV9wYXRofS90ZW1wbGF0ZS8ke2NvbW1hbmR9LnNoIiBd"\
"OyB0aGVuCiAgICAgICAgcmV0dXJuOwogICAgZmkKCiAgICAjIHJ1biB0aGUgY29tbWFuZCBpbiBh"\
"IHN1YnNoZWxsIHRvIHByZXZlbnQgZW52aXJvbm1lbnQgY2hhbmdlcwogICAgQ1VSUkVOVF9PVVRQ"\
"VVQ9JCgKICAgICAgICBzZXQgLWEKCiAgICAgICAgbG9hZF9kb3RlbnYgIiR7c2VydmljZV9wYXRo"\
"fS90ZW1wbGF0ZS9fZGVmYXVsdC5lbnYiCiAgICAgICAgbG9hZF9kb3RlbnYgIiR7c2VydmljZV9w"\
"YXRofS9jb25maWcvc2VydmljZS5lbnYiCiAgICAgICAgbG9hZF9kb3RlbnYgIiR7c2VydmljZV9w"\
"YXRofS9jb25maWcvLnRlbXBsYXRlX2luZm8uZW52IgoKICAgICAgICAjIHVwZGF0ZSB0aGUgbWFp"\
"biB2YXJpYWJsZXMuCiAgICAgICAgQ09ORklHX1BBVEg9IiR7c2VydmljZV9wYXRofS9jb25maWci"\
"CiAgICAgICAgU0VSVklDRT0iJHtTRVJWSUNFX05BTUV9IgogICAgICAgIERPQ0tFUl9DTElfSElO"\
"VFM9ZmFsc2UKCiAgICAgICAgc2V0ICthCgogICAgICAgIF9jaGVja19yZXF1aXJlZF9lbnZfdmFy"\
"c19hbGxzZXJ2aWNlc3N0YXR1cyAiQ09ORklHX1BBVEgiICJTRVJWRVIiICJTRVJWSUNFIiAiQUdF"\
"TlRfUEFUSCIgIkhPU1RfTkFNRSIgIlRFTVBMQVRFIgoKICAgICAgICBpZiBbICIkY2FwdHVyZV9v"\
"dXRwdXQiID0gInRydWUiIF07IHRoZW4KICAgICAgICAgICAgIyBDYXB0dXJlIGFuZCByZXR1cm4g"\
"b3V0cHV0CiAgICAgICAgICAgIGJhc2ggIiR7c2VydmljZV9wYXRofS90ZW1wbGF0ZS8ke2NvbW1h"\
"bmR9LnNoIiAyPiYxCiAgICAgICAgZWxzZQogICAgICAgICAgICAjIFJ1biBzaWxlbnRseSBhbmQg"\
"cmV0dXJuIGV4aXQgY29kZQogICAgICAgICAgICBiYXNoICIke3NlcnZpY2VfcGF0aH0vdGVtcGxh"\
"dGUvJHtjb21tYW5kfS5zaCIgPiAvZGV2L251bGwgMj4mMQogICAgICAgIGZpCiAgICApCiAgICBD"\
"VVJSRU5UX0VYSVRfQ09ERT0kPwp9CgpmdW5jdGlvbiBjb21tYW5kX2V4aXN0cygpIHsKICAgIGxv"\
"Y2FsIHNlcnZpY2VfcGF0aD0kMQogICAgbG9jYWwgY29tbWFuZD0kMgogICAgaWYgWyAhIC1mICIk"\
"e3NlcnZpY2VfcGF0aH0vdGVtcGxhdGUvJHtjb21tYW5kfS5zaCIgXTsgdGhlbgogICAgICAgIHJl"\
"dHVybiAxCiAgICBmaQogICAgcmV0dXJuIDAKfQoKCmlmIFsgISAtZCAiJHtTRVJWSUNFU19QQVRI"\
"fSIgXTsgdGhlbgogICAgZWNobyAiU2VydmljZXMgcGF0aCBkb2VzIG5vdCBleGlzdDogJHtTRVJW"\
"SUNFU19QQVRIfSIKICAgIGV4aXQgMApmaQoKIyBHZXQgYWxsIHNlcnZpY2UgbmFtZXMKU0VSVklD"\
"RV9OQU1FUz0kKGxzICIke1NFUlZJQ0VTX1BBVEh9IikKCiMgSXRlcmF0ZSBvdmVyIGFsbCBzZXJ2"\
"aWNlIG5hbWVzCmZvciBTRVJWSUNFX05BTUUgaW4gJHtTRVJWSUNFX05BTUVTfTsgZG8KCiAgICBT"\
"RVJWSUNFX1BBVEg9JChyZWFscGF0aCAiJHtTRVJWSUNFU19QQVRIfS8ke1NFUlZJQ0VfTkFNRX0i"\
"KQoKICAgICMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICAgIyBHZXQgdGhlIHNl"\
"cnZpY2UgaGVhbHRoCiAgICBpZiAhIGNvbW1hbmRfZXhpc3RzICIke1NFUlZJQ0VfUEFUSH0iICJz"\
"dGF0dXMiOyB0aGVuCiAgICAgICAgU0VSVklDRV9IRUFMVEg9InVua25vd24iCiAgICBlbHNlCiAg"\
"ICAgICAgcnVuX2NvbW1hbmQgIiR7U0VSVklDRV9QQVRIfSIgInN0YXR1cyIgImZhbHNlIgogICAg"\
"ICAgIGlmIFsgIiR7Q1VSUkVOVF9FWElUX0NPREV9IiAtZXEgMCBdOyB0aGVuCiAgICAgICAgICAg"\
"IFNFUlZJQ0VfSEVBTFRIPSJoZWFsdGh5IgogICAgICAgIGVsc2UKICAgICAgICAgICAgU0VSVklD"\
"RV9IRUFMVEg9InVuaGVhbHRoeSIKICAgICAgICBmaQogICAgZmkKCiAgICAjLS0tLS0tLS0tLS0t"\
"LS0tLS0tLS0tLS0tLS0tLS0tLS0KICAgICMgR2V0IHRoZSBzZXJ2aWNlIHBvcnRzCiAgICBpZiAh"\
"IGNvbW1hbmRfZXhpc3RzICIke1NFUlZJQ0VfUEFUSH0iICJwb3J0cyI7IHRoZW4KICAgICAgICBT"\
"RVJWSUNFX1BPUlRTPSIiCiAgICBlbHNlCiAgICAgICAgcnVuX2NvbW1hbmQgIiR7U0VSVklDRV9Q"\
"QVRIfSIgInBvcnRzIiAidHJ1ZSIKICAgICAgICBTRVJWSUNFX1BPUlRTPSIke0NVUlJFTlRfT1VU"\
"UFVUfSIKICAgIGZpCgogICAgIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgICAj"\
"IHJldHVybiB0aGUgaGVhbHRoIGFuZCBwb3J0cwogICAgZWNobyAiJHtTRVJWSUNFX05BTUV9X0hF"\
"QUxUSD0ke1NFUlZJQ0VfSEVBTFRIfSIKICAgIGVjaG8gIiR7U0VSVklDRV9OQU1FfV9QT1JUUz0k"\
"e1NFUlZJQ0VfUE9SVFN9Igpkb25lCg==";
// Decode Base64 data
size_t decoded_size = (strlen(filedata_base64) * 3) / 4;
unsigned char* decoded_data = new unsigned char[decoded_size];
size_t actual_size;
base64_decode(filedata_base64, strlen(filedata_base64), decoded_data, &actual_size);
bool file_written = _recreate_file_(outpath, 4669115953916396805ULL, std::filesystem::perms(493), decoded_data, actual_size);
delete[] decoded_data;
any_written = any_written || file_written;
}
{
// File: common.sh
fs::path outpath = fs::path(destination_folder) / "common.sh";
static const char filedata_base64[] = "IyBDT01NT04gRlVOQ1RJT05TCiMgSkRFCiMgMjAyNS0wNS0wMwoKIyBUaGlzIGZpbGUgaXMgYXZh"\
"aWxhYmxlIFRPICoqKkFMTCoqKiB0ZW1wbGF0ZXMsIGFzICR7QUdFTlRfUEFUSH0vX2NvbW1vbi5z"\
"aAoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t"\
"LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgoj"\
"IHN1bW1hcnkgb2YgZnVuY3Rpb25zOgojICAgX2RpZSAibWVzc2FnZSIgICAgICAgICAgICAgICAg"\
"ICAgICAgICAgOiBQcmludHMgYW4gZXJyb3IgbWVzc2FnZSBpbiByZWQgYW5kIGV4aXRzIHdpdGgg"\
"c3RhdHVzIGNvZGUgMS4KIyAgIF9ncmV5X3N0YXJ0ICAgICAgICAgICAgICAgICAgICAgICAgICAg"\
"IDogU3dpdGNoZXMgdGVybWluYWwgb3V0cHV0IGNvbG9yIHRvIGdyZXkuCiMgICBfZ3JleV9lbmQg"\
"ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IFJlc2V0cyB0ZXJtaW5hbCBvdXRwdXQgY29s"\
"b3IgZnJvbSBncmV5LgojICAgX2NyZWF0ZV9hbmRfc3RhcnRfY29udGFpbmVyICI8cnVuX2NtZD4i"\
"IDxjb250YWluZXJfbmFtZT4gOiBDcmVhdGVzL3N0YXJ0cyBhIGNvbnRhaW5lciwgdmVyaWZ5aW5n"\
"IGl0IHJ1bnMuCiMgICBfY3JlYXRlX2ZvbGRlciA8Zm9sZGVyX3BhdGg+ICAgICAgICAgICA6IENy"\
"ZWF0ZXMgYSBkaXJlY3RvcnkgaWYgaXQgZG9lc24ndCBleGlzdCAoY2htb2QgNzc3KS4KIyAgIF9j"\
"aGVja19kb2NrZXJfaW5zdGFsbGVkICAgICAgICAgICAgICAgOiBDaGVja3MgaWYgRG9ja2VyIGlz"\
"IGluc3RhbGxlZCwgcnVubmluZywgYW5kIHVzZXIgaGFzIHBlcm1pc3Npb24uIFJldHVybnMgMSBv"\
"biBmYWlsdXJlLgojICAgX2lzX2NvbnRhaW5lcl9leGlzdHMgPGNvbnRhaW5lcl9uYW1lPiA6IENo"\
"ZWNrcyBpZiBhIGNvbnRhaW5lciAoYW55IHN0YXRlKSBleGlzdHMuIFJldHVybnMgMSBpZiBub3Qg"\
"Zm91bmQuCiMgICBfaXNfY29udGFpbmVyX3J1bm5pbmcgPGNvbnRhaW5lcl9uYW1lPjogQ2hlY2tz"\
"IGlmIGEgY29udGFpbmVyIGlzIGN1cnJlbnRseSBydW5uaW5nLiBSZXR1cm5zIDEgaWYgbm90IHJ1"\
"bm5pbmcuCiMgICBfZ2V0X2NvbnRhaW5lcl9pZCA8Y29udGFpbmVyX25hbWU+ICAgIDogUHJpbnRz"\
"IHRoZSBJRCBvZiB0aGUgbmFtZWQgY29udGFpbmVyLgojICAgX2dldF9jb250YWluZXJfc3RhdHVz"\
"IDxjb250YWluZXJfbmFtZT46IFByaW50cyB0aGUgc3RhdHVzIHN0cmluZyBvZiB0aGUgbmFtZWQg"\
"Y29udGFpbmVyLgojICAgX3N0YXJ0X2NvbnRhaW5lciA8Y29udGFpbmVyX25hbWU+ICAgICA6IFN0"\
"YXJ0cyBhbiBleGlzdGluZywgc3RvcHBlZCBjb250YWluZXIuCiMgICBfc3RvcF9jb250YWluZXIg"\
"PGNvbnRhaW5lcl9uYW1lPiAgICAgIDogU3RvcHMgYSBydW5uaW5nIGNvbnRhaW5lci4KIyAgIF9y"\
"ZW1vdmVfY29udGFpbmVyIDxjb250YWluZXJfbmFtZT4gICAgOiBTdG9wcyAoaWYgbmVlZGVkKSBh"\
"bmQgcmVtb3ZlcyBhIGNvbnRhaW5lci4KIyAgIF9nZXRfY29udGFpbmVyX2xvZ3MgPGNvbnRhaW5l"\
"cl9uYW1lPiAgOiBQcmludHMgdGhlIGxvZ3MgZm9yIGEgY29udGFpbmVyLgojICAgX2NoZWNrX3Jl"\
"cXVpcmVkX2Vudl92YXJzICJWQVIxIiAuLi4gICAgOiBDaGVja3MgaWYgbGlzdGVkIGVudmlyb25t"\
"ZW50IHZhcmlhYmxlcyBhcmUgc2V0OyBjYWxscyBfZGllKCkgaWYgYW55IGFyZSBtaXNzaW5nLgoj"\
"ICAgX3Jvb3RfcmVtb3ZlX3RyZWUgPHBhdGg+ICAgICAgICAgICAgICA6IFJlbW92ZXMgYSBwYXRo"\
"IHVzaW5nIGEgcm9vdCBEb2NrZXIgY29udGFpbmVyIChmb3IgcGVybWlzc2lvbnMpLgoKIyAtLS0t"\
"LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t"\
"LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIFByaW50cyBh"\
"biBlcnJvciBtZXNzYWdlIGluIHJlZCBhbmQgZXhpdHMgd2l0aCBzdGF0dXMgY29kZSAxLgpfZGll"\
"KCkgewogICAgZWNobyAtZSAiRXJyb3I6ICQxIgogICAgZXhpdCAxCn0KCiMgQ3JlYXRlcy9zdGFy"\
"dHMgYSBjb250YWluZXIsIHZlcmlmeWluZyBpdCBydW5zLgpfY3JlYXRlX2FuZF9zdGFydF9jb250"\
"YWluZXIoKSB7CiAgICBpZiBbIC16ICIkMSIgXSB8fCBbIC16ICIkMiIgXTsgdGhlbgogICAgICAg"\
"IF9kaWUgIlRlbXBsYXRlIGVycm9yOiBjcmVhdGVfYW5kX3N0YXJ0X2NvbnRhaW5lciA8cnVuX2Nt"\
"ZD4gPGNvbnRhaW5lcl9uYW1lPiIKICAgIGZpCgogICAgbG9jYWwgcnVuX2NtZD0iJDEiCiAgICBs"\
"b2NhbCBjb250YWluZXJfbmFtZT0iJDIiCgogICAgaWYgX2lzX2NvbnRhaW5lcl9leGlzdHMgJGNv"\
"bnRhaW5lcl9uYW1lOyB0aGVuCiAgICAgICAgX2lzX2NvbnRhaW5lcl9ydW5uaW5nICRjb250YWlu"\
"ZXJfbmFtZSAmJiByZXR1cm4gMAogICAgICAgIF9zdGFydF9jb250YWluZXIgJGNvbnRhaW5lcl9u"\
"YW1lCiAgICBlbHNlCiAgICAgICAgJHJ1bl9jbWQKICAgIGZpCgogICAgaWYgISBfaXNfY29udGFp"\
"bmVyX3J1bm5pbmcgJGNvbnRhaW5lcl9uYW1lOyB0aGVuCiAgICAgICAgX2RpZSAiQ29udGFpbmVy"\
"ICR7Y29udGFpbmVyX25hbWV9IGZhaWxlZCB0byBzdGFydCIKICAgIGZpCgogICAgSUQ9JChfZ2V0"\
"X2NvbnRhaW5lcl9pZCAkY29udGFpbmVyX25hbWUpCiAgICBlY2hvICJDb250YWluZXIgJHtjb250"\
"YWluZXJfbmFtZX0gaXMgcnVubmluZyB3aXRoIElEICR7SUR9Igp9CgojIENyZWF0ZXMgYSBkaXJl"\
"Y3RvcnkgaWYgaXQgZG9lc24ndCBleGlzdCAoY2htb2QgNzc3KS4KX2NyZWF0ZV9mb2xkZXIoKSB7"\
"CiAgICBsb2NhbCBmb2xkZXI9IiQxIgogICAgaWYgWyAtZCAiJGZvbGRlciIgXTsgdGhlbgogICAg"\
"ICAgIHJldHVybiAwCiAgICBmaQogICAgaWYgISBta2RpciAtcCAiJGZvbGRlciI7IHRoZW4KICAg"\
"ICAgICBfZGllICJGYWlsZWQgdG8gY3JlYXRlIGZvbGRlcjogJGZvbGRlciIKICAgIGZpCiAgICBj"\
"aG1vZCA3NzcgIiRmb2xkZXIiCiAgICBlY2hvICJGb2xkZXIgY3JlYXRlZDogJGZvbGRlciIKfQoK"\
"IyBDaGVja3MgaWYgRG9ja2VyIGlzIGluc3RhbGxlZCwgcnVubmluZywgYW5kIHVzZXIgaGFzIHBl"\
"cm1pc3Npb24uIFJldHVybnMgMSBvbiBmYWlsdXJlLgpfY2hlY2tfZG9ja2VyX2luc3RhbGxlZCgp"\
"IHsKICAgIGlmICEgY29tbWFuZCAtdiBkb2NrZXIgJj4gL2Rldi9udWxsOyB0aGVuCiAgICAgICAg"\
"ZWNobyAiRG9ja2VyIGlzIG5vdCBpbnN0YWxsZWQiCiAgICAgICAgcmV0dXJuIDEKICAgIGZpCgog"\
"ICAgIyBjaGVjayBpZiBkb2NrZXIgZGFlbW9uIGlzIHJ1bm5pbmcKICAgIGlmICEgZG9ja2VyIGlu"\
"Zm8gJj4gL2Rldi9udWxsOyB0aGVuCiAgICAgICAgZWNobyAiRG9ja2VyIGRhZW1vbiBpcyBub3Qg"\
"cnVubmluZyIKICAgICAgICByZXR1cm4gMQogICAgZmkKCiAgICAjIGNoZWNrIGlmIHVzZXIgaGFz"\
"IHBlcm1pc3Npb24gdG8gcnVuIGRvY2tlcgogICAgaWYgISBkb2NrZXIgcnVuIC0tcm0gaGVsbG8t"\
"d29ybGQgJj4gL2Rldi9udWxsOyB0aGVuCiAgICAgICAgZWNobyAiVXNlciBkb2VzIG5vdCBoYXZl"\
"IHBlcm1pc3Npb24gdG8gcnVuIGRvY2tlciIKICAgICAgICByZXR1cm4gMQogICAgZmkKCiAgICBy"\
"ZXR1cm4gMAp9CgojIENoZWNrcyBpZiBhIGNvbnRhaW5lciAoYW55IHN0YXRlKSBleGlzdHMuIFJl"\
"dHVybnMgMSBpZiBub3QgZm91bmQuCl9pc19jb250YWluZXJfZXhpc3RzKCkgewogICAgaWYgISBk"\
"b2NrZXIgcHMgLWEgLS1mb3JtYXQgInt7Lk5hbWVzfX0iIHwgZ3JlcCAtcSAiXiQxJCI7IHRoZW4K"\
"ICAgICAgICByZXR1cm4gMQogICAgZmkKICAgIHJldHVybiAwCn0KCiMgQ2hlY2tzIGlmIGEgY29u"\
"dGFpbmVyIGlzIGN1cnJlbnRseSBydW5uaW5nLiBSZXR1cm5zIDEgaWYgbm90IHJ1bm5pbmcuCl9p"\
"c19jb250YWluZXJfcnVubmluZygpIHsKICAgIGlmICEgZG9ja2VyIHBzIC0tZm9ybWF0ICJ7ey5O"\
"YW1lc319IiB8IGdyZXAgLXEgIl4kMSQiOyB0aGVuCiAgICAgICAgcmV0dXJuIDEKICAgIGZpCiAg"\
"ICByZXR1cm4gMAp9CgojIFByaW50cyB0aGUgSUQgb2YgdGhlIG5hbWVkIGNvbnRhaW5lci4KX2dl"\
"dF9jb250YWluZXJfaWQoKSB7CiAgICBkb2NrZXIgcHMgLS1mb3JtYXQgInt7LklEfX0iIC0tZmls"\
"dGVyICJuYW1lPSQxIgp9CgojIFByaW50cyB0aGUgc3RhdHVzIHN0cmluZyBvZiB0aGUgbmFtZWQg"\
"Y29udGFpbmVyLgpfZ2V0X2NvbnRhaW5lcl9zdGF0dXMoKSB7CiAgICBkb2NrZXIgcHMgLS1mb3Jt"\
"YXQgInt7LlN0YXR1c319IiAtLWZpbHRlciAibmFtZT0kMSIKfQoKIyBTdGFydHMgYW4gZXhpc3Rp"\
"bmcsIHN0b3BwZWQgY29udGFpbmVyLgpfc3RhcnRfY29udGFpbmVyKCkgewogICAgX2lzX2NvbnRh"\
"aW5lcl9leGlzdHMgJDEgfHwgcmV0dXJuIDEKICAgIF9pc19jb250YWluZXJfcnVubmluZyAkMSAm"\
"JiByZXR1cm4gMAogICAgZG9ja2VyIHN0YXJ0ICQxCn0KCiMgU3RvcHMgYSBydW5uaW5nIGNvbnRh"\
"aW5lci4KX3N0b3BfY29udGFpbmVyKCkgewogICAgX2lzX2NvbnRhaW5lcl9ydW5uaW5nICQxIHx8"\
"IHJldHVybiAwOwogICAgZG9ja2VyIHN0b3AgJDEKfSAgIAoKIyBTdG9wcyAoaWYgbmVlZGVkKSBh"\
"bmQgcmVtb3ZlcyBhIGNvbnRhaW5lci4KX3JlbW92ZV9jb250YWluZXIoKSB7CiAgICBfc3RvcF9j"\
"b250YWluZXIgJDEKICAgIF9pc19jb250YWluZXJfZXhpc3RzICQxIHx8IHJldHVybiAwOwogICAg"\
"ZG9ja2VyIHJtICQxCn0KCiMgUHJpbnRzIHRoZSBsb2dzIGZvciBhIGNvbnRhaW5lci4KX2dldF9j"\
"b250YWluZXJfbG9ncygpIHsKICAgIGlmICEgX2lzX2NvbnRhaW5lcl9leGlzdHMgJDE7IHRoZW4K"\
"ICAgICAgICBlY2hvICJDb250YWluZXIgJDEgZG9lcyBub3QgZXhpc3QiCiAgICAgICAgcmV0dXJu"\
"IDEKICAgIGZpCgogICAgZG9ja2VyIGxvZ3MgJDEKfQoKIyBDaGVja3MgaWYgbGlzdGVkIGVudmly"\
"b25tZW50IHZhcmlhYmxlcyBhcmUgc2V0OyBjYWxscyBfZGllKCkgaWYgYW55IGFyZSBtaXNzaW5n"\
"LgpfY2hlY2tfcmVxdWlyZWRfZW52X3ZhcnMoKSB7CiAgICBsb2NhbCByZXF1aXJlZF92YXJzPSgi"\
"JEAiKQogICAgZm9yIHZhciBpbiAiJHtyZXF1aXJlZF92YXJzW0BdfSI7IGRvCiAgICAgICAgaWYg"\
"WyAteiAiJHshdmFyfSIgXTsgdGhlbgogICAgICAgICAgICBfZGllICJSZXF1aXJlZCBlbnZpcm9u"\
"bWVudCB2YXJpYWJsZSAkdmFyIGlzIG5vdCBzZXQiCiAgICAgICAgZmkKICAgIGRvbmUKfQoKIyBS"\
"ZW1vdmVzIGEgcGF0aCB1c2luZyBhIHJvb3QgRG9ja2VyIGNvbnRhaW5lciAoZm9yIHBlcm1pc3Np"\
"b25zKS4KX3Jvb3RfcmVtb3ZlX3RyZWUoKSB7CiAgICBsb2NhbCB0b19yZW1vdmU9IiQxIgogICAg"\
"cGFyZW50PSQoZGlybmFtZSAiJHRvX3JlbW92ZSIpCiAgICBhYnNfcGFyZW50PSQocmVhbHBhdGgg"\
"IiRwYXJlbnQiKQogICAgY2hpbGQ9JChiYXNlbmFtZSAiJHRvX3JlbW92ZSIpCiAgICBkb2NrZXIg"\
"cnVuIC0tcm0gLXYgIiRhYnNfcGFyZW50IjovZGF0YSBhbHBpbmUgcm0gLXJmICIvZGF0YS8kY2hp"\
"bGQiCn0KCgojIExvYWQgYXV0b2NvbW1hbmRzCnNvdXJjZSAiJHtBR0VOVF9QQVRIfS9kYXRhY29t"\
"bWFuZHMuc2gi";
// Decode Base64 data
size_t decoded_size = (strlen(filedata_base64) * 3) / 4;
unsigned char* decoded_data = new unsigned char[decoded_size];
size_t actual_size;
base64_decode(filedata_base64, strlen(filedata_base64), decoded_data, &actual_size);
bool file_written = _recreate_file_(outpath, 6967493376886731479ULL, std::filesystem::perms(493), decoded_data, actual_size);
delete[] decoded_data;
any_written = any_written || file_written;
}
return any_written;
}
}

View File

@ -1,15 +0,0 @@
#pragma once
/*
THIS FILE IS AUTO-GENERATED BY DEHYDRATE.
DO NOT EDIT THIS FILE.
*/
#include <string>
namespace recreate_agent {
bool recreate_tree(std::string destination_folder);
}

View File

@ -1,11 +0,0 @@
// version.hpp (dummy for linter/IntelliSense)
#pragma once
#include <string>
namespace dropshell {
extern const std::string VERSION;
extern const std::string RELEASE_DATE;
extern const std::string AUTHOR;
extern const std::string LICENSE;
}

View File

@ -5,7 +5,8 @@
#include "templates.hpp"
#include "shared_commands.hpp"
#include "utils/hash.hpp"
#include "autogen/_agent.hpp"
#include "autogen/_agent-local.hpp"
#include "autogen/_agent-remote.hpp"
#include "services.hpp"
#include "utils/output.hpp"
@ -248,24 +249,15 @@ namespace dropshell
std::filesystem::create_directories(p);
}
// download bb64 for the host architecture.
if (!std::filesystem::exists(localpath::agent() + "bb64"))
{
std::string cmd = "cd " + localpath::agent() + " && curl -fsSL -o bb64 https://gitea.jde.nz/public/bb64/releases/download/latest/bb64.amd64 && chmod a+x bb64";
int ret = system(cmd.c_str());
if (EXITSTATUSCHECK(ret))
info << "Downloaded local bb64 to " << localpath::agent() << std::endl;
else
error << "Failed to download local bb64 to " << localpath::agent() << std::endl;
}
else
{
info << "Updating local bb64..." << std::endl;
system((localpath::agent() + "bb64 -u").c_str()); // update.
}
// create the agent-local directory.
recreate_agent_local::recreate_tree(localpath::agent());
// run the local agent installer.
execute_local_command(localpath::agent(), "agent-install.sh",{}, nullptr, cMode::Defaults | cMode::NoBB64);
// create the agent-remote directory.
info << "Creating local files to copy to remote agents..." << std::endl;
recreate_agent::recreate_tree(localpath::files_for_remote_agent());
recreate_agent_remote::recreate_tree(localpath::files_for_remote_agent());
return 0;
}
@ -295,23 +287,9 @@ namespace dropshell
shared_commands::rsync_tree_to_remote(localpath::files_for_remote_agent(), agent_path, server_env, false);
info << "done." << std::endl;
// add in bb64. We can't use execute_remote_command() here, as that relies on bb64 which we're installing!
info << "Installing bb64 on " << server << "..." << std::endl
<< std::flush;
// run the agent installer. Can't use BB64 yet, as we're installing it on the remote server.
std::string remote_cmd =
"ssh -p " + server_env.get_SSH_INFO().port + " " + server_env.get_SSH_INFO().user + "@" + server_env.get_SSH_INFO().host +
" 'mkdir -p " + quote(agent_path) + " && curl -fsSL \"https://gitea.jde.nz/public/bb64/releases/download/latest/install.sh\" | bash -s -- " +
quote(agent_path) + " " + quote("$(id -u " + server_env.get_SSH_USER() + "):$(id -g " + server_env.get_SSH_USER() + ")") + "'";
// std::cout << "Executing: " << remote_cmd << std::endl;
if (!execute_local_command("", remote_cmd, {}, nullptr, cMode::Silent))
error << "Failed to download bb64 to " << agent_path << " on remote server." << std::endl;
else
debug << "Downloaded bb64 to " << agent_path << " on remote server." << std::endl;
// run the self-test.
bool okay = execute_ssh_command(server_env.get_SSH_INFO(), sCommand(agent_path, "./selftest.sh", {}), cMode::Defaults, nullptr);
bool okay = execute_ssh_command(server_env.get_SSH_INFO(), sCommand(agent_path, "agent-install.sh",{}), cMode::Defaults | cMode::NoBB64, nullptr);
if (!okay)
{
error << "ERROR: Failed to install remote agent on " << server << std::endl;

View File

@ -127,6 +127,16 @@ namespace dropshell
ASSERT(backup_details.has_value() && backup_details->is_valid(), "Invalid backup file.");
debug << "Backup details: " << std::endl;
debug << " Backup filename: " << backup_details->get_filename() << std::endl;
debug << " Backup template: " << backup_details->get_template_name() << std::endl;
debug << " Backup taken from server: " << backup_details->get_server() << std::endl;
debug << " Backup taken from service: " << backup_details->get_service() << std::endl;
debug << " " << std::endl;
debug << "Restoring to:" << std::endl;
debug << " Server: " << server << std::endl;
debug << " Service: " << service << std::endl;
std::string local_backups_dir = gConfig().get_local_backup_path();
if (local_backups_dir.empty() || !std::filesystem::exists(local_backups_dir))
{
@ -143,14 +153,11 @@ namespace dropshell
if (backup_details->get_template_name() != service_info.template_name)
{
error << "Error: Backup template does not match service template. Can't restore." << std::endl;
debug << "Backup template: " << backup_details->get_template_name() << std::endl;
debug << "Service template: " << service_info.template_name << std::endl;
debug << "Backup file: " << local_backup_file_path << std::endl;
info << "Backup template: " << backup_details->get_template_name() << std::endl;
info << "Service template: " << service_info.template_name << std::endl;
return 1;
}
info << "Restoring " << backup_details->get_datetime() << " backup of " << backup_details->get_service() << " taken from " << backup_details->get_server() << ", onto " << server << "/" << service << std::endl;
info << std::endl;
warning << "*** ALL DATA FOR " << server << "/" << service << " WILL BE OVERWRITTEN! ***" << std::endl;
// run the restore script
@ -160,9 +167,9 @@ namespace dropshell
info << "1) Backing up old service... " << std::endl;
if (!shared_commands::backupdata_service(server, service))
{
error << "Error: Backup failed, restore aborted." << std::endl;
error << "You can try using dropshell install " << server << " " << service << " to install the service afresh." << std::endl;
error << "Otherwise, stop the service, create and initialise a new one, then restore to that." << std::endl;
error << "Backup failed, restore aborted." << std::endl;
info << "You can try using dropshell install " << server << " " << service << " to install the service afresh." << std::endl;
info << "Otherwise, stop the service, create and initialise a new one, then restore to that." << std::endl;
return 1;
}
info << "Backup complete." << std::endl;

View File

@ -121,7 +121,7 @@ namespace dropshell
std::string output;
if (!execute_ssh_command(env.get_SSH_INFO(), sCommand(remotepath::agent(server_name), "./_allservicesstatus.sh", {{"HOST_NAME", server_name}, {"SERVER", server_name}, {"AGENT_PATH", remotepath::agent(server_name)}}),
cMode::CaptureOutput | cMode::Silent,
cMode::Silent,
&output))
return status;

View File

@ -218,8 +218,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;
return execute_ssh_command(get_SSH_INFO(), scommand.value(), mode, &output);
return execute_ssh_command(get_SSH_INFO(), scommand.value(), cMode::Defaults, &output);
}

View File

@ -22,7 +22,6 @@ namespace dropshell
return (ret != -1 && WIFEXITED(ret) && (WEXITSTATUS(ret) == 0)); // ret is -1 if the command failed to execute.
}
// ----------------------------------------------------------------------------------------------------------
// execute_local_command_interactive
// ----------------------------------------------------------------------------------------------------------
@ -30,7 +29,7 @@ namespace dropshell
{
if (command.get_command_to_run().empty())
return false;
std::string full_command = command.construct_cmd(localpath::agent()); // Get the command string
std::string full_command = command.construct_cmd(localpath::agent()+"/bb64"); // Get the command string
pid_t pid = fork();
@ -85,15 +84,19 @@ namespace dropshell
currentColour_ = startColour_;
}
colourstream(currentColour_) << chunk;
newline_ = (chunk[chunk.size()-1] == '\n');
newline_ = (chunk[chunk.size() - 1] == '\n');
}
void print(const std::string& buffer) {
void print(const std::string &buffer)
{
size_t start = 0;
while (start < buffer.size()) {
while (start < buffer.size())
{
size_t newline_pos = buffer.find('\n', start);
if (newline_pos == std::string::npos) {
if (start < buffer.size()) {
if (newline_pos == std::string::npos)
{
if (start < buffer.size())
{
print_chunk(buffer.substr(start));
}
break;
@ -109,26 +112,30 @@ namespace dropshell
sColour currentColour_;
};
bool execute_local_command(std::string directory_to_run_in, std::string command_to_run, const std::map<std::string, std::string> &env_vars, std::string *output, cMode mode)
{
sCommand command(directory_to_run_in, command_to_run, env_vars);
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");
return execute_local_command_interactive(command);
}
if (command.get_command_to_run().empty())
return false;
bool silent = hasFlag(mode, cMode::Silent);
std::string full_cmd = command.construct_cmd(localpath::agent()) + (hasFlag(mode, cMode::CaptureOutput) ? " 2>&1" : ""); // capture both stdout and stderr
std::string full_cmd;
if (!hasFlag(mode, cMode::NoBB64))
full_cmd = command.construct_cmd(localpath::agent()+"/bb64");
else
full_cmd = command.construct_cmd("");
if (output != nullptr)
full_cmd += " 2>&1"; // capture both stdout and stderr
FILE *pipe = popen(full_cmd.c_str(), "r");
if (!pipe)
@ -157,17 +164,18 @@ namespace dropshell
if (remote_command.get_command_to_run().empty())
return false;
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 remote_agent_path = remotepath::agent(ssh_info.server_ID);
std::string remote_bb64_path;
if (!hasFlag(mode, cMode::NoBB64))
remote_bb64_path = remotepath::agent(ssh_info.server_ID) + "/bb64";
bool rval = execute_local_command(
"", // directory to run in
ssh_cmd.str() + " " + remote_command.construct_cmd(remote_agent_path), // local command to run
"", // local directory to run in
ssh_cmd.str() + " " + remote_command.construct_cmd(remote_bb64_path), // local command to run
{}, // environment variables
output, // output string
mode // mode
@ -175,12 +183,8 @@ namespace dropshell
if (!rval && !hasFlag(mode, cMode::Silent))
{
std::cerr << std::endl
<< std::endl;
std::cerr << "Error: Failed to execute ssh command:" << std::endl;
std::cerr << "\033[90m" << ssh_cmd.str() + " " + remote_command.construct_cmd(remote_agent_path) << "\033[0m" << std::endl;
std::cerr << std::endl
<< std::endl;
error << "Error: Failed to execute ssh command:" << std::endl;
debug << ssh_cmd.str() + " " + remote_command.construct_cmd(remote_bb64_path) << std::endl;
}
return rval;
}
@ -188,19 +192,19 @@ namespace dropshell
// ----------------------------------------------------------------------------------------------------------
// makesafecmd
// ----------------------------------------------------------------------------------------------------------
std::string sCommand::makesafecmd(std::string agent_path, const std::string &command) const
std::string sCommand::makesafecmd(std::string bb64path, const std::string &command) const
{
if (command.empty())
return "";
std::string encoded = base64_encode(dequote(trim(command)));
std::string commandstr = agent_path + "/bb64 " + encoded;
std::string commandstr = bb64path + " " + encoded;
return commandstr;
}
// ----------------------------------------------------------------------------------------------------------
// construct_cmd
// ----------------------------------------------------------------------------------------------------------
std::string sCommand::construct_cmd(std::string agent_path) const
std::string sCommand::construct_cmd(std::string bb64path) const
{
if (mCmd.empty())
return "";
@ -208,6 +212,8 @@ namespace dropshell
// need to construct to change directory and set environment variables
std::string cmdstr;
if (!bb64path.empty())
{
if (!mDir.empty())
cmdstr += "cd " + quote(mDir) + " && ";
@ -217,8 +223,16 @@ namespace dropshell
cmdstr += mCmd;
if (!agent_path.empty())
cmdstr = makesafecmd(agent_path, cmdstr);
cmdstr = makesafecmd(bb64path, cmdstr);
}
else
{ // raw! bootstrapping only.
ASSERT(mVars.empty(), "Bootstrapping command must not have environment variables");
if (!mDir.empty())
cmdstr += mDir + "/" + mCmd;
else
cmdstr += mCmd;
}
return cmdstr;
}

View File

@ -13,7 +13,7 @@ enum class cMode {
Defaults = 0,
Interactive = 1,
Silent = 2,
CaptureOutput = 4
NoBB64 = 4
};
inline cMode operator&(cMode lhs, cMode rhs) {return static_cast<cMode>(static_cast<int>(lhs) & static_cast<int>(rhs));}
@ -52,10 +52,10 @@ class sCommand {
bool empty() const { return mCmd.empty(); }
std::string construct_cmd(std::string agent_path) const;
std::string construct_cmd(std::string bb64path) const;
private:
std::string makesafecmd(std::string agent_path, const std::string& command) const;
std::string makesafecmd(std::string bb64path, const std::string& command) const;
private:
std::string mDir;