Add an option to control the login shell
This commit is contained in:
parent
0bd1676978
commit
01dd0416ac
@ -96,6 +96,8 @@ def make_tarfile(ssh_opts: SSHOptions, base_env: Dict[str, str]) -> bytes:
|
|||||||
env.update(ssh_opts.env)
|
env.update(ssh_opts.env)
|
||||||
env['KITTY_SHELL_INTEGRATION'] = ksi or DELETE_ENV_VAR
|
env['KITTY_SHELL_INTEGRATION'] = ksi or DELETE_ENV_VAR
|
||||||
env['KITTY_SSH_KITTEN_DATA_DIR'] = ssh_opts.remote_dir
|
env['KITTY_SSH_KITTEN_DATA_DIR'] = ssh_opts.remote_dir
|
||||||
|
if ssh_opts.login_shell:
|
||||||
|
env['KITTY_LOGIN_SHELL'] = ssh_opts.login_shell
|
||||||
env_script = serialize_env(env, base_env)
|
env_script = serialize_env(env, base_env)
|
||||||
buf = io.BytesIO()
|
buf = io.BytesIO()
|
||||||
with tarfile.open(mode='w:bz2', fileobj=buf, encoding='utf-8') as tf:
|
with tarfile.open(mode='w:bz2', fileobj=buf, encoding='utf-8') as tf:
|
||||||
@ -173,7 +175,7 @@ def prepare_script(ans: str, replacements: Dict[str, str]) -> str:
|
|||||||
atexit.register(safe_remove, tf.name)
|
atexit.register(safe_remove, tf.name)
|
||||||
replacements['DATA_PASSWORD'] = pw
|
replacements['DATA_PASSWORD'] = pw
|
||||||
replacements['PASSWORD_FILENAME'] = os.path.basename(tf.name)
|
replacements['PASSWORD_FILENAME'] = os.path.basename(tf.name)
|
||||||
for k in ('EXEC_CMD', 'OVERRIDE_LOGIN_SHELL'):
|
for k in ('EXEC_CMD',):
|
||||||
replacements[k] = replacements.get(k, '')
|
replacements[k] = replacements.get(k, '')
|
||||||
|
|
||||||
def sub(m: 're.Match[str]') -> str:
|
def sub(m: 're.Match[str]') -> str:
|
||||||
|
|||||||
@ -91,5 +91,8 @@ for details on how this setting works. The special value :code:`inherit` means
|
|||||||
use the setting from kitty.conf. This setting is useful for overriding
|
use the setting from kitty.conf. This setting is useful for overriding
|
||||||
integration on a per-host basis.''')
|
integration on a per-host basis.''')
|
||||||
|
|
||||||
|
opt('login_shell', '', long_text='''
|
||||||
|
The login shell to execute on the remote host. By default, the remote user account's
|
||||||
|
login shell is used.''')
|
||||||
|
|
||||||
egr() # }}}
|
egr() # }}}
|
||||||
|
|||||||
@ -21,6 +21,9 @@ class Parser:
|
|||||||
def interpreter(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
def interpreter(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||||
ans['interpreter'] = str(val)
|
ans['interpreter'] = str(val)
|
||||||
|
|
||||||
|
def login_shell(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||||
|
ans['login_shell'] = str(val)
|
||||||
|
|
||||||
def remote_dir(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
def remote_dir(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||||
ans['remote_dir'] = relative_dir(val)
|
ans['remote_dir'] = relative_dir(val)
|
||||||
|
|
||||||
|
|||||||
@ -5,12 +5,19 @@ import kittens.ssh.copy
|
|||||||
|
|
||||||
|
|
||||||
option_names = ( # {{{
|
option_names = ( # {{{
|
||||||
'copy', 'env', 'hostname', 'interpreter', 'remote_dir', 'shell_integration') # }}}
|
'copy',
|
||||||
|
'env',
|
||||||
|
'hostname',
|
||||||
|
'interpreter',
|
||||||
|
'login_shell',
|
||||||
|
'remote_dir',
|
||||||
|
'shell_integration') # }}}
|
||||||
|
|
||||||
|
|
||||||
class Options:
|
class Options:
|
||||||
hostname: str = '*'
|
hostname: str = '*'
|
||||||
interpreter: str = 'sh'
|
interpreter: str = 'sh'
|
||||||
|
login_shell: str = ''
|
||||||
remote_dir: str = '.local/share/kitty-ssh-kitten'
|
remote_dir: str = '.local/share/kitty-ssh-kitten'
|
||||||
shell_integration: str = 'inherit'
|
shell_integration: str = 'inherit'
|
||||||
copy: typing.Dict[str, kittens.ssh.copy.CopyInstruction] = {}
|
copy: typing.Dict[str, kittens.ssh.copy.CopyInstruction] = {}
|
||||||
|
|||||||
@ -84,7 +84,7 @@ print(' '.join(map(str, buf)))'''), lines=13, cols=77)
|
|||||||
@property
|
@property
|
||||||
@lru_cache()
|
@lru_cache()
|
||||||
def all_possible_sh(self):
|
def all_possible_sh(self):
|
||||||
return tuple(sh for sh in ('dash', 'zsh', 'bash', 'posh', 'sh') if shutil.which(sh))
|
return tuple(filter(shutil.which, ('dash', 'zsh', 'bash', 'posh', 'sh')))
|
||||||
|
|
||||||
def test_ssh_copy(self):
|
def test_ssh_copy(self):
|
||||||
simple_data = 'rkjlhfwf9whoaa'
|
simple_data = 'rkjlhfwf9whoaa'
|
||||||
@ -188,6 +188,9 @@ copy --exclude */w.* d1
|
|||||||
if login_shell == 'bash':
|
if login_shell == 'bash':
|
||||||
pty.send_cmd_to_child('echo $HISTFILE')
|
pty.send_cmd_to_child('echo $HISTFILE')
|
||||||
pty.wait_till(lambda: '/.bash_history' in pty.screen_contents())
|
pty.wait_till(lambda: '/.bash_history' in pty.screen_contents())
|
||||||
|
elif login_shell == 'zsh':
|
||||||
|
pty.send_cmd_to_child('echo "login_shell=$ZSH_NAME"')
|
||||||
|
pty.wait_till(lambda: 'login_shell=zsh' in pty.screen_contents())
|
||||||
# check that turning off shell integration works
|
# check that turning off shell integration works
|
||||||
if ok_login_shell in ('bash', 'zsh'):
|
if ok_login_shell in ('bash', 'zsh'):
|
||||||
for val in ('', 'no-rc', 'enabled no-rc'):
|
for val in ('', 'no-rc', 'enabled no-rc'):
|
||||||
@ -197,7 +200,6 @@ copy --exclude */w.* d1
|
|||||||
def check_bootstrap(self, sh, home_dir, login_shell='', SHELL_INTEGRATION_VALUE='enabled', extra_exec='', pre_data='', ssh_opts=None):
|
def check_bootstrap(self, sh, home_dir, login_shell='', SHELL_INTEGRATION_VALUE='enabled', extra_exec='', pre_data='', ssh_opts=None):
|
||||||
script = bootstrap_script(
|
script = bootstrap_script(
|
||||||
EXEC_CMD=f'echo "UNTAR_DONE"; {extra_exec}',
|
EXEC_CMD=f'echo "UNTAR_DONE"; {extra_exec}',
|
||||||
OVERRIDE_LOGIN_SHELL=login_shell,
|
|
||||||
)
|
)
|
||||||
env = basic_shell_env(home_dir)
|
env = basic_shell_env(home_dir)
|
||||||
# Avoid generating unneeded completion scripts
|
# Avoid generating unneeded completion scripts
|
||||||
@ -205,6 +207,9 @@ copy --exclude */w.* d1
|
|||||||
# prevent newuser-install from running
|
# prevent newuser-install from running
|
||||||
open(os.path.join(home_dir, '.zshrc'), 'w').close()
|
open(os.path.join(home_dir, '.zshrc'), 'w').close()
|
||||||
options = {'shell_integration': shell_integration(SHELL_INTEGRATION_VALUE or 'disabled')}
|
options = {'shell_integration': shell_integration(SHELL_INTEGRATION_VALUE or 'disabled')}
|
||||||
|
if login_shell:
|
||||||
|
ssh_opts = ssh_opts or {}
|
||||||
|
ssh_opts['login_shell'] = login_shell
|
||||||
pty = self.create_pty(f'{sh} -c {shlex.quote(script)}', cwd=home_dir, env=env, options=options, ssh_opts=ssh_opts)
|
pty = self.create_pty(f'{sh} -c {shlex.quote(script)}', cwd=home_dir, env=env, options=options, ssh_opts=ssh_opts)
|
||||||
if pre_data:
|
if pre_data:
|
||||||
pty.write_buf = pre_data.encode('utf-8')
|
pty.write_buf = pre_data.encode('utf-8')
|
||||||
|
|||||||
@ -245,9 +245,9 @@ execute_with_python() {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGIN_SHELL="OVERRIDE_LOGIN_SHELL"
|
if [ -n "$KITTY_LOGIN_SHELL" ]; then
|
||||||
if [ -n "$LOGIN_SHELL" ]; then
|
login_shell="$KITTY_LOGIN_SHELL"
|
||||||
login_shell="$LOGIN_SHELL"
|
unset KITTY_LOGIN_SHELL
|
||||||
else
|
else
|
||||||
using_getent || using_id || using_python || using_passwd || die "Could not detect login shell";
|
using_getent || using_id || using_python || using_passwd || die "Could not detect login shell";
|
||||||
fi
|
fi
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user