mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2025-11-22 13:36:17 +00:00
Update flask_terminal_routes.py
This commit is contained in:
@@ -13,7 +13,8 @@ import select
|
|||||||
import struct
|
import struct
|
||||||
import fcntl
|
import fcntl
|
||||||
import termios
|
import termios
|
||||||
import signal
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
terminal_bp = Blueprint('terminal', __name__)
|
terminal_bp = Blueprint('terminal', __name__)
|
||||||
sock = Sock()
|
sock = Sock()
|
||||||
@@ -34,6 +35,25 @@ def set_winsize(fd, rows, cols):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error setting window size: {e}")
|
print(f"Error setting window size: {e}")
|
||||||
|
|
||||||
|
def read_and_forward_output(master_fd, ws):
|
||||||
|
"""Read from PTY and send to WebSocket"""
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
# Use select with timeout to check if data is available
|
||||||
|
r, _, _ = select.select([master_fd], [], [], 0.01)
|
||||||
|
if master_fd in r:
|
||||||
|
try:
|
||||||
|
data = os.read(master_fd, 4096)
|
||||||
|
if data:
|
||||||
|
ws.send(data.decode('utf-8', errors='ignore'))
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
except OSError:
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error reading from PTY: {e}")
|
||||||
|
break
|
||||||
|
|
||||||
@sock.route('/ws/terminal')
|
@sock.route('/ws/terminal')
|
||||||
def terminal_websocket(ws):
|
def terminal_websocket(ws):
|
||||||
"""WebSocket endpoint for terminal sessions"""
|
"""WebSocket endpoint for terminal sessions"""
|
||||||
@@ -62,44 +82,41 @@ def terminal_websocket(ws):
|
|||||||
fcntl.fcntl(master_fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)
|
fcntl.fcntl(master_fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)
|
||||||
|
|
||||||
# Set initial terminal size
|
# Set initial terminal size
|
||||||
set_winsize(master_fd, 24, 80)
|
set_winsize(master_fd, 30, 120)
|
||||||
|
|
||||||
|
# Start thread to read PTY output and forward to WebSocket
|
||||||
|
output_thread = threading.Thread(
|
||||||
|
target=read_and_forward_output,
|
||||||
|
args=(master_fd, ws),
|
||||||
|
daemon=True
|
||||||
|
)
|
||||||
|
output_thread.start()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
# Use select to wait for data from either WebSocket or PTY
|
# Receive data from WebSocket (blocking)
|
||||||
readable, _, _ = select.select([ws.sock, master_fd], [], [], 0.1)
|
data = ws.receive(timeout=None)
|
||||||
|
|
||||||
# Read from WebSocket (user input)
|
if data is None:
|
||||||
if ws.sock in readable:
|
# Client closed connection
|
||||||
|
break
|
||||||
|
|
||||||
|
# Handle terminal resize (optional)
|
||||||
|
if data.startswith('\x1b[8;'):
|
||||||
try:
|
try:
|
||||||
data = ws.receive(timeout=0)
|
parts = data[4:-1].split(';')
|
||||||
if data is None:
|
rows, cols = int(parts[0]), int(parts[1])
|
||||||
break
|
set_winsize(master_fd, rows, cols)
|
||||||
|
continue
|
||||||
# Handle special commands (optional)
|
|
||||||
if data.startswith('\x1b[8;'): # Terminal resize
|
|
||||||
# Parse resize: ESC[8;{rows};{cols}t
|
|
||||||
try:
|
|
||||||
parts = data[4:-1].split(';')
|
|
||||||
rows, cols = int(parts[0]), int(parts[1])
|
|
||||||
set_winsize(master_fd, rows, cols)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
# Send input to bash
|
|
||||||
os.write(master_fd, data.encode('utf-8'))
|
|
||||||
except:
|
except:
|
||||||
break
|
pass
|
||||||
|
|
||||||
# Read from PTY (bash output)
|
# Send input to bash
|
||||||
if master_fd in readable:
|
try:
|
||||||
try:
|
os.write(master_fd, data.encode('utf-8'))
|
||||||
output = os.read(master_fd, 4096)
|
except OSError as e:
|
||||||
if output:
|
print(f"Error writing to PTY: {e}")
|
||||||
ws.send(output.decode('utf-8', errors='ignore'))
|
break
|
||||||
except OSError:
|
|
||||||
# PTY closed
|
|
||||||
break
|
|
||||||
|
|
||||||
# Check if process is still alive
|
# Check if process is still alive
|
||||||
if shell_process.poll() is not None:
|
if shell_process.poll() is not None:
|
||||||
@@ -113,15 +130,23 @@ def terminal_websocket(ws):
|
|||||||
shell_process.terminate()
|
shell_process.terminate()
|
||||||
shell_process.wait(timeout=1)
|
shell_process.wait(timeout=1)
|
||||||
except:
|
except:
|
||||||
shell_process.kill()
|
try:
|
||||||
|
shell_process.kill()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
os.close(master_fd)
|
try:
|
||||||
os.close(slave_fd)
|
os.close(master_fd)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.close(slave_fd)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
if session_id in active_sessions:
|
if session_id in active_sessions:
|
||||||
del active_sessions[session_id]
|
del active_sessions[session_id]
|
||||||
|
|
||||||
ws.close()
|
|
||||||
|
|
||||||
def init_terminal_routes(app):
|
def init_terminal_routes(app):
|
||||||
"""Initialize terminal routes with Flask app"""
|
"""Initialize terminal routes with Flask app"""
|
||||||
|
|||||||
Reference in New Issue
Block a user