v1.8.5: restore sudo auto-password + fix sudo SFTP operations

Terminal:
- Auto-detect [sudo] password prompts in interactive shell output
- Auto-send server password when sudo prompt detected
- Reset detection flag on new command (Enter key)

SSH client (SFTPSession):
- Fix exec_command() sudo password timing (0.1s delay for prompt)
- Fix listdir_attr_sudo() ls output parsing with proper maxsplit
- Handle filenames with spaces, symlinks, and varied ls formats

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chrome-storm-c442
2026-02-24 03:48:30 -05:00
parent 6144c17a96
commit f7c7fe731f
4 changed files with 43 additions and 15 deletions

View File

@@ -37,6 +37,10 @@ class TerminalTab(ctk.CTkFrame):
# Thread-safe data queue
self._data_queue: queue.Queue[bytes] = queue.Queue()
# Sudo auto-password detection
self._sudo_buffer = b"" # Buffer for detecting sudo prompts
self._sudo_sent = False # Prevent sending password twice for same prompt
def set_server(self, alias: str | None):
if alias == self._current_alias:
return
@@ -151,7 +155,20 @@ class TerminalTab(ctk.CTkFrame):
except queue.Empty:
pass
if chunks:
self._terminal.feed(b"".join(chunks))
combined = b"".join(chunks)
self._sudo_buffer += combined
# Keep only last 200 bytes for pattern matching
self._sudo_buffer = self._sudo_buffer[-200:]
if not self._sudo_sent:
buf_str = self._sudo_buffer.decode("utf-8", errors="replace").lower()
if "[sudo] password for" in buf_str or buf_str.rstrip().endswith("password:"):
server = self.store.get_server(self._current_alias)
if server and server.get("password"):
self._session.send(server["password"].encode() + b"\n")
self._sudo_sent = True
self._terminal.feed(combined)
def _on_disconnected(self):
"""Called from SSH read thread."""
@@ -189,6 +206,9 @@ class TerminalTab(ctk.CTkFrame):
session = self._session # local ref for thread safety
if session and session.connected:
session.send(data)
# Reset sudo sent flag when user sends a new command (detects \r or \n)
if b'\r' in data or b'\n' in data:
self._sudo_sent = False
elif self._current_alias and not self._intentional_disconnect and self._reconnect_count == 0:
# Session dead, no reconnect in progress — trigger one attempt
self._on_disconnected()