fixes #277 Build fails on mips architectures

This commit is contained in:
Garrett D'Amore 2019-06-27 18:33:09 -07:00
parent 30e78c7859
commit 061f3f89b0
2 changed files with 115 additions and 42 deletions

View File

@ -20,20 +20,100 @@ import (
"os"
"os/signal"
"syscall"
"unsafe"
"golang.org/x/sys/unix"
)
type termiosPrivate syscall.Termios
type termiosPrivate struct {
tio *unix.Termios
}
// Linux is a little weird, in that it supports the ospeed and
// ispeed fields for most architectures, which can be set to nearly
// any valid value. However, for some (e.g. MIPS) it does not have
// those fields. In all cases it also uses the old BXXX values
// and attempts to find the closest match unless something different
// was specified by the application. Since we can't rely on
// ospeed or ispeed everywhere, we settle for the legacy method.
// (Alternatively we could have different versions of this for
// different CPU architectures, but that's no fun either.)
func getbaud(tios *unix.Termios) int {
bval := tios.Cflag & unix.CBAUD
// This gives us the appropriate BXXX value, so convert.
// Note that if we ever have SPARC on Linux, it will need
// a different set of values.
switch bval {
case unix.B0:
return 0
case unix.B50:
return 50
case unix.B75:
return 75
case unix.B110:
return 110
case unix.B134:
return 134
case unix.B150:
return 150
case unix.B200:
return 200
case unix.B300:
return 300
case unix.B600:
return 600
case unix.B1200:
return 1200
case unix.B1800:
return 1800
case unix.B2400:
return 2400
case unix.B4800:
return 4800
case unix.B9600:
return 9600
case unix.B19200:
return 19200
case unix.B38400:
return 38400
case unix.B57600:
return 57600
case unix.B115200:
return 115200
case unix.B230400:
return 230400
case unix.B460800:
return 460800
case unix.B500000:
return 500000
case unix.B576000:
return 576000
case unix.B921600:
return 921600
case unix.B1000000:
return 1000000
case unix.B1152000:
return 1152000
case unix.B1500000:
return 1500000
case unix.B2000000:
return 2000000
case unix.B2500000:
return 2500000
case unix.B3000000:
return 3000000
case unix.B3500000:
return 3500000
case unix.B4000000:
return 4000000
}
return 0
}
func (t *tScreen) termioInit() error {
var e error
var newtios termiosPrivate
var fd uintptr
var tios uintptr
var ioc uintptr
t.tiosp = &termiosPrivate{}
var raw *unix.Termios
var tio *unix.Termios
if t.in, e = os.OpenFile("/dev/tty", os.O_RDONLY, 0); e != nil {
goto failed
@ -42,41 +122,39 @@ func (t *tScreen) termioInit() error {
goto failed
}
tios = uintptr(unsafe.Pointer(t.tiosp))
ioc = uintptr(syscall.TCGETS)
fd = uintptr(t.out.Fd())
if _, _, e1 := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0); e1 != 0 {
e = e1
tio, e = unix.IoctlGetTermios(int(t.out.Fd()), unix.TCGETS)
if e != nil {
goto failed
}
// On this platform, the baud rate is stored
// directly as an integer in termios.c_ospeed.
t.baud = int(t.tiosp.Ospeed)
newtios = *t.tiosp
newtios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK |
syscall.ISTRIP | syscall.INLCR | syscall.IGNCR |
syscall.ICRNL | syscall.IXON
newtios.Oflag &^= syscall.OPOST
newtios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON |
syscall.ISIG | syscall.IEXTEN
newtios.Cflag &^= syscall.CSIZE | syscall.PARENB
newtios.Cflag |= syscall.CS8
t.tiosp = &termiosPrivate{tio: tio}
t.baud = getbaud(tio)
// make a local copy, to make it raw
raw = &unix.Termios{
Cflag: tio.Cflag,
Oflag: tio.Oflag,
Iflag: tio.Iflag,
Lflag: tio.Lflag,
Cc: tio.Cc,
}
raw.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP |
unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON)
raw.Oflag &^= unix.OPOST
raw.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG |
unix.IEXTEN)
raw.Cflag &^= (unix.CSIZE | unix.PARENB)
raw.Cflag |= unix.CS8
// This is setup for blocking reads. In the past we attempted to
// use non-blocking reads, but now a separate input loop and timer
// copes with the problems we had on some systems (BSD/Darwin)
// where close hung forever.
newtios.Cc[syscall.VMIN] = 1
newtios.Cc[syscall.VTIME] = 0
raw.Cc[syscall.VMIN] = 1
raw.Cc[syscall.VTIME] = 0
tios = uintptr(unsafe.Pointer(&newtios))
// Well this kind of sucks, because we don't have TCSETSF, but only
// TCSETS. This can leave some output unflushed.
ioc = uintptr(syscall.TCSETS)
if _, _, e1 := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0); e1 != 0 {
e = e1
e = unix.IoctlSetTermios(int(t.out.Fd()), unix.TCSETS, raw)
if e != nil {
goto failed
}
@ -104,14 +182,11 @@ func (t *tScreen) termioFini() {
<-t.indoneq
if t.out != nil {
fd := uintptr(t.out.Fd())
// XXX: We'd really rather do TCSETSF here!
ioc := uintptr(syscall.TCSETS)
tios := uintptr(unsafe.Pointer(t.tiosp))
syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0)
if t.out != nil && t.tiosp != nil {
unix.IoctlSetTermios(int(t.out.Fd()), unix.TCSETSF, t.tiosp.tio)
t.out.Close()
}
if t.in != nil {
t.in.Close()
}

View File

@ -110,14 +110,12 @@ func (t *tScreen) termioInit() error {
goto failed
}
t.tiosp = &termiosPrivate{}
tio, e = unix.IoctlGetTermios(int(t.out.Fd()), unix.TCGETS)
if e != nil {
goto failed
}
t.tiosp.tio = tio
t.tiosp = &termiosPrivate{tio: tio}
t.baud = getbaud(tio)
// make a local copy, to make it raw