Browse code

Get pkg/term to build for Solaris

Signed-off-by: Amit Krishnan <krish.amit@gmail.com>

Amit Krishnan authored on 2016/04/16 03:28:44
Showing 6 changed files
... ...
@@ -11,7 +11,7 @@ import (
11 11
 import "C"
12 12
 
13 13
 // Termios is the Unix API for terminal I/O.
14
-// It is passthgrouh for syscall.Termios in order to make it portable with
14
+// It is passthrough for syscall.Termios in order to make it portable with
15 15
 // other platforms where it is not available or handled differently.
16 16
 type Termios syscall.Termios
17 17
 
... ...
@@ -1,5 +1,6 @@
1 1
 // +build !windows
2 2
 // +build !linux !cgo
3
+// +build !solaris !cgo
3 4
 
4 5
 package term
5 6
 
6 7
new file mode 100644
... ...
@@ -0,0 +1,63 @@
0
+// +build solaris,cgo
1
+
2
+package term
3
+
4
+import (
5
+	"syscall"
6
+	"unsafe"
7
+)
8
+
9
+// #include <termios.h>
10
+import "C"
11
+
12
+// Termios is the Unix API for terminal I/O.
13
+// It is passthrough for syscall.Termios in order to make it portable with
14
+// other platforms where it is not available or handled differently.
15
+type Termios syscall.Termios
16
+
17
+// MakeRaw put the terminal connected to the given file descriptor into raw
18
+// mode and returns the previous state of the terminal so that it can be
19
+// restored.
20
+func MakeRaw(fd uintptr) (*State, error) {
21
+	var oldState State
22
+	if err := tcget(fd, &oldState.termios); err != 0 {
23
+		return nil, err
24
+	}
25
+
26
+	newState := oldState.termios
27
+
28
+	newState.Iflag &^= (syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON | syscall.IXANY)
29
+	newState.Oflag &^= syscall.OPOST
30
+	newState.Lflag &^= (syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN)
31
+	newState.Cflag &^= (syscall.CSIZE | syscall.PARENB)
32
+	newState.Cflag |= syscall.CS8
33
+
34
+	/*
35
+		VMIN is the minimum number of characters that needs to be read in non-canonical mode for it to be returned
36
+		Since VMIN is overloaded with another element in canonical mode when we switch modes it defaults to 4. It
37
+		needs to be explicitly set to 1.
38
+	*/
39
+	newState.Cc[C.VMIN] = 1
40
+	newState.Cc[C.VTIME] = 0
41
+
42
+	if err := tcset(fd, &newState); err != 0 {
43
+		return nil, err
44
+	}
45
+	return &oldState, nil
46
+}
47
+
48
+func tcget(fd uintptr, p *Termios) syscall.Errno {
49
+	ret, err := C.tcgetattr(C.int(fd), (*C.struct_termios)(unsafe.Pointer(p)))
50
+	if ret != 0 {
51
+		return err.(syscall.Errno)
52
+	}
53
+	return 0
54
+}
55
+
56
+func tcset(fd uintptr, p *Termios) syscall.Errno {
57
+	ret, err := C.tcsetattr(C.int(fd), C.TCSANOW, (*C.struct_termios)(unsafe.Pointer(p)))
58
+	if ret != 0 {
59
+		return err.(syscall.Errno)
60
+	}
61
+	return 0
62
+}
... ...
@@ -10,7 +10,6 @@ import (
10 10
 	"os"
11 11
 	"os/signal"
12 12
 	"syscall"
13
-	"unsafe"
14 13
 )
15 14
 
16 15
 var (
... ...
@@ -47,27 +46,6 @@ func GetFdInfo(in interface{}) (uintptr, bool) {
47 47
 	return inFd, isTerminalIn
48 48
 }
49 49
 
50
-// GetWinsize returns the window size based on the specified file descriptor.
51
-func GetWinsize(fd uintptr) (*Winsize, error) {
52
-	ws := &Winsize{}
53
-	_, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(ws)))
54
-	// Skip errno = 0
55
-	if err == 0 {
56
-		return ws, nil
57
-	}
58
-	return ws, err
59
-}
60
-
61
-// SetWinsize tries to set the specified window size for the specified file descriptor.
62
-func SetWinsize(fd uintptr, ws *Winsize) error {
63
-	_, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws)))
64
-	// Skip errno = 0
65
-	if err == 0 {
66
-		return nil
67
-	}
68
-	return err
69
-}
70
-
71 50
 // IsTerminal returns true if the given file descriptor is a terminal.
72 51
 func IsTerminal(fd uintptr) bool {
73 52
 	var termios Termios
74 53
new file mode 100644
... ...
@@ -0,0 +1,41 @@
0
+// +build solaris
1
+
2
+package term
3
+
4
+import (
5
+	"syscall"
6
+	"unsafe"
7
+)
8
+
9
+/*
10
+#include <unistd.h>
11
+#include <stropts.h>
12
+#include <termios.h>
13
+
14
+// Small wrapper to get rid of variadic args of ioctl()
15
+int my_ioctl(int fd, int cmd, struct winsize *ws) {
16
+	return ioctl(fd, cmd, ws);
17
+}
18
+*/
19
+import "C"
20
+
21
+// GetWinsize returns the window size based on the specified file descriptor.
22
+func GetWinsize(fd uintptr) (*Winsize, error) {
23
+	ws := &Winsize{}
24
+	ret, err := C.my_ioctl(C.int(fd), C.int(syscall.TIOCGWINSZ), (*C.struct_winsize)(unsafe.Pointer(ws)))
25
+	// Skip retval = 0
26
+	if ret == 0 {
27
+		return ws, nil
28
+	}
29
+	return ws, err
30
+}
31
+
32
+// SetWinsize tries to set the specified window size for the specified file descriptor.
33
+func SetWinsize(fd uintptr, ws *Winsize) error {
34
+	ret, err := C.my_ioctl(C.int(fd), C.int(syscall.TIOCSWINSZ), (*C.struct_winsize)(unsafe.Pointer(ws)))
35
+	// Skip retval = 0
36
+	if ret == 0 {
37
+		return nil
38
+	}
39
+	return err
40
+}
0 41
new file mode 100644
... ...
@@ -0,0 +1,29 @@
0
+// +build !solaris,!windows
1
+
2
+package term
3
+
4
+import (
5
+	"syscall"
6
+	"unsafe"
7
+)
8
+
9
+// GetWinsize returns the window size based on the specified file descriptor.
10
+func GetWinsize(fd uintptr) (*Winsize, error) {
11
+	ws := &Winsize{}
12
+	_, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(ws)))
13
+	// Skipp errno = 0
14
+	if err == 0 {
15
+		return ws, nil
16
+	}
17
+	return ws, err
18
+}
19
+
20
+// SetWinsize tries to set the specified window size for the specified file descriptor.
21
+func SetWinsize(fd uintptr, ws *Winsize) error {
22
+	_, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws)))
23
+	// Skipp errno = 0
24
+	if err == 0 {
25
+		return nil
26
+	}
27
+	return err
28
+}