// Copyright (c) 2026 Charles KWON OhJun (charleskwonohjun@gmail.com) // All rights reserved. //go:build linux // Termios ioctl helpers for the debugger — Linux uses TCGETS/TCSETS. // Kept in a tiny shim so debugcli/debugtui stay platform-neutral. package hbrt import ( "os" "syscall" "unsafe" ) const ( ioctlGetTermios = syscall.TCGETS ioctlSetTermios = syscall.TCSETS ) var ( savedTermios syscall.Termios termSaved bool ) func restoreCooked() { fd := int(os.Stdin.Fd()) var t syscall.Termios syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlGetTermios, uintptr(unsafe.Pointer(&t)), 0, 0, 0) if !termSaved { savedTermios = t termSaved = true } t.Lflag |= syscall.ICANON | syscall.ECHO t.Oflag |= syscall.OPOST syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlSetTermios, uintptr(unsafe.Pointer(&t)), 0, 0, 0) } func reenterRaw() { fd := int(os.Stdin.Fd()) var t syscall.Termios syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlGetTermios, uintptr(unsafe.Pointer(&t)), 0, 0, 0) t.Lflag &^= syscall.ICANON | syscall.ECHO | syscall.ISIG t.Oflag &^= syscall.OPOST t.Cc[syscall.VMIN] = 1 t.Cc[syscall.VTIME] = 0 syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlSetTermios, uintptr(unsafe.Pointer(&t)), 0, 0, 0) } func termSize() (int, int) { type winsize struct { Row, Col, Xpixel, Ypixel uint16 } var ws winsize _, _, _ = syscall.Syscall(syscall.SYS_IOCTL, uintptr(1), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&ws))) return int(ws.Row), int(ws.Col) } // readDebugKey puts stdin into raw mode just long enough to consume // one keystroke / ANSI escape sequence, then restores the previous // termios. The cross-platform decoder in debugkey.go turns the bytes // into a logical key code. func readDebugKey() int { fd := int(os.Stdin.Fd()) var t syscall.Termios syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlGetTermios, uintptr(unsafe.Pointer(&t)), 0, 0, 0) raw := t raw.Lflag &^= syscall.ICANON | syscall.ECHO raw.Cc[syscall.VMIN] = 1 raw.Cc[syscall.VTIME] = 0 syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlSetTermios, uintptr(unsafe.Pointer(&raw)), 0, 0, 0) defer syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlSetTermios, uintptr(unsafe.Pointer(&t)), 0, 0, 0) buf := make([]byte, 8) n, _ := syscall.Read(fd, buf) return decodeDebugKey(buf, n) }