Skip to content

Commit fc89e12

Browse files
committed
Fix stdin to use a pty on Unix
This prevents the internal shell from trying to buffer stdin, causing none of the data piped into it to actually go through until the process is closed. The holdover is only required on Unix. Windows doesn't support PTY but it also doesn't seem to care and never buffers stdin as far as I can see anyway.
1 parent dde677f commit fc89e12

File tree

2 files changed

+25
-5
lines changed

2 files changed

+25
-5
lines changed

jishaku/features/shell.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,12 @@ def __init__(self, reader: ShellReader, *args: typing.Any, **kwargs: typing.Any)
8484
async def on_submit(self, interaction: discord.Interaction, /):
8585
value = self.stdin_content.value or ""
8686

87-
if self.reader.process.stdin and self.reader.process.stdin.writable():
88-
self.reader.process.stdin.write(f"{value}\r".encode('utf-8'))
89-
self.reader.process.stdin.flush()
87+
if self.reader.stdin and self.reader.stdin.writable():
88+
if sys.platform == "win32":
89+
self.reader.stdin.write(f"{value}\r\n".encode('utf-8'))
90+
else:
91+
self.reader.stdin.write(f"{value}\r".encode('utf-8'))
92+
self.reader.stdin.flush()
9093

9194
await interaction.response.send_message(
9295
content="Sent into stdin",

jishaku/shell.py

+19-2
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,36 @@ def __init__(
7474
self.highlight = "cmd"
7575
# Windows doesn't use ANSI codes
7676
self.escape_ansi = True
77+
78+
self.process = subprocess.Popen( # pylint: disable=consider-using-with
79+
sequence,
80+
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE
81+
)
82+
83+
self.stdin = self.process.stdin
84+
self.stdout = self.process.stdout
7785
else:
86+
import pty # pylint: disable=import-outside-toplevel
87+
7888
sequence = [SHELL, '-c', code]
7989
self.ps1 = "$"
8090
self.highlight = "ansi"
8191
self.escape_ansi = escape_ansi
8292

83-
self.process = subprocess.Popen(sequence, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # pylint: disable=consider-using-with
93+
master_in, slave_in = pty.openpty()
94+
self.process = subprocess.Popen( # pylint: disable=consider-using-with
95+
sequence,
96+
stdin=slave_in, stdout=subprocess.PIPE, stderr=subprocess.PIPE
97+
)
98+
self.stdin = os.fdopen(master_in, 'wb')
99+
self.stdout = self.process.stdout
100+
84101
self.close_code = None
85102

86103
self.loop = loop or asyncio.get_event_loop()
87104
self.timeout = timeout
88105

89-
self.stdout_task = self.make_reader_task(self.process.stdout, self.stdout_handler) if self.process.stdout else None
106+
self.stdout_task = self.make_reader_task(self.stdout, self.stdout_handler) if self.process.stdout else None
90107
self.stderr_task = self.make_reader_task(self.process.stderr, self.stderr_handler) if self.process.stderr else None
91108

92109
self.queue: 'asyncio.Queue[str]' = asyncio.Queue(maxsize=250)

0 commit comments

Comments
 (0)