Use a new controlling terminal when reading shell environment
This is because some people do things in their rc files based on checking the name of the controlling terminal.
This commit is contained in:
parent
6958ded4c4
commit
bdade7e151
@ -118,6 +118,10 @@ def remove_cloexec(fd):
|
||||
fcntl.fcntl(fd, fcntl.F_SETFD, fcntl.fcntl(fd, fcntl.F_GETFD) & ~fcntl.FD_CLOEXEC)
|
||||
|
||||
|
||||
def remove_blocking(fd):
|
||||
os.set_blocking(fd, False)
|
||||
|
||||
|
||||
def default_env():
|
||||
try:
|
||||
return default_env.env
|
||||
@ -132,6 +136,13 @@ def set_default_env(val=None):
|
||||
default_env.env = env
|
||||
|
||||
|
||||
def openpty():
|
||||
master, slave = os.openpty() # Note that master and slave are in blocking mode
|
||||
remove_cloexec(slave)
|
||||
fast_data_types.set_iutf8_fd(master, True)
|
||||
return master, slave
|
||||
|
||||
|
||||
class Child:
|
||||
|
||||
child_fd = pid = None
|
||||
@ -178,9 +189,7 @@ class Child:
|
||||
if self.forked:
|
||||
return
|
||||
self.forked = True
|
||||
master, slave = os.openpty() # Note that master and slave are in blocking mode
|
||||
remove_cloexec(slave)
|
||||
fast_data_types.set_iutf8_fd(master, True)
|
||||
master, slave = openpty()
|
||||
stdin, self.stdin = self.stdin, None
|
||||
ready_read_fd, ready_write_fd = os.pipe()
|
||||
remove_cloexec(ready_read_fd)
|
||||
@ -206,7 +215,7 @@ class Child:
|
||||
fast_data_types.thread_write(stdin_write_fd, stdin)
|
||||
os.close(ready_read_fd)
|
||||
self.terminal_ready_fd = ready_write_fd
|
||||
fcntl.fcntl(self.child_fd, fcntl.F_SETFL, fcntl.fcntl(self.child_fd, fcntl.F_GETFL) | os.O_NONBLOCK)
|
||||
remove_blocking(self.child_fd)
|
||||
return pid
|
||||
|
||||
def mark_terminal_ready(self):
|
||||
|
||||
@ -10,7 +10,7 @@ from contextlib import contextmanager, suppress
|
||||
|
||||
from .borders import load_borders_program
|
||||
from .boss import Boss
|
||||
from .child import set_default_env
|
||||
from .child import set_default_env, openpty, remove_blocking
|
||||
from .cli import create_opts, parse_args
|
||||
from .config import cached_values_for, initial_window_size_func
|
||||
from .constants import (
|
||||
@ -203,23 +203,37 @@ def macos_cmdline(argv_args):
|
||||
return ans
|
||||
|
||||
|
||||
def read_shell_environment(opts):
|
||||
def read_shell_environment(opts=None):
|
||||
if not hasattr(read_shell_environment, 'ans'):
|
||||
import subprocess
|
||||
from .session import resolved_shell
|
||||
shell = resolved_shell(opts)
|
||||
p = subprocess.Popen(shell + ['-l', '-c', 'env'], stdout=subprocess.PIPE)
|
||||
raw = p.stdout.read()
|
||||
if p.wait() == 0:
|
||||
raw = raw.decode('utf-8', 'replace')
|
||||
ans = read_shell_environment.ans = {}
|
||||
for line in raw.splitlines():
|
||||
k, v = line.partition('=')[::2]
|
||||
if k and v:
|
||||
ans[k] = v
|
||||
else:
|
||||
log_error('Failed to run shell to read its environment')
|
||||
read_shell_environment.ans = {}
|
||||
master, slave = openpty()
|
||||
remove_blocking(master)
|
||||
p = subprocess.Popen(shell + ['-l', '-c', 'env'], stdout=slave, stdin=slave, stderr=slave, start_new_session=True, close_fds=True)
|
||||
with os.fdopen(master, 'rb') as stdout, os.fdopen(slave, 'wb'):
|
||||
raw = b''
|
||||
while p.wait(0.01) is None:
|
||||
with suppress(Exception):
|
||||
raw += stdout.read()
|
||||
if p.returncode == 0:
|
||||
while True:
|
||||
try:
|
||||
x = stdout.read()
|
||||
except Exception:
|
||||
break
|
||||
if not x:
|
||||
break
|
||||
raw += x
|
||||
raw = raw.decode('utf-8', 'replace')
|
||||
ans = read_shell_environment.ans = {}
|
||||
for line in raw.splitlines():
|
||||
k, v = line.partition('=')[::2]
|
||||
if k and v:
|
||||
ans[k] = v
|
||||
else:
|
||||
log_error('Failed to run shell to read its environment')
|
||||
read_shell_environment.ans = {}
|
||||
return read_shell_environment.ans
|
||||
|
||||
|
||||
|
||||
@ -74,8 +74,8 @@ class Session:
|
||||
self.tabs[-1].cwd = val
|
||||
|
||||
|
||||
def resolved_shell(opts):
|
||||
ans = opts.shell
|
||||
def resolved_shell(opts=None):
|
||||
ans = getattr(opts, 'shell', '.')
|
||||
if ans == '.':
|
||||
ans = [shell_path]
|
||||
else:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user