diff --git a/kitty_tests/ssh.py b/kitty_tests/ssh.py index 0fdc21177..48a336641 100644 --- a/kitty_tests/ssh.py +++ b/kitty_tests/ssh.py @@ -12,7 +12,7 @@ from contextlib import suppress from functools import lru_cache from kittens.ssh.utils import get_connection_data -from kitty.constants import is_macos, kitten_exe, runtime_dir +from kitty.constants import is_macos, kitten_exe, kitty_base_dir, runtime_dir from kitty.fast_data_types import CURSOR_BEAM, shm_unlink from kitty.utils import SSHConnectionData @@ -201,6 +201,38 @@ env COLORTERM pty = self.check_bootstrap(sh, tdir, test_script=f'{m}; echo "$login_shell"; exit 0', SHELL_INTEGRATION_VALUE='') self.assertIn(expected_login_shell, pty.screen_contents()) + def test_ssh_login_shell_fallback_quoting(self): + bootstrap_utils = os.path.join(kitty_base_dir, 'shell-integration', 'ssh', 'bootstrap-utils.sh') + python = shutil.which('python3') or shutil.which('python2') or shutil.which('python') + if python is None: + self.skipTest('Python executable not found') + runners = [('execute_with_python', python, 'PYTHON_FOR_TEST')] + if perl := shutil.which('perl'): + runners.append(('execute_with_perl', perl, 'PERL_FOR_TEST')) + script = '''\ +. "$BOOTSTRAP_UTILS" +detect_python() { python="$PYTHON_FOR_TEST"; return 0; } +detect_perl() { perl="$PERL_FOR_TEST"; return 0; } +login_shell=$LOGIN_SHELL +shell_name=$(command basename "$login_shell") +"$EXEC_FUNC" +''' + for func, executable, env_key in runners: + with tempfile.TemporaryDirectory() as tdir: + login_shell = os.path.join(tdir, "login shell's python") + os.symlink(python, login_shell) + env = { + 'PATH': os.environ.get('PATH', '/usr/bin:/bin'), + 'BOOTSTRAP_UTILS': bootstrap_utils, + 'EXEC_FUNC': func, + 'LOGIN_SHELL': login_shell, + env_key: executable, + } + cp = subprocess.run( + ['sh', '-c', script], env=env, stdin=subprocess.DEVNULL, + stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + self.assertEqual(cp.returncode, 0, cp.stderr + cp.stdout) + @retry_on_failure() def test_ssh_shell_integration(self): ok_login_shell = '' diff --git a/shell-integration/ssh/bootstrap-utils.sh b/shell-integration/ssh/bootstrap-utils.sh index d152b575b..e834c9a61 100644 --- a/shell-integration/ssh/bootstrap-utils.sh +++ b/shell-integration/ssh/bootstrap-utils.sh @@ -87,14 +87,14 @@ using_shell_env() { execute_with_python() { if detect_python; then - exec "$python" "-c" "import os; os.execlp('$login_shell', '-' '$shell_name')" + exec "$python" "-c" 'import os, sys; os.execlp(sys.argv[1], "-" + sys.argv[2])' "$login_shell" "$shell_name" fi return 1 } execute_with_perl() { if detect_perl; then - exec "$perl" "-e" "exec {'$login_shell'} '-$shell_name'" + exec "$perl" "-e" 'exec {$ARGV[0]} ("-" . $ARGV[1])' "$login_shell" "$shell_name" fi return 1 } @@ -215,7 +215,7 @@ prepare_for_exec() { fi ;; esac - shell_name=$(command basename $login_shell) + shell_name=$(command basename "$login_shell") [ -n "$login_cwd" ] && cd "$login_cwd" }