File: term_unix.go

package info (click to toggle)
golang-github-moby-term 0.0~git20230502.9c3c875-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 180 kB
  • sloc: makefile: 2
file content (98 lines) | stat: -rw-r--r-- 2,103 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//go:build !windows
// +build !windows

package term

import (
	"errors"
	"io"
	"os"

	"golang.org/x/sys/unix"
)

// ErrInvalidState is returned if the state of the terminal is invalid.
//
// Deprecated: ErrInvalidState is no longer used.
var ErrInvalidState = errors.New("Invalid terminal state")

// terminalState holds the platform-specific state / console mode for the terminal.
type terminalState struct {
	termios unix.Termios
}

func stdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
	return os.Stdin, os.Stdout, os.Stderr
}

func getFdInfo(in interface{}) (uintptr, bool) {
	var inFd uintptr
	var isTerminalIn bool
	if file, ok := in.(*os.File); ok {
		inFd = file.Fd()
		isTerminalIn = isTerminal(inFd)
	}
	return inFd, isTerminalIn
}

func getWinsize(fd uintptr) (*Winsize, error) {
	uws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ)
	ws := &Winsize{Height: uws.Row, Width: uws.Col, x: uws.Xpixel, y: uws.Ypixel}
	return ws, err
}

func setWinsize(fd uintptr, ws *Winsize) error {
	return unix.IoctlSetWinsize(int(fd), unix.TIOCSWINSZ, &unix.Winsize{
		Row:    ws.Height,
		Col:    ws.Width,
		Xpixel: ws.x,
		Ypixel: ws.y,
	})
}

func isTerminal(fd uintptr) bool {
	_, err := tcget(fd)
	return err == nil
}

func restoreTerminal(fd uintptr, state *State) error {
	if state == nil {
		return errors.New("invalid terminal state")
	}
	return tcset(fd, &state.termios)
}

func saveState(fd uintptr) (*State, error) {
	termios, err := tcget(fd)
	if err != nil {
		return nil, err
	}
	return &State{termios: *termios}, nil
}

func disableEcho(fd uintptr, state *State) error {
	newState := state.termios
	newState.Lflag &^= unix.ECHO

	return tcset(fd, &newState)
}

func setRawTerminal(fd uintptr) (*State, error) {
	return makeRaw(fd)
}

func setRawTerminalOutput(fd uintptr) (*State, error) {
	return nil, nil
}

func tcget(fd uintptr) (*unix.Termios, error) {
	p, err := unix.IoctlGetTermios(int(fd), getTermios)
	if err != nil {
		return nil, err
	}
	return p, nil
}

func tcset(fd uintptr, p *unix.Termios) error {
	return unix.IoctlSetTermios(int(fd), setTermios, p)
}