Signed-off-by: Amit Krishnan <krish.amit@gmail.com>
| ... | ... |
@@ -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 |
|
| 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 |
+} |