Skip to content

Instantly share code, notes, and snippets.

@kvaps
Forked from EddieIvan01/raw_mode_posix.go
Created August 22, 2021 22:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kvaps/37de1fc4546d874a50dbf62dd9417046 to your computer and use it in GitHub Desktop.
Save kvaps/37de1fc4546d874a50dbf62dd9417046 to your computer and use it in GitHub Desktop.
syscall to set raw-mode-input terminal in Go (Posix/Windows)
// +build darwin linux
package main
import (
"os"
"syscall"
"unsafe"
)
func getTermios(fd uintptr) *syscall.Termios {
var t syscall.Termios
_, _, err := syscall.Syscall6(
syscall.SYS_IOCTL,
os.Stdin.Fd(),
syscall.TCGETS,
uintptr(unsafe.Pointer(&t)),
0, 0, 0)
if err != 0 {
panic("err")
}
return &t
}
func setTermios(fd uintptr, term *syscall.Termios) {
_, _, err := syscall.Syscall6(
syscall.SYS_IOCTL,
os.Stdin.Fd(),
syscall.TCSETS,
uintptr(unsafe.Pointer(term)),
0,0,0)
if err != 0 {
panic("err")
}
}
func setRaw(term *syscall.Termios) {
// This attempts to replicate the behaviour documented for cfmakeraw in
// the termios(3) manpage.
term.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON
// newState.Oflag &^= syscall.OPOST
term.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN
term.Cflag &^= syscall.CSIZE | syscall.PARENB
term.Cflag |= syscall.CS8
term.Cc[syscall.VMIN] = 1
term.Cc[syscall.VTIME] = 0
}
func main() {
t := getTermios(os.Stdin.Fd())
origin := *t
defer func() {
setTermios(os.Stdin.Fd(), &origin)
}()
setRaw(t)
setTermios(os.Stdin.Fd(), t)
for i := 0; i < 3; i++{
buf := make([]byte, 1)
syscall.Read(0, buf)
println(buf[0])
}
}
package main
import (
"os"
"syscall"
"unsafe"
)
var kernel32 = syscall.NewLazyDLL("kernel32.dll")
var (
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
procSetConsoleMode = kernel32.NewProc("SetConsoleMode")
)
const (
enableLineInput = 2
enableEchoInput = 4
enableProcessedInput = 1
enableWindowInput = 8
enableMouseInput = 16
enableInsertMode = 32
enableQuickEditMode = 64
enableExtendedFlags = 128
enableAutoPosition = 256
enableProcessedOutput = 1
enableWrapAtEolOutput = 2
)
func getTermMode(fd uintptr) uint32 {
var mode uint32
_, _, err := syscall.Syscall(
procGetConsoleMode.Addr(),
2,
fd,
uintptr(unsafe.Pointer(&mode)),
0)
if err != 0 {
panic("err")
}
return mode
}
func setTermMode(fd uintptr, mode uint32) {
_, _, err := syscall.Syscall(
procSetConsoleMode.Addr(),
2,
fd,
uintptr(mode),
0)
if err != 0 {
panic("err")
}
}
func main() {
originMode := getTermMode(os.Stdin.Fd())
defer func(m uint32) {
setTermMode(os.Stdin.Fd(), m)
}(originMode)
originMode &^= (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput)
setTermMode(os.Stdin.Fd(), originMode)
for i := 0; i < 3; i++{
buf := make([]byte, 1)
syscall.Read(syscall.Handle(os.Stdin.Fd()), buf)
println(buf[0])
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment