From 8d9d4475333811106294d1ce4ced1eb759285aea Mon Sep 17 00:00:00 2001 From: Sam Hardeman Date: Sat, 13 Sep 2025 16:10:56 +0200 Subject: [PATCH] Initial test version of `binbox`, a bash packer --- binbox | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100755 binbox diff --git a/binbox b/binbox new file mode 100755 index 0000000..151fdc5 --- /dev/null +++ b/binbox @@ -0,0 +1,175 @@ +#!/bin/bash +# binbox: Creates a multi-binary script that self-contains the input scripts. +# Symlinking to the resulting binary with the name of one of the original scripts will trigger +# said script. The idea is similar to `busybox`. + +DAISY_INTERNAL=1 +. daisy.source + +ARGS=$@ + +function help() +{ + echo "$DAISY_BIN is a utility that allows you to generate busybox-style combined binaries." + echo "To access the original functionality of an input binary, you can either use a symlink or" + echo "call the function like so: 'combi-bin input-bin ." + echo "" + echo "> Usage:" + echo "Creating boxed binary: $DAISY_BIN -o <-s source files> <-p include files verbatim> -i INPUT_BINS ..." + echo " Unpacking a boxed binary: $DAISY_BIN -e " + echo "View this screen: $DAISY_BIN " + exit 0 +} + +if [[ $@ == '' ]]; then + help +fi + +# Define some building blocks +CASE_P1="case $BINARY in" +CASE_PM1=" $OPTION)" +CASE_PM2=" exec $OTPION_fn" +CASE_PM3=" ;;" +CASE_CM1=" *)" +CASE_CM2=" exec help_fn" +CASE_CM3=" ;;" +CASE_P2="esac" + +FUNC_P1="function $OPTION_fn() {" +FUNC_P2=" exit($?)" +FUNC_P3="}" + +BASIC_P1="BINARY=$0" + +# Start parsing args +inputs=() +output="" + +inputs=() +output="" +includes=() +sources=() + +args=("$@") +i=0 +b=0 +s=0 +p=0 +while [ $i -lt $# ]; do + case "${args[$i]}" in + -i) + ((i++)) + while [ $i -lt $# ] && [[ ! "${args[$i]}" =~ ^- ]]; do + inputs+=("${args[$i]}") + ((i++)) + ((b++)) + done + continue + ;; + -s) + ((i++)) + while [ $i -lt $# ] && [[ ! "${args[$i]}" =~ ^- ]]; do + sources+=("${args[$i]}") + ((i++)) + ((s++)) + done + continue + ;; + -p) + ((i++)) + while [ $i -lt $# ] && [[ ! "${args[$i]}" =~ ^- ]]; do + includes+=("${args[$i]}") + ((i++)) + ((p++)) + done + continue + ;; + -o) + ((i++)) + output="${args[$i]}" + ;; + esac + ((i++)) +done + +echo "Input binaries: ${inputs[*]}" +echo "Include files: ${includes[*]}" +echo "Source files: ${sources[*]}" +echo "Output binary: $output" + +if [ "$b" -eq 0 ]; then + echo "Missing input binaries!" + exit 1 +fi + +if [[ "$output" == "" ]]; then + echo "Missing output file!" + exit 1 +fi + +function add() +{ + echo "$@" >> "$output" +} + +rm -rf "$output" + +# Now to construct the binary +# >>> Section 1, includes +add "#!/bin/bash" +add "# Multi-call binary generated by LACKADAISICAL binbox" +add "# $output information:" +add "# Contained modules: ${inputs[*]}" +add "# Files included verbatim: ${includes[*]}" +add "# Files sourced: ${sources[*]}" +add "# Symlink to this binary with the module name to invoke it, or" +add "# use '$output ' to do the same." + +for f in "${sources[@]}"; do + add ". $f" +done + +for f in "${includes[@]}"; do + add "" + add "# Included file $f" + add "$(cat "$f")" +done + +add "" +add "if [[ \$# -eq 0 ]]; then" +add " echo 'Available modules:'" + for f in "${inputs[@]}"; do + add "echo '$f'" + done +add " exit 0" +add "fi" + + +# >>> Section 2: Modules +for f in "${inputs[@]}"; do + add "# Module '$f':" + add "function $f()" + add "{" + add "$(cat "$f" | grep -v "#!")" + add "}" +done + +# >>> Section 3: Module selection +add "SYMED=1" +add "BINSELF=\$(basename \$0 | rev | cut -d "/" -f 1 | rev)" +add "BOXFILE=$(basename \"$output\")" +add "if [[ \$BINSELF == \$BOXFILE ]]; then" +add " SYMED=0" +add "fi" + +add "if [[ \$SYMED -eq 0 ]]; then" +add " eval \$@" +add " exit \$?" +add "fi" + +add "if [[ \$SYMED -eq 1 ]]; then" +add " eval \$(basename \$0) \$@" +add "fi" + + +chmod +x "$output"