ssh kitten: Support system where the login shell is a non-POSIX shell
Now the kitten passes its script to /bin/sh and detects the login shell using various strategies based on the value of $USER on the remote machine. The strategies are tried one after another till one succeeds: 1) getent passwd $USER 2) id -P 3) python pwd module 4) parsing /etc/passwd The hope is that these strategies will fail on fewer systems than relying on the login shell being POSIX compliant.
This commit is contained in:
parent
32d275c138
commit
fd4c7a4ed2
@ -16,6 +16,8 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
|
||||
- Fix a regression in 0.21.0 that broke rendering of private use Unicode symbols followed
|
||||
by spaces, when they also exist not followed by spaces (:iss:`3729`)
|
||||
|
||||
- ssh kitten: Support system where the login shell is a non-POSIX shell
|
||||
|
||||
- Add support for the XTVERSION escape code
|
||||
|
||||
- macOS: Fix a regression in 0.21.0 that broke middle-click to paste from clipboard (:iss:`3730`)
|
||||
|
||||
@ -55,7 +55,8 @@ type it each time::
|
||||
alias ssh="kitty +kitten ssh"
|
||||
|
||||
If for some reason that does not work (typically because the server is using a
|
||||
non POSIX compliant shell), you can try using it with python instead::
|
||||
non POSIX compliant shell as ``/bin/sh``), you can try using it with ``python``
|
||||
instead::
|
||||
|
||||
kitty +kitten ssh use-python myserver
|
||||
|
||||
|
||||
@ -21,27 +21,83 @@ cat >$tmp << 'TERMEOF'
|
||||
TERMINFO
|
||||
TERMEOF
|
||||
|
||||
tic_out=$(tic -x -o ~/.terminfo $tmp 2>&1)
|
||||
tic_out=$(tic -x -o $HOME/.terminfo $tmp 2>&1)
|
||||
rc=$?
|
||||
rm $tmp
|
||||
if [ "$rc" != "0" ]; then echo "$tic_out"; exit 1; fi
|
||||
if [ -z "$USER" ]; then export USER=$(whoami); fi
|
||||
shell_name=$(basename $0)
|
||||
export TERMINFO="$HOME/.terminfo"
|
||||
login_shell=""
|
||||
python=""
|
||||
|
||||
login_shell_is_ok() {
|
||||
if [ -z "$login_shell" ] || [ ! -x "$login_shell" ]; then return 1; fi
|
||||
case "$login_shell" in
|
||||
*sh) return 0;
|
||||
esac
|
||||
return 1;
|
||||
}
|
||||
|
||||
detect_python() {
|
||||
python=$(command -v python3)
|
||||
if [ -z "$python" ]; then python=$(command -v python2); fi
|
||||
if [ -z "$python" ]; then python=python; fi
|
||||
}
|
||||
|
||||
using_getent() {
|
||||
cmd=$(command -v getent)
|
||||
if [ -z "$cmd" ]; then return; fi
|
||||
output=$($cmd passwd $USER 2>/dev/null)
|
||||
if [ $? = 0 ]; then login_shell=$(echo $output | cut -d: -f7); fi
|
||||
}
|
||||
|
||||
using_id() {
|
||||
cmd=$(command -v id)
|
||||
if [ -z "$cmd" ]; then return; fi
|
||||
output=$($cmd -P $USER 2>/dev/null)
|
||||
if [ $? = 0 ]; then login_shell=$(echo $output | cut -d: -f7); fi
|
||||
}
|
||||
|
||||
using_passwd() {
|
||||
cmd=$(command -v grep)
|
||||
if [ -z "$cmd" ]; then return; fi
|
||||
output=$($cmd "^$USER:" /etc/passwd 2>/dev/null)
|
||||
if [ $? = 0 ]; then login_shell=$(echo $output | cut -d: -f7); fi
|
||||
}
|
||||
|
||||
using_python() {
|
||||
detect_python
|
||||
if [ ! -x "$python" ]; then return; fi
|
||||
output=$($python -c "import pwd, os; print(pwd.getpwuid(os.geteuid()).pw_shell)")
|
||||
if [ $? = 0 ]; then login_shell=$output; fi
|
||||
}
|
||||
|
||||
execute_with_python() {
|
||||
detect_python
|
||||
exec $python -c "import os; os.execl('$login_shell', '-' '$shell_name')"
|
||||
}
|
||||
|
||||
die() { echo "$*" 1>&2 ; exit 1; }
|
||||
|
||||
using_getent
|
||||
if ! login_shell_is_ok; then using_id; fi
|
||||
if ! login_shell_is_ok; then using_python; fi
|
||||
if ! login_shell_is_ok; then using_passwd; fi
|
||||
if ! login_shell_is_ok; then die "Could not detect login shell"; fi
|
||||
|
||||
|
||||
# If a command was passed to SSH execute it here
|
||||
EXEC_CMD
|
||||
|
||||
# We need to pass the first argument to the executed program with a leading -
|
||||
# to make sure the shell executes as a login shell. Note that not all shells
|
||||
# support exec -a so we use the below to try to detect such shells
|
||||
|
||||
case "dash" in
|
||||
*$shell_name*)
|
||||
python=$(command -v python3)
|
||||
if [ -z "$python" ]; then python=$(command -v python2); fi
|
||||
if [ -z "$python" ]; then python=python; fi
|
||||
exec $python -c "import os; os.execlp('$0', '-' '$shell_name')"
|
||||
;;
|
||||
esac
|
||||
exec -a "-$shell_name" "$0"
|
||||
shell_name=$(basename $login_shell)
|
||||
if [ -z "$PIPESTATUS" ]; then
|
||||
# the dash shell does not support exec -a and also does not define PIPESTATUS
|
||||
execute_with_python
|
||||
fi
|
||||
exec -a "-$shell_name" $login_shell
|
||||
'''
|
||||
|
||||
|
||||
@ -184,9 +240,9 @@ def get_posix_cmd(terminfo: str, remote_args: List[str]) -> List[str]:
|
||||
# line 1129 of ssh.c and on the remote side sshd.c runs the
|
||||
# concatenated command as shell -c cmd
|
||||
args = [c.replace("'", """'"'"'""") for c in remote_args]
|
||||
command_to_execute = "exec $0 -c '{}'".format(' '.join(args))
|
||||
command_to_execute = "exec $login_shell -c '{}'".format(' '.join(args))
|
||||
sh_script = sh_script.replace('EXEC_CMD', command_to_execute)
|
||||
return [sh_script] + remote_args
|
||||
return [f'/bin/sh -c {shlex.quote(sh_script)}']
|
||||
|
||||
|
||||
def get_python_cmd(terminfo: str, command_to_execute: List[str]) -> List[str]:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user