-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat(term): termios package This will help us remove the dep on u-root/u-root from /ssh, and also adds support to netbsd. This one is less generic though, and specifically made to be used with ssh.TerminalModes, which is our main use case for now. Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * chore: fmt Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * fix: do not couple with ssh Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * chore: remove comments Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * fix: rename field * fix: darwin Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * ci: test build termios on many goos/goarch Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * test: open a pty and test it only on linux, on other OSs this will help by simply failing to compile Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * ci: go test instead of build Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * feat: support iox Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * fix: typo Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * ci: fixes Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * ci: fixes Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * ci: fixes Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * fix: bits Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * refactor: constants Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * wip: syscalls Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * fix: flush Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * fix: do not attempt to test/build on windows * ci: only test termios when it changes * fix: more tests, improvements * test: fix --------- Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
- Loading branch information
Showing
12 changed files
with
504 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
name: termios | ||
on: | ||
push: | ||
pull_request: | ||
paths: | ||
- "exp/term/termios/**" | ||
|
||
jobs: | ||
test: | ||
runs-on: ubuntu-latest | ||
defaults: | ||
run: | ||
working-directory: ./exp/term | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: actions/setup-go@v5 | ||
with: | ||
go-version-file: ./exp/term/go.mod | ||
cache: true | ||
cache-dependency-path: ./exp/term.sum | ||
# https://go.dev/doc/install/source#environment | ||
- run: GOOS=darwin GOARCH=amd64 go test -c -v ./termios/... | ||
- run: GOOS=darwin GOARCH=arm64 go test -c -v ./termios/... | ||
- run: GOOS=dragonfly GOARCH=amd64 go test -c -v ./termios/... | ||
- run: GOOS=freebsd GOARCH=386 go test -c -v ./termios/... | ||
- run: GOOS=freebsd GOARCH=amd64 go test -c -v ./termios/... | ||
- run: GOOS=freebsd GOARCH=arm go test -c -v ./termios/... | ||
- run: GOOS=linux GOARCH=386 go test -c -v ./termios/... | ||
- run: GOOS=linux GOARCH=amd64 go test -c -v ./termios/... | ||
- run: GOOS=linux GOARCH=arm go test -c -v ./termios/... | ||
- run: GOOS=linux GOARCH=arm64 go test -c -v ./termios/... | ||
- run: GOOS=linux GOARCH=mips go test -c -v ./termios/... | ||
- run: GOOS=linux GOARCH=mips64 go test -c -v ./termios/... | ||
- run: GOOS=linux GOARCH=mips64le go test -c -v ./termios/... | ||
- run: GOOS=linux GOARCH=mipsle go test -c -v ./termios/... | ||
- run: GOOS=linux GOARCH=ppc64 go test -c -v ./termios/... | ||
- run: GOOS=linux GOARCH=ppc64le go test -c -v ./termios/... | ||
- run: GOOS=linux GOARCH=riscv64 go test -c -v ./termios/... | ||
- run: GOOS=linux GOARCH=s390x go test -c -v ./termios/... | ||
- run: GOOS=netbsd GOARCH=386 go test -c -v ./termios/... | ||
- run: GOOS=netbsd GOARCH=amd64 go test -c -v ./termios/... | ||
- run: GOOS=netbsd GOARCH=arm go test -c -v ./termios/... | ||
- run: GOOS=openbsd GOARCH=386 go test -c -v ./termios/... | ||
- run: GOOS=openbsd GOARCH=amd64 go test -c -v ./termios/... | ||
- run: GOOS=openbsd GOARCH=arm go test -c -v ./termios/... | ||
- run: GOOS=openbsd GOARCH=arm64 go test -c -v ./termios/... | ||
|
||
# unsupported | ||
# - run: GOOS=aix GOARCH=ppc64 go test -c -v ./termios/... | ||
# - run: GOOS=android GOARCH=386 go test -c -v ./termios/... | ||
# - run: GOOS=android GOARCH=amd64 go test -c -v ./termios/... | ||
# - run: GOOS=android GOARCH=arm go test -c -v ./termios/... | ||
# - run: GOOS=android GOARCH=arm64 go test -c -v ./termios/... | ||
# - run: GOOS=illumos GOARCH=amd64 go test -c -v ./termios/... | ||
# - run: GOOS=ios GOARCH=arm64 go test -c -v ./termios/... | ||
# - run: GOOS=js GOARCH=wasm go test -c -v ./termios/... | ||
# - run: GOOS=linux GOARCH=loong64 go test -c -v ./termios/... | ||
# - run: GOOS=plan9 GOARCH=386 go test -c -v ./termios/... | ||
# - run: GOOS=plan9 GOARCH=amd64 go test -c -v ./termios/... | ||
# - run: GOOS=plan9 GOARCH=arm go test -c -v ./termios/... | ||
# - run: GOOS=solaris GOARCH=amd64 go test -c -v ./termios/... | ||
# - run: GOOS=wasip1 GOARCH=wasm go test -c -v ./termios/... | ||
# - run: GOOS=windows GOARCH=386 go test -c -v ./termios/... | ||
# - run: GOOS=windows GOARCH=amd64 go test -c -v ./termios/... | ||
# - run: GOOS=windows GOARCH=arm go test -c -v ./termios/... | ||
# - run: GOOS=windows GOARCH=arm64 go test -c -v ./termios/... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
//go:build netbsd || openbsd | ||
// +build netbsd openbsd | ||
|
||
package termios | ||
|
||
func speed(b uint32) int32 { return int32(b) } | ||
func bit(b uint32) uint32 { return b } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
//go:build darwin | ||
// +build darwin | ||
|
||
package termios | ||
|
||
func speed(b uint32) uint64 { return uint64(b) } | ||
func bit(b uint32) uint64 { return uint64(b) } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
//go:build !darwin && !netbsd && !openbsd | ||
// +build !darwin,!netbsd,!openbsd | ||
|
||
package termios | ||
|
||
func speed(b uint32) uint32 { return b } | ||
func bit(b uint32) uint32 { return b } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
//go:build darwin && netbsd && freebsd && netbsd | ||
// +build darwin,netbsd,freebsd,netbsd | ||
|
||
package term | ||
|
||
import "syscall" | ||
|
||
func init() { | ||
allCcOpts[STATUS] = syscall.VSTATUS | ||
allCcOpts[DSUSP] = syscall.VDSUSP | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
//go:build darwin | ||
// +build darwin | ||
|
||
package termios | ||
|
||
import "syscall" | ||
|
||
func init() { | ||
allLineOpts[IUTF8] = syscall.IUTF8 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
//go:build linux | ||
// +build linux | ||
|
||
package termios | ||
|
||
import "syscall" | ||
|
||
func init() { | ||
allCcOpts[SWTCH] = syscall.VSWTC | ||
allInputOpts[IUCLC] = syscall.IUCLC | ||
allLineOpts[IUTF8] = syscall.IUTF8 | ||
allLineOpts[XCASE] = syscall.XCASE | ||
allOutputOpts[OLCUC] = syscall.OLCUC | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,250 @@ | ||
//go:build darwin || netbsd || freebsd || openbsd || linux || dragonfly | ||
// +build darwin netbsd freebsd openbsd linux dragonfly | ||
|
||
package termios | ||
|
||
import ( | ||
"syscall" | ||
|
||
"golang.org/x/sys/unix" | ||
) | ||
|
||
// SetWinSize sets window size for an fd from a Winsize. | ||
func SetWinSize(fd int, w *unix.Winsize) error { | ||
return unix.IoctlSetWinsize(fd, ioctlSetWinSize, w) | ||
} | ||
|
||
// GetWinSize gets window size for an fd. | ||
func GetWinSize(fd int) (*unix.Winsize, error) { | ||
return unix.IoctlGetWinsize(fd, ioctlSetWinSize) | ||
} | ||
|
||
// GetTermios gets the termios of the given fd. | ||
func GetTermios(fd int) (*unix.Termios, error) { | ||
return unix.IoctlGetTermios(fd, ioctlGets) | ||
} | ||
|
||
// SetTermios sets the given termios over the given fd's current termios. | ||
func SetTermios( | ||
fd int, | ||
ispeed uint32, | ||
ospeed uint32, | ||
cc map[CC]uint8, | ||
iflag map[I]bool, | ||
oflag map[O]bool, | ||
cflag map[C]bool, | ||
lflag map[L]bool, | ||
) error { | ||
term, err := unix.IoctlGetTermios(fd, ioctlGets) | ||
if err != nil { | ||
return err | ||
} | ||
term.Ispeed = speed(ispeed) | ||
term.Ospeed = speed(ospeed) | ||
|
||
for key, value := range cc { | ||
call, ok := allCcOpts[key] | ||
if !ok { | ||
continue | ||
} | ||
term.Cc[call] = value | ||
} | ||
|
||
for key, value := range iflag { | ||
mask, ok := allInputOpts[key] | ||
if ok { | ||
if value { | ||
term.Iflag |= bit(mask) | ||
} else { | ||
term.Iflag &= ^bit(mask) | ||
} | ||
} | ||
} | ||
for key, value := range oflag { | ||
mask, ok := allOutputOpts[key] | ||
if ok { | ||
if value { | ||
term.Oflag |= bit(mask) | ||
} else { | ||
term.Oflag &= ^bit(mask) | ||
} | ||
} | ||
} | ||
for key, value := range cflag { | ||
mask, ok := allControlOpts[key] | ||
if ok { | ||
if value { | ||
term.Cflag |= bit(mask) | ||
} else { | ||
term.Cflag &= ^bit(mask) | ||
} | ||
} | ||
} | ||
for key, value := range lflag { | ||
mask, ok := allLineOpts[key] | ||
if ok { | ||
if value { | ||
term.Lflag |= bit(mask) | ||
} else { | ||
term.Lflag &= ^bit(mask) | ||
} | ||
} | ||
} | ||
return unix.IoctlSetTermios(fd, ioctlSets, term) | ||
} | ||
|
||
// CC is the termios cc field. | ||
// | ||
// It stores an array of special characters related to terminal I/O. | ||
type CC uint8 | ||
|
||
// CC possible values. | ||
const ( | ||
INTR CC = iota | ||
QUIT | ||
ERASE | ||
KILL | ||
EOF | ||
EOL | ||
EOL2 | ||
START | ||
STOP | ||
SUSP | ||
WERASE | ||
RPRNT | ||
LNEXT | ||
DISCARD | ||
STATUS | ||
SWTCH | ||
DSUSP | ||
FLUSH | ||
) | ||
|
||
// https://www.man7.org/linux/man-pages/man3/termios.3.html | ||
var allCcOpts = map[CC]int{ | ||
INTR: syscall.VINTR, | ||
QUIT: syscall.VQUIT, | ||
ERASE: syscall.VERASE, | ||
KILL: syscall.VQUIT, | ||
EOF: syscall.VEOF, | ||
EOL: syscall.VEOL, | ||
EOL2: syscall.VEOL2, | ||
START: syscall.VSTART, | ||
STOP: syscall.VSTOP, | ||
SUSP: syscall.VSUSP, | ||
WERASE: syscall.VWERASE, | ||
RPRNT: syscall.VREPRINT, | ||
LNEXT: syscall.VLNEXT, | ||
DISCARD: syscall.VDISCARD, | ||
|
||
// XXX: these syscalls don't exist for any OS | ||
// FLUSH: syscall.VFLUSH, | ||
} | ||
|
||
// Input Controls | ||
type I uint8 | ||
|
||
// Input possible values. | ||
const ( | ||
IGNPAR I = iota | ||
PARMRK | ||
INPCK | ||
ISTRIP | ||
INLCR | ||
IGNCR | ||
ICRNL | ||
IXON | ||
IXANY | ||
IXOFF | ||
IMAXBEL | ||
IUCLC | ||
) | ||
|
||
var allInputOpts = map[I]uint32{ | ||
IGNPAR: syscall.IGNPAR, | ||
PARMRK: syscall.PARMRK, | ||
INPCK: syscall.INPCK, | ||
ISTRIP: syscall.ISTRIP, | ||
INLCR: syscall.INLCR, | ||
IGNCR: syscall.IGNCR, | ||
ICRNL: syscall.ICRNL, | ||
IXON: syscall.IXON, | ||
IXANY: syscall.IXANY, | ||
IXOFF: syscall.IXOFF, | ||
IMAXBEL: syscall.IMAXBEL, | ||
} | ||
|
||
// Output Controls | ||
type O uint8 | ||
|
||
// Output possible values. | ||
const ( | ||
OPOST O = iota | ||
ONLCR | ||
OCRNL | ||
ONOCR | ||
ONLRET | ||
OLCUC | ||
) | ||
|
||
var allOutputOpts = map[O]uint32{ | ||
OPOST: syscall.OPOST, | ||
ONLCR: syscall.ONLCR, | ||
OCRNL: syscall.OCRNL, | ||
ONOCR: syscall.ONOCR, | ||
ONLRET: syscall.ONLRET, | ||
} | ||
|
||
// Control | ||
type C uint8 | ||
|
||
// Control possible values. | ||
const ( | ||
CS7 C = iota | ||
CS8 | ||
PARENB | ||
PARODD | ||
) | ||
|
||
var allControlOpts = map[C]uint32{ | ||
CS7: syscall.CS7, | ||
CS8: syscall.CS8, | ||
PARENB: syscall.PARENB, | ||
PARODD: syscall.PARODD, | ||
} | ||
|
||
// Line Controls. | ||
type L uint8 | ||
|
||
// Line possible values. | ||
const ( | ||
ISIG L = iota | ||
ICANON | ||
ECHO | ||
ECHOE | ||
ECHOK | ||
ECHONL | ||
NOFLSH | ||
TOSTOP | ||
IEXTEN | ||
ECHOCTL | ||
ECHOKE | ||
PENDIN | ||
IUTF8 | ||
XCASE | ||
) | ||
|
||
var allLineOpts = map[L]uint32{ | ||
ISIG: syscall.ISIG, | ||
ICANON: syscall.ICANON, | ||
ECHO: syscall.ECHO, | ||
ECHOE: syscall.ECHOE, | ||
ECHOK: syscall.ECHOK, | ||
ECHONL: syscall.ECHONL, | ||
NOFLSH: syscall.NOFLSH, | ||
TOSTOP: syscall.TOSTOP, | ||
IEXTEN: syscall.IEXTEN, | ||
ECHOCTL: syscall.ECHOCTL, | ||
ECHOKE: syscall.ECHOKE, | ||
PENDIN: syscall.PENDIN, | ||
} |
Oops, something went wrong.