#!/bin/false command -v recursive_dependencies >/dev/null || source dependencies.bash # Input: $BASH_RPC_REMOTE_DEST - hostname passed to ssh (uses ssh host aliases) # Input: $BASH_RPC_SSH_OPTIONS - option arguments passed to ssh (they precede '--') # Input: "$0" - copied to remote bash's $0 # Input: $1 - shell script source code to run in the remote bash # Input: $2, $3, ... - command line arguments passed to the remote bash as $1, $2, ... # Input: stdin, stdout, stderr: passed to the remote bash over ssh # Input: "$SHELL" - remote shell to launch (better be bash) __bashrpc__remote_run_script() { local script="$1" shift BASH_RPC_SHELL_OPTIONS=(--norc --noprofile) # printf 'DEBUG:<%s>\n' "${BASH_RPC_SSH_OPTIONS[@]}" >&2 exec ssh \ "${BASH_RPC_SSH_OPTIONS[@]}" -- \ "${BASH_RPC_REMOTE_DEST:-localhost}" \ "$SHELL" "${BASH_RPC_SHELL_OPTIONS[@]}" \ -c "${script@Q}" \ "$0" "${@@Q}" } with_ssh_options() { __bashrpc__with_ssh_options "$@"; } __bashrpc__with_ssh_options() { local -a BASH_RPC_SSH_OPTIONS while [ "$1" != '--' ] do if [ $# -gt 0 ] then BASH_RPC_SSH_OPTIONS+=("$1") shift continue fi >&2 printf '%s: Error: %s\n' "$0" \ 'with_ssh_options(): expected argument "--" not found' exit 1 done shift "$@" } with_ssh_option() { __bashrpc__with_ssh_option "$@"; } __bashrpc__with_ssh_option() { local -a BASH_RPC_SSH_OPTIONS=("${BASH_RPC_SSH_OPTIONS[@]}") BASH_RPC_SSH_OPTIONS+=("$1") shift "$@" } # Preserves the rest of stdin for the command. __bashrpc__eval_stdin() { [ "$1" ] && read -N"$1" -r || return # Prepare "$@" for script execution context. shift # Even unset REPLY to leave pristine environment. eval "unset REPLY; $REPLY" } __bashrpc__run_function_simple() { script_source=$(declare -f "$1" && printf '"$@";\n') __bashrpc__remote_run_script \ "$script_source" \ "$@" } __bashrpc__notty_stage1() { [ "$1" ] && read -N"$1" -r && # Read script from stdin, munges REPLY shift && # Prepare "$@" for script execution context. eval "unset REPLY; $REPLY" # Unset munged REPLY in exec context } __bashrpc__remote_run_stage1_notty() { stage1_source=$( declare -f __bashrpc__notty_stage1 | sed -Ene 's/^ {4}//p' ) stage2_source=$1 shift { printf '%s' "$stage2_source" cat } | __bashrpc__remote_run_script \ "$stage1_source" "${#stage2_source}" \ "$@" } __bashrpc__read_stdin() { REPLY= read -r -N2147483647 || [ "$REPLY" ] } __bashrpc__tty_stage1() { local SET_TERM="$1" local PRELUDE="shift;${BASH_RPC_TRACE_REMOTE:+ set -x;}" __bashrpc__read_stdin <\n' "${BASH_RPC_SSH_OPTIONS[@]}" >&2 TERM="$stage2_source" \ __bashrpc__with_ssh_option -t \ __bashrpc__remote_run_script \ "$stage1_source" "$@" ) } remote_run_function() { main=$1 # funcs=$(compgen -A function) funcs=$(recursive_dependencies "$main") stage2_source=$( declare -f $funcs printf '"$@"\n' ) if [ -t 0 ] then __bashrpc__remote_run_stage1_tty "$stage2_source" "$@" else __bashrpc__remote_run_stage1_notty "$stage2_source" "$@" fi }