Get askpass basically working

This commit is contained in:
Kovid Goyal 2022-03-10 22:11:37 +05:30
parent 3b724c8415
commit 61558d518e
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 33 additions and 12 deletions

View File

@ -74,7 +74,7 @@ class HistoryCompleter:
def option_text() -> str: def option_text() -> str:
return '''\ return '''\
--type -t --type -t
choices=line,yesno,choices choices=line,yesno,choices,password
default=line default=line
Type of input. Defaults to asking for a line of text. Type of input. Defaults to asking for a line of text.
@ -361,6 +361,13 @@ def main(args: List[str]) -> Response:
loop.loop(handler) loop.loop(handler)
return {'items': items, 'response': handler.response} return {'items': items, 'response': handler.response}
if cli_opts.type == 'password':
import getpass
if cli_opts.message:
print(styled(cli_opts.message, bold=True))
q = getpass.getpass()
return {'items': items, 'response': q or ''}
import readline as rl import readline as rl
readline = rl readline = rl
from kitty.shell import init_readline from kitty.shell import init_readline

View File

@ -1084,7 +1084,7 @@ dispatch_dcs(Screen *screen, PyObject DUMP_UNUSED *dump_callback) {
} else IF_SIMPLE_PREFIX("kitty-print|", screen_handle_print) } else IF_SIMPLE_PREFIX("kitty-print|", screen_handle_print)
} else IF_SIMPLE_PREFIX("kitty-echo|", screen_handle_echo) } else IF_SIMPLE_PREFIX("kitty-echo|", screen_handle_echo)
} else IF_SIMPLE_PREFIX("kitty-ssh|", screen_handle_ssh) } else IF_SIMPLE_PREFIX("kitty-ssh|", screen_handle_ssh)
} else IF_SIMPLE_PREFIX("kitty-askpass|", screen_handle_askpass) } else IF_SIMPLE_PREFIX("kitty-ask|", screen_handle_askpass)
#undef IF_SIMPLE_PREFIX #undef IF_SIMPLE_PREFIX
} else { } else {
REPORT_ERROR("Unrecognized DCS @ code: 0x%x", screen->parser_buf[1]); REPORT_ERROR("Unrecognized DCS @ code: 0x%x", screen->parser_buf[1]);

View File

@ -3,22 +3,36 @@
import json import json
import os import os
import struct
import sys import sys
import time
from kitty.shm import SharedMemory from kitty.shm import SharedMemory
msg = sys.argv[-1] msg = sys.argv[-1]
prompt = os.environ.get('SSH_ASKPASS_PROMPT', '') prompt = os.environ.get('SSH_ASKPASS_PROMPT', '')
is_confirm = prompt == 'confirm' is_confirm = prompt == 'confirm'
ask_cmdline = ['-m', msg, '--type', 'yesno' if is_confirm else 'password'] q = {
if is_confirm: 'prompt': msg,
ask_cmdline += ['--default', 'y'] 'type': 'confirm' if is_confirm else 'get_line',
data = json.dumps(ask_cmdline).encode('utf-8') 'is_password': True,
sz = struct.pack('>I', len(data)) }
with SharedMemory(size=len(data) + len(sz) + 1, unlink_on_exit=True, prefix=f'askpass-{os.getpid()}-') as shm, open(os.ctermid(), 'wb') as tty:
data = json.dumps(q)
with SharedMemory(size=len(data) + 1 + SharedMemory.num_bytes_for_size, unlink_on_exit=True, prefix=f'askpass-{os.getpid()}-'
) as shm, open(os.ctermid(), 'wb') as tty:
shm.write(b'\0') shm.write(b'\0')
shm.write(sz) shm.write_data_with_size(data)
shm.write(data)
shm.flush() shm.flush()
print(f'\x1bP@kitty-ask|{shm.name}\x1b\\', flush=True) with open(os.ctermid(), 'wb') as f:
f.write(f'\x1bP@kitty-ask|{shm.name}\x1b\\'.encode('ascii'))
while True:
# TODO: Replace sleep() with a mutex and condition variable created in the shared memory
time.sleep(0.05)
shm.seek(0)
if shm.read(1) == b'\x01':
break
response = json.loads(shm.read_data_with_size())
if is_confirm:
response = 'yes' if response else 'no'
if response:
print(response, flush=True)