diff --git a/bb64.cpp b/bb64.cpp new file mode 100644 index 0000000..3fa00bc --- /dev/null +++ b/bb64.cpp @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include +#include + +#include "version.h" + +// Custom base64 encoding/decoding tables +static const std::string 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(base64_chars[(val >> valb) & 0x3F]); + valb -= 6; + } + } + if (valb > -6) out.push_back(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[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; +} + +// Recursively decode and print if nested bb64 command is found +void recursive_print(const std::string &decoded) { + std::cout << decoded << std::endl; + size_t pos = decoded.find("bb64 "); + if (pos != std::string::npos) { + std::istringstream iss(decoded.substr(pos)); + std::string cmd, arg; + iss >> cmd >> arg; + if (cmd == "bb64" && !arg.empty()) { + std::string nested = base64_decode(arg); + recursive_print(nested); + } + } +} + +int main(int argc, char *argv[]) { + if (argc < 2) { + std::cerr << "bb64 version " << VERSION << ", by J842." << std::endl; + // heredoc for instructions + std::cerr << R"( + +Usage: + bb64 BASE64COMMAND Decodes and runs the command + bb64 -i BASE64COMMAND Displays the decoded command + bb64 -e COMMAND Encodes the command and prints the result + +)" << std::endl; + return -1; + } + std::string mode; + int argi = 1; + if (std::string(argv[1]) == "-i" || std::string(argv[1]) == "-e") { + mode = argv[1]; + argi = 2; + } + if (mode == "-e") { + // Encode the rest of the arguments as a single command string + std::ostringstream oss; + for (int i = argi; i < argc; ++i) { + if (i > argi) oss << " "; + oss << argv[i]; + } + std::string encoded = base64_encode(oss.str()); + std::cout << encoded << std::endl; + return 0; + } else if (mode == "-i") { + if (argi >= argc) { + std::cerr << "No BASE64COMMAND provided for -i" << std::endl; + return -1; + } + std::string decoded = base64_decode(argv[argi]); + recursive_print(decoded); + return 0; + } else { + // Default: decode and run + std::string decoded = base64_decode(argv[argi]); + if (decoded.empty()) { + std::cerr << "Failed to decode base64 command." << std::endl; + return -1; + } + // Replace current process with bash -c "decoded" + execlp("bash", "bash", "-c", decoded.c_str(), (char *)nullptr); + // If execlp returns, there was an error + std::cerr << "Failed to execute command." << std::endl; + return -1; + } +} \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..130b607 --- /dev/null +++ b/build.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -e + +SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +OUTPUT_DIR="$SCRIPT_DIR/output" +mkdir -p "$OUTPUT_DIR" + +# Build for x86_64 with musl static linking +if [[ $(uname -m) == "x86_64" ]]; then + echo "Building for x86_64 (musl static)..." + if command -v x86_64-linux-musl-g++ &>/dev/null; then + x86_64-linux-musl-g++ -O2 -static -o "$OUTPUT_DIR/bb64.amd64" bb64.cpp + else + g++ -O2 -static -o "$OUTPUT_DIR/bb64.amd64" bb64.cpp -static-libgcc -static-libstdc++ + echo "Warning: musl-g++ not found, built with g++ static flags." + fi + echo "Built bb64.amd64 (x86_64, static)" +fi + +# Build for arm64 (musl static) if cross-compiler available +if command -v aarch64-linux-musl-g++ &>/dev/null; then + echo "Building for arm64 (musl static)..." + aarch64-linux-musl-g++ -O2 -static -o "$OUTPUT_DIR/bb64.arm64" bb64.cpp + echo "Built bb64.arm64 (arm64, static)" +fi \ No newline at end of file diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..0e8ff96 --- /dev/null +++ b/install.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# Installs bb64 on the local machine. + +# 1. determines the architecture of the local machine + +# 2. downloads the appropriate bb64 binary + +# 3. makes the bb64 binary executable + +# 4. moves the bb64 binary to /usr/local/bin + +# 5. prints a message to the user + diff --git a/install_prerequisites.sh b/install_prerequisites.sh new file mode 100755 index 0000000..9490aa6 --- /dev/null +++ b/install_prerequisites.sh @@ -0,0 +1,67 @@ +#!/bin/bash +set -e + +# Check for root +if [[ $EUID -ne 0 ]]; then + echo "This script must be run as root." >&2 + exit 1 +fi + +# Install required packages +apt update +apt install -y musl-tools wget tar + +# Set install directory +if [ -n "$SUDO_USER" ] && [ "$SUDO_USER" != "root" ]; then + USER_HOME=$(eval echo ~$SUDO_USER) +else + USER_HOME="$HOME" +fi +INSTALL_DIR="$USER_HOME/.musl-cross" +mkdir -p "$INSTALL_DIR" + +MUSL_CC_URL="https://musl.cc" +TMPDIR=$(mktemp -d) +trap 'rm -rf "$TMPDIR"' EXIT + +# x86_64 +if [ ! -d "$INSTALL_DIR/x86_64-linux-musl-cross" ]; then + echo "Downloading x86_64 musl cross toolchain..." + wget -nc -O "$TMPDIR/x86_64-linux-musl-cross.tgz" $MUSL_CC_URL/x86_64-linux-musl-cross.tgz + tar -C "$INSTALL_DIR" -xvf "$TMPDIR/x86_64-linux-musl-cross.tgz" +fi + +# aarch64 +if [ ! -d "$INSTALL_DIR/aarch64-linux-musl-cross" ]; then + echo "Downloading aarch64 musl cross toolchain..." + wget -nc -O "$TMPDIR/aarch64-linux-musl-cross.tgz" $MUSL_CC_URL/aarch64-linux-musl-cross.tgz + tar -C "$INSTALL_DIR" -xvf "$TMPDIR/aarch64-linux-musl-cross.tgz" +fi + +# Print instructions for adding to PATH +cat <> "$BASHRC" + echo "# Add musl cross compilers to PATH for bb64" >> "$BASHRC" + echo "$EXPORT_LINE" >> "$BASHRC" + echo "Added musl cross compilers to $BASHRC" + else + echo "musl cross compiler PATH already present in $BASHRC" + fi +fi diff --git a/output/bb64.amd64 b/output/bb64.amd64 new file mode 100755 index 0000000..0ed8d1d Binary files /dev/null and b/output/bb64.amd64 differ diff --git a/output/bb64.arm64 b/output/bb64.arm64 new file mode 100755 index 0000000..2f7dcd3 Binary files /dev/null and b/output/bb64.arm64 differ diff --git a/publish.sh b/publish.sh new file mode 100644 index 0000000..1d3b722 --- /dev/null +++ b/publish.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# Publishes bb64 (both arm64 and amd64) to the Gitea Releases page for the repository. + +# Increments the version number in the VERSION file by one first. + +# Builds the bb64 binary for arm64 and amd64. + +# Uploads the binaries to the Gitea Releases page. + +# Prints a message to the user. + + diff --git a/version.h b/version.h new file mode 100644 index 0000000..c7e4b7c --- /dev/null +++ b/version.h @@ -0,0 +1,2 @@ +static const char *VERSION = "1"; +