Skip to content

Commit

Permalink
Make pearl-ssh usable on the remote server
Browse files Browse the repository at this point in the history
- restructure the pearl directory on the remote as discussed at fsquillace#7;
- declare local variables on the function header;
  • Loading branch information
laur89 committed Dec 25, 2015
1 parent 6f9cb1b commit d11c9f3
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 24 deletions.
29 changes: 28 additions & 1 deletion bin/ssh-pearl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,33 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

source "$(dirname $0)/../lib/ssh_pearl.sh"


# Resolves the real (non-linked) location of the node.
#
# @param {string} node full path to the file whose real location we're after.
#
# @returns {string} full path to the node's real location (minus node name).
function resolve_real_path() {
local src dir

src="$1"

[[ "$#" -ne 1 ]] && { echo -e "exactly 1 arg (node location) required. abort." "$FUNCNAME"; return 1; }
[[ -z "$src" ]] && { echo -e "node argument has to be a non-empty string." "$FUNCNAME"; return 1; }
[[ -e "$src" ]] || { echo -e "node argument has to be an existing file." "$FUNCNAME"; return 1; }

while [[ -h "$src" ]]; do # resolve $src until the file is no longer a symlink
src="$(readlink -- "$src")"
if [[ "$src" != /* ]]; then
dir="$(cd -P -- "$(dirname -- "$src")" && pwd)"
src="$dir/$src" # if $src was a relative symlink, we need to resolve it relative to the path where the symlink was located.
fi
done

echo "$(cd -P -- "$(dirname -- "$src")" && pwd)"
}

source "$(resolve_real_path "$0")/../lib/ssh_pearl.sh" || exit 1

ssh_pearl "$@"
97 changes: 74 additions & 23 deletions lib/ssh_pearl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,49 +18,100 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

function ssh_pearl(){
function _aggregate_scripts(){
local fileRc="$1"
local dirRc="$2"
[[ -f "${fileRc}" ]] && cat "${fileRc}"
[[ -d "${dirRc}" ]] && cat "${dirRc}"/*
SELF="$(basename "$0")"
LIBNAME='ssh_pearl.sh'

# Resolves the real (non-linked) location of the node.
#
# @param {string} node full path to the file whose real location we're after.
#
# @returns {string} full path to the node's real location (minus node name).
function resolve_real_path() {
local src dir

src="$1"

[[ "$#" -ne 1 ]] && { echo -e "exactly 1 arg (node location) required. abort." "$FUNCNAME"; return 1; }
[[ -z "$src" ]] && { echo -e "node argument has to be a non-empty string." "$FUNCNAME"; return 1; }
[[ -e "$src" ]] || { echo -e "node argument has to be an existing file." "$FUNCNAME"; return 1; }

while [[ -h "$src" ]]; do # resolve $src until the file is no longer a symlink
src="$(readlink -- "$src")"
if [[ "$src" != /* ]]; then
dir="$(cd -P -- "$(dirname -- "$src")" && pwd)"
src="$dir/$src" # if $src was a relative symlink, we need to resolve it relative to the path where the symlink was located.
fi
done

echo "$(cd -P -- "$(dirname -- "$src")" && pwd)"
}


function ssh_pearl() {
local self lib rcScript inputrcScript vimrcScript ssh_opts opt commands arg commands_opt

commands=()
ssh_opts=()

function _aggregate_scripts() {
local node

for node in "$@"; do
[[ -f "$node" ]] && cat "$node"
[[ -d "$node" ]] && cat "$node"/*
done
}

[[ -z "$@" ]] && { ssh; return $?; }

local ssh_opts=()
for opt in "$@"; do
case "$opt" in
--) shift ; break ;;
*) ssh_opts+=("$opt") ; shift ;;
*) ssh_opts+=("$opt") ; shift ;;
esac
done

local commands=()
for arg in "$@"; do commands+=("$arg"); done
local commands_opt=""
[[ -z "${commands[@]}" ]] || commands_opt="-c '${commands[@]}'"
for arg in "$@"; do
commands+=("$arg")
done

[[ -n "${commands[@]}" ]] && commands_opt="-c '${commands[*]}'"

command -v base64 >/dev/null 2>&1 || { echo >&2 "pearl-ssh requires base64 to be installed locally. Aborting."; return 1; }
command -v gzip >/dev/null 2>&1 || { echo >&2 "pearl-ssh requires gzip to be installed locally. Aborting."; return 1; }

[[ -z "$PEARL_HOME" ]] && PEARL_HOME=${HOME}/.config/pearl

local rcScript="$(_aggregate_scripts "$PEARL_HOME/sshrc" "$PEARL_HOME/sshrc.d" | gzip | base64)"
local inputrcScript="$(_aggregate_scripts "$PEARL_HOME/sshinputrc" "$PEARL_HOME/sshinputrc.d" | gzip | base64)"
local vimrcScript="$(_aggregate_scripts "$PEARL_HOME/sshvimrc" "$PEARL_HOME/sshvimrc.d" | gzip | base64)"
rcScript="$(_aggregate_scripts "$PEARL_HOME/bashrc" "$PEARL_HOME/bashrc.d" | gzip | base64)"
inputrcScript="$(_aggregate_scripts "$PEARL_HOME/inputrc" "$PEARL_HOME/inputrc.d" | gzip | base64)"
vimrcScript="$(_aggregate_scripts "$PEARL_HOME/vimrc" "$PEARL_HOME/vimrc.d" | gzip | base64)"
self="$(gzip < "$0" | base64)"
lib="$(gzip < "$(resolve_real_path "$0")/../lib/$LIBNAME" | base64)"

CMD="
for tmpDir in /tmp \$HOME; do [[ -w \"\$tmpDir\" ]] && { foundTmpDir=\"\$tmpDir\"; break; } done;
[[ -z \"\$foundTmpDir\" ]] && { echo >&2 \"Could not find writable tempdirs on the server. Aborting.\"; exit 1; };
for tmpDir in /tmp \$HOME; do [[ -w \"\$tmpDir\" ]] && { foundTmpDir=\"\$tmpDir\"; break; } done
[[ -z \"\$foundTmpDir\" ]] && { echo >&2 \"couldn't find writable tempdirs on the server. Aborting.\"; exit 1; };
command -v base64 >/dev/null 2>&1 || { echo >&2 \"pearl-ssh requires base64 to be installed on the server. Aborting.\"; exit 1; };
command -v gunzip >/dev/null 2>&1 || { echo >&2 \"pearl-ssh requires gunzip to be installed on the server. Aborting.\"; exit 1; };
PEARLSSH_HOME=\"\$(mktemp -d pearl-XXXXX -p \"\$foundTmpDir\")\";
trap \"rm -rf \"\$PEARLSSH_HOME\"; exit\" EXIT HUP INT QUIT PIPE TERM KILL;
echo \"${rcScript}\" | base64 -di | gunzip > \"\${PEARLSSH_HOME}/bashrc\";
echo \"${inputrcScript}\" | base64 -di | gunzip > \"\${PEARLSSH_HOME}/inputrc\";
echo \"${vimrcScript}\" | base64 -di | gunzip > \"\${PEARLSSH_HOME}/vimrc\";
VIMINIT=\"let \\\$MYVIMRC='\${PEARLSSH_HOME}/vimrc' | source \\\$MYVIMRC\" INPUTRC=\"\${PEARLSSH_HOME}/inputrc\" bash --rcfile \"\${PEARLSSH_HOME}/bashrc\" -i ${commands_opt};
PEARLSSH_ROOT=\"\$(mktemp -d pearl-XXXXX -p \"\$foundTmpDir\")\" || exit 1
PEARLSSH_ETC=\"\$PEARLSSH_ROOT/etc\"
mkdir \"\$PEARLSSH_ETC\" || exit 1
PEARLSSH_BIN=\"\$PEARLSSH_ROOT/bin\"
mkdir \"\$PEARLSSH_BIN\" || exit 1
PEARLSSH_LIB=\"\$PEARLSSH_ROOT/lib\"
mkdir \"\$PEARLSSH_LIB\" || exit 1
export PEARL_HOME=\"\$PEARLSSH_ETC\";
trap \"rm -rf \"\$PEARLSSH_ROOT\"; exit\" EXIT HUP INT QUIT PIPE TERM;
echo \"${rcScript}\" | base64 -di | gunzip > \"\${PEARLSSH_ETC}/bashrc\";
echo \"${inputrcScript}\" | base64 -di | gunzip > \"\${PEARLSSH_ETC}/inputrc\";
echo \"${vimrcScript}\" | base64 -di | gunzip > \"\${PEARLSSH_ETC}/vimrc\";
echo \"${self}\" | base64 -di | gunzip > \"\${PEARLSSH_BIN}/$SELF\";
echo \"${lib}\" | base64 -di | gunzip > \"\${PEARLSSH_LIB}/$LIBNAME\";
chmod -R +x \"\$PEARLSSH_BIN\";
export PATH=\$PATH:\$PEARLSSH_BIN;
VIMINIT=\"let \\\$MYVIMRC='\${PEARLSSH_ETC}/vimrc' | source \\\$MYVIMRC\" INPUTRC=\"\${PEARLSSH_ETC}/inputrc\" bash --rcfile \"\${PEARLSSH_ETC}/bashrc\" -i ${commands_opt};
"

ssh -t "${ssh_opts[@]}" -- "$CMD"
}

0 comments on commit d11c9f3

Please sign in to comment.