Dont rely on env -0 for bash either

This commit is contained in:
Kovid Goyal 2022-04-15 13:33:32 +05:30
parent bde468594e
commit e71b9091a3
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 55 additions and 9 deletions

View File

@ -497,6 +497,51 @@ def parse_opts_for_clone(args: List[str]) -> LaunchCLIOptions:
return default_opts
def parse_bash_env(text: str) -> Dict[str, str]:
# See https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html
ans = {}
pos = 0
escapes = r'"\$`'
while pos < len(text):
idx = text.find('="', pos)
if idx < 0:
break
i = text.rfind(' ', 0, idx)
if i < 0:
break
key = text[i+1:idx]
pos = idx + 2
buf: List[str] = []
a = buf.append
while pos < len(text):
ch = text[pos]
pos += 1
if ch == '\\':
if text[pos] in escapes:
a(text[pos])
pos += 1
continue
a(ch)
elif ch == '"':
break
else:
a(ch)
ans[key] = ''.join(buf)
return ans
def parse_null_env(text: str) -> Dict[str, str]:
ans = {}
for line in text.split('\0'):
if line:
try:
k, v = line.split('=', 1)
except ValueError:
continue
ans[k] = v
return ans
class CloneCmd:
def __init__(self, msg: str) -> None:
@ -504,6 +549,7 @@ class CloneCmd:
self.args: List[str] = []
self.env: Optional[Dict[str, str]] = None
self.cwd = ''
self.envfmt = 'default'
self.pid = -1
self.parse_message(msg)
self.opts = parse_opts_for_clone(self.args)
@ -520,14 +566,7 @@ class CloneCmd:
if k == 'a':
self.args.append(v)
elif k == 'env':
self.env = {}
for line in v.split('\0'):
if line:
try:
k, v = line.split('=', 1)
except ValueError:
continue
self.env[k] = v
self.env = parse_bash_env(v) if self.envfmt == 'bash' else parse_null_env(v)
elif k == 'cwd':
self.cwd = v
elif k == 'argv':

View File

@ -357,3 +357,10 @@ PS1="{ps1}"
run_test('bash +O login_shell -ic "echo ok;read"', 'bash.bashrc', excluded=('.bash_profile'), wait_string='ok', assert_not_in=True)
run_test('bash -l .bashrc', 'profile', rc='echo ok;read', wait_string='ok', assert_not_in=True)
run_test('bash -il -- .bashrc', 'profile', rc='echo ok;read', wait_string='ok')
with self.run_shell(rc=f'''PS1="{ps1}"\nexport ES=$'a\n `b` c\n$d' ''') as pty:
pty.callbacks.clear()
pty.send_cmd_to_child('clone-in-kitty')
pty.wait_till(lambda: len(pty.callbacks.clone_cmds) == 1)
env = pty.callbacks.clone_cmds[0].env
self.ae(env.get('ES'), 'a\n `b` c\n$d')

View File

@ -276,7 +276,7 @@ case :$SHELLOPTS: in
*:posix:*) ;;
*)
clone-in-kitty() {
builtin local data="argv=${_ksi_prompt[argv]},cwd=$(builtin printf "%s" "$PWD" | builtin command base64),env=$(builtin command env -0 | builtin command base64)"
builtin local data="argv=${_ksi_prompt[argv]},cwd=$(builtin printf "%s" "$PWD" | builtin command base64),envfmt=bash,env=$(builtin export | builtin command base64)"
while :; do
case "$1" in
"") break;;