Skip to content

Commit 0a62135

Browse files
committed
ghost: fix how control sequence is processed
1 parent 9bac3c1 commit 0a62135

File tree

2 files changed

+27
-39
lines changed

2 files changed

+27
-39
lines changed

overlord/ghost.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1053,7 +1053,6 @@ func (ghost *Ghost) SpawnTTYServer(res *Response) error {
10531053

10541054
feedInput := func(buffer []byte) error {
10551055
escapeStart := bytes.Index(buffer, []byte{0x1b, '['})
1056-
10571056
if escapeStart != -1 {
10581057
tty.Write(buffer[:escapeStart])
10591058
rest, err := ghost.handleTTYControl(tty, buffer[escapeStart:])

py/ghost.py

Lines changed: 27 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -563,27 +563,35 @@ def SendErrorResponse(self, omsg, error):
563563
msg = {'rid': omsg['rid'], 'status': FAILED, 'payload': {'error': error}}
564564
self.SendMessage(msg)
565565

566-
def HandleTTYControl(self, fd, control_str):
566+
def HandleTTYControl(self, fd, buffer):
567567
"""Handle terminal control sequences.
568568
569569
Args:
570570
fd: File descriptor of the terminal
571571
control_str: Control string to process
572+
573+
Returns:
574+
index of the next character after the control sequence
572575
"""
576+
if not buffer.startswith(b'\x1b['):
577+
return 0
578+
579+
t_pos = buffer.find(b't')
580+
if t_pos == -1:
581+
return 0
582+
573583
try:
574-
# Check for ANSI escape sequence for window size
575-
if control_str.startswith('\x1b[') and control_str.endswith('t'):
576-
# Remove ESC[ prefix and 't' suffix
577-
payload = control_str[2:-1].split(';')
578-
if len(payload) >= 3 and payload[0] == '8':
579-
# Window size in characters (rows;cols)
580-
rows = int(payload[1])
581-
cols = int(payload[2])
582-
logging.info('Terminal resize request received: rows=%d, cols=%d', rows, cols)
583-
winsize = struct.pack('HHHH', rows, cols, 0, 0)
584-
fcntl.ioctl(fd, termios.TIOCSWINSZ, winsize)
584+
params = buffer[2:t_pos].split(b';')
585+
if len(params) >= 3 and params[0] == b'8':
586+
rows = int(params[1])
587+
cols = int(params[2])
588+
logging.info('Terminal resize request received: rows=%d, cols=%d', rows, cols)
589+
winsize = struct.pack('HHHH', rows, cols, 0, 0)
590+
fcntl.ioctl(fd, termios.TIOCSWINSZ, winsize)
591+
return t_pos + 1
585592
except Exception as e:
586593
logging.warning('Error handling terminal control: %s', e)
594+
return 0
587595

588596
def SpawnTTYServer(self, unused_var):
589597
"""Spawn a TTY server and forward I/O to the TCP socket."""
@@ -627,32 +635,13 @@ def _ProcessBuffer(buf):
627635
if buf == b'\x04':
628636
raise RuntimeError('connection terminated')
629637

630-
write_buffer = b''
631-
i = 0
632-
while i < len(buf):
633-
# Check for ESC sequence
634-
if buf[i:i+2] == b'\x1b[':
635-
# Look for the 't' terminator
636-
sequence_found = False
637-
for j in range(i+2, len(buf)):
638-
if buf[j:j+1] == b't':
639-
# Found a complete escape sequence
640-
control_seq = buf[i:j+1].decode('utf-8', errors='ignore')
641-
self.HandleTTYControl(fd, control_seq)
642-
# Skip the processed sequence
643-
i = j + 1
644-
sequence_found = True
645-
break
646-
if not sequence_found:
647-
# No terminator found, treat as regular data
648-
write_buffer += buf[i:i+1]
649-
i += 1
650-
else:
651-
write_buffer += buf[i:i+1]
652-
i += 1
653-
654-
if write_buffer:
655-
os.write(fd, write_buffer)
638+
pos = buf.find(b'\x1b[')
639+
if pos != -1:
640+
os.write(fd, buf[:pos])
641+
consumed = self.HandleTTYControl(fd, buf[pos:])
642+
os.write(fd, buf[pos+consumed:])
643+
else:
644+
os.write(fd, buf)
656645

657646
# Initial buffer processing
658647
_ProcessBuffer(self._sock.RecvBuf())

0 commit comments

Comments
 (0)