| ... | ... |
@@ -30,7 +30,7 @@ require ( |
| 30 | 30 |
github.com/containerd/fifo v1.1.0 |
| 31 | 31 |
github.com/containerd/typeurl/v2 v2.1.0 |
| 32 | 32 |
github.com/coreos/go-systemd/v22 v22.5.0 |
| 33 |
- github.com/creack/pty v1.1.11 |
|
| 33 |
+ github.com/creack/pty v1.1.18 |
|
| 34 | 34 |
github.com/deckarep/golang-set/v2 v2.3.0 |
| 35 | 35 |
github.com/docker/distribution v2.8.1+incompatible |
| 36 | 36 |
github.com/docker/go-connections v0.4.0 |
| ... | ... |
@@ -470,8 +470,9 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr |
| 470 | 470 |
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= |
| 471 | 471 |
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= |
| 472 | 472 |
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= |
| 473 |
-github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= |
|
| 474 | 473 |
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= |
| 474 |
+github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= |
|
| 475 |
+github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= |
|
| 475 | 476 |
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= |
| 476 | 477 |
github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= |
| 477 | 478 |
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= |
| 478 | 479 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,17 @@ |
| 0 |
+ARG GOVERSION=1.14 |
|
| 1 |
+FROM golang:${GOVERSION}
|
|
| 2 |
+ |
|
| 3 |
+# Set base env. |
|
| 4 |
+ARG GOOS=linux |
|
| 5 |
+ARG GOARCH=amd64 |
|
| 6 |
+ENV GOOS=${GOOS} GOARCH=${GOARCH} CGO_ENABLED=0 GOFLAGS='-v -ldflags=-s -ldflags=-w'
|
|
| 7 |
+ |
|
| 8 |
+# Pre compile the stdlib for 386/arm (32bits). |
|
| 9 |
+RUN go build -a std |
|
| 10 |
+ |
|
| 11 |
+# Add the code to the image. |
|
| 12 |
+WORKDIR pty |
|
| 13 |
+ADD . . |
|
| 14 |
+ |
|
| 15 |
+# Build the lib. |
|
| 16 |
+RUN go build |
| ... | ... |
@@ -1,3 +1,4 @@ |
| 1 |
+# NOTE: Using 1.13 as a base to build the RISCV compiler, the resulting version is based on go1.6. |
|
| 1 | 2 |
FROM golang:1.13 |
| 2 | 3 |
|
| 3 | 4 |
# Clone and complie a riscv compatible version of the go compiler. |
| ... | ... |
@@ -8,7 +9,15 @@ ENV PATH=/riscv-go/misc/riscv:/riscv-go/bin:$PATH |
| 8 | 8 |
RUN cd /riscv-go/src && GOROOT_BOOTSTRAP=$(go env GOROOT) ./make.bash |
| 9 | 9 |
ENV GOROOT=/riscv-go |
| 10 | 10 |
|
| 11 |
-# Make sure we compile. |
|
| 11 |
+# Set the base env. |
|
| 12 |
+ENV GOOS=linux GOARCH=riscv CGO_ENABLED=0 GOFLAGS='-v -ldflags=-s -ldflags=-w' |
|
| 13 |
+ |
|
| 14 |
+# Pre compile the stdlib. |
|
| 15 |
+RUN go build -a std |
|
| 16 |
+ |
|
| 17 |
+# Add the code to the image. |
|
| 12 | 18 |
WORKDIR pty |
| 13 | 19 |
ADD . . |
| 14 |
-RUN GOOS=linux GOARCH=riscv go build |
|
| 20 |
+ |
|
| 21 |
+# Build the lib. |
|
| 22 |
+RUN go build |
| ... | ... |
@@ -4,9 +4,13 @@ Pty is a Go package for using unix pseudo-terminals. |
| 4 | 4 |
|
| 5 | 5 |
## Install |
| 6 | 6 |
|
| 7 |
- go get github.com/creack/pty |
|
| 7 |
+```sh |
|
| 8 |
+go get github.com/creack/pty |
|
| 9 |
+``` |
|
| 10 |
+ |
|
| 11 |
+## Examples |
|
| 8 | 12 |
|
| 9 |
-## Example |
|
| 13 |
+Note that those examples are for demonstration purpose only, to showcase how to use the library. They are not meant to be used in any kind of production environment. |
|
| 10 | 14 |
|
| 11 | 15 |
### Command |
| 12 | 16 |
|
| ... | ... |
@@ -14,10 +18,11 @@ Pty is a Go package for using unix pseudo-terminals. |
| 14 | 14 |
package main |
| 15 | 15 |
|
| 16 | 16 |
import ( |
| 17 |
- "github.com/creack/pty" |
|
| 18 | 17 |
"io" |
| 19 | 18 |
"os" |
| 20 | 19 |
"os/exec" |
| 20 |
+ |
|
| 21 |
+ "github.com/creack/pty" |
|
| 21 | 22 |
) |
| 22 | 23 |
|
| 23 | 24 |
func main() {
|
| ... | ... |
@@ -51,7 +56,7 @@ import ( |
| 51 | 51 |
"syscall" |
| 52 | 52 |
|
| 53 | 53 |
"github.com/creack/pty" |
| 54 |
- "golang.org/x/crypto/ssh/terminal" |
|
| 54 |
+ "golang.org/x/term" |
|
| 55 | 55 |
) |
| 56 | 56 |
|
| 57 | 57 |
func test() error {
|
| ... | ... |
@@ -77,15 +82,17 @@ func test() error {
|
| 77 | 77 |
} |
| 78 | 78 |
}() |
| 79 | 79 |
ch <- syscall.SIGWINCH // Initial resize. |
| 80 |
+ defer func() { signal.Stop(ch); close(ch) }() // Cleanup signals when done.
|
|
| 80 | 81 |
|
| 81 | 82 |
// Set stdin in raw mode. |
| 82 |
- oldState, err := terminal.MakeRaw(int(os.Stdin.Fd())) |
|
| 83 |
+ oldState, err := term.MakeRaw(int(os.Stdin.Fd())) |
|
| 83 | 84 |
if err != nil {
|
| 84 | 85 |
panic(err) |
| 85 | 86 |
} |
| 86 |
- defer func() { _ = terminal.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort.
|
|
| 87 |
+ defer func() { _ = term.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort.
|
|
| 87 | 88 |
|
| 88 | 89 |
// Copy stdin to the pty and the pty to stdout. |
| 90 |
+ // NOTE: The goroutine will keep reading until the next keystroke before returning. |
|
| 89 | 91 |
go func() { _, _ = io.Copy(ptmx, os.Stdin) }()
|
| 90 | 92 |
_, _ = io.Copy(os.Stdout, ptmx) |
| 91 | 93 |
|
| 92 | 94 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,18 @@ |
| 0 |
+// Copyright 2014 The Go Authors. All rights reserved. |
|
| 1 |
+// Use of this source code is governed by a BSD-style |
|
| 2 |
+// license that can be found in the LICENSE file. |
|
| 3 |
+ |
|
| 4 |
+//go:build gc |
|
| 5 |
+//+build gc |
|
| 6 |
+ |
|
| 7 |
+#include "textflag.h" |
|
| 8 |
+ |
|
| 9 |
+// |
|
| 10 |
+// System calls for amd64, Solaris are implemented in runtime/syscall_solaris.go |
|
| 11 |
+// |
|
| 12 |
+ |
|
| 13 |
+TEXT ·sysvicall6(SB),NOSPLIT,$0-88 |
|
| 14 |
+ JMP syscall·sysvicall6(SB) |
|
| 15 |
+ |
|
| 16 |
+TEXT ·rawSysvicall6(SB),NOSPLIT,$0-88 |
|
| 17 |
+ JMP syscall·rawSysvicall6(SB) |
| ... | ... |
@@ -10,7 +10,7 @@ import ( |
| 10 | 10 |
// available on the current platform. |
| 11 | 11 |
var ErrUnsupported = errors.New("unsupported")
|
| 12 | 12 |
|
| 13 |
-// Opens a pty and its corresponding tty. |
|
| 13 |
+// Open a pty and its corresponding tty. |
|
| 14 | 14 |
func Open() (pty, tty *os.File, err error) {
|
| 15 | 15 |
return open() |
| 16 | 16 |
} |
| ... | ... |
@@ -1,9 +1,15 @@ |
| 1 |
-// +build !windows,!solaris |
|
| 1 |
+//go:build !windows && !solaris && !aix |
|
| 2 |
+// +build !windows,!solaris,!aix |
|
| 2 | 3 |
|
| 3 | 4 |
package pty |
| 4 | 5 |
|
| 5 | 6 |
import "syscall" |
| 6 | 7 |
|
| 8 |
+const ( |
|
| 9 |
+ TIOCGWINSZ = syscall.TIOCGWINSZ |
|
| 10 |
+ TIOCSWINSZ = syscall.TIOCSWINSZ |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 7 | 13 |
func ioctl(fd, cmd, ptr uintptr) error {
|
| 8 | 14 |
_, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, cmd, ptr) |
| 9 | 15 |
if e != 0 {
|
| ... | ... |
@@ -1,30 +1,48 @@ |
| 1 |
+//go:build solaris |
|
| 2 |
+// +build solaris |
|
| 3 |
+ |
|
| 1 | 4 |
package pty |
| 2 | 5 |
|
| 3 | 6 |
import ( |
| 4 |
- "golang.org/x/sys/unix" |
|
| 7 |
+ "syscall" |
|
| 5 | 8 |
"unsafe" |
| 6 | 9 |
) |
| 7 | 10 |
|
| 11 |
+//go:cgo_import_dynamic libc_ioctl ioctl "libc.so" |
|
| 12 |
+//go:linkname procioctl libc_ioctl |
|
| 13 |
+var procioctl uintptr |
|
| 14 |
+ |
|
| 8 | 15 |
const ( |
| 9 | 16 |
// see /usr/include/sys/stropts.h |
| 10 |
- I_PUSH = uintptr((int32('S')<<8 | 002))
|
|
| 11 |
- I_STR = uintptr((int32('S')<<8 | 010))
|
|
| 12 |
- I_FIND = uintptr((int32('S')<<8 | 013))
|
|
| 17 |
+ I_PUSH = uintptr((int32('S')<<8 | 002))
|
|
| 18 |
+ I_STR = uintptr((int32('S')<<8 | 010))
|
|
| 19 |
+ I_FIND = uintptr((int32('S')<<8 | 013))
|
|
| 20 |
+ |
|
| 13 | 21 |
// see /usr/include/sys/ptms.h |
| 14 | 22 |
ISPTM = (int32('P') << 8) | 1
|
| 15 | 23 |
UNLKPT = (int32('P') << 8) | 2
|
| 16 | 24 |
PTSSTTY = (int32('P') << 8) | 3
|
| 17 | 25 |
ZONEPT = (int32('P') << 8) | 4
|
| 18 | 26 |
OWNERPT = (int32('P') << 8) | 5
|
| 27 |
+ |
|
| 28 |
+ // see /usr/include/sys/termios.h |
|
| 29 |
+ TIOCSWINSZ = (uint32('T') << 8) | 103
|
|
| 30 |
+ TIOCGWINSZ = (uint32('T') << 8) | 104
|
|
| 19 | 31 |
) |
| 20 | 32 |
|
| 21 | 33 |
type strioctl struct {
|
| 22 |
- ic_cmd int32 |
|
| 23 |
- ic_timout int32 |
|
| 24 |
- ic_len int32 |
|
| 25 |
- ic_dp unsafe.Pointer |
|
| 34 |
+ icCmd int32 |
|
| 35 |
+ icTimeout int32 |
|
| 36 |
+ icLen int32 |
|
| 37 |
+ icDP unsafe.Pointer |
|
| 26 | 38 |
} |
| 27 | 39 |
|
| 40 |
+// Defined in asm_solaris_amd64.s. |
|
| 41 |
+func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) |
|
| 42 |
+ |
|
| 28 | 43 |
func ioctl(fd, cmd, ptr uintptr) error {
|
| 29 |
- return unix.IoctlSetInt(int(fd), uint(cmd), int(ptr)) |
|
| 44 |
+ if _, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procioctl)), 3, fd, cmd, ptr, 0, 0, 0); errno != 0 {
|
|
| 45 |
+ return errno |
|
| 46 |
+ } |
|
| 47 |
+ return nil |
|
| 30 | 48 |
} |
| ... | ... |
@@ -1,3 +1,6 @@ |
| 1 |
+//go:build darwin |
|
| 2 |
+// +build darwin |
|
| 3 |
+ |
|
| 1 | 4 |
package pty |
| 2 | 5 |
|
| 3 | 6 |
import ( |
| ... | ... |
@@ -33,7 +36,7 @@ func open() (pty, tty *os.File, err error) {
|
| 33 | 33 |
return nil, nil, err |
| 34 | 34 |
} |
| 35 | 35 |
|
| 36 |
- t, err := os.OpenFile(sname, os.O_RDWR, 0) |
|
| 36 |
+ t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) |
|
| 37 | 37 |
if err != nil {
|
| 38 | 38 |
return nil, nil, err |
| 39 | 39 |
} |
| ... | ... |
@@ -1,3 +1,6 @@ |
| 1 |
+//go:build linux |
|
| 2 |
+// +build linux |
|
| 3 |
+ |
|
| 1 | 4 |
package pty |
| 2 | 5 |
|
| 3 | 6 |
import ( |
| ... | ... |
@@ -28,7 +31,7 @@ func open() (pty, tty *os.File, err error) {
|
| 28 | 28 |
return nil, nil, err |
| 29 | 29 |
} |
| 30 | 30 |
|
| 31 |
- t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) |
|
| 31 |
+ t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) //nolint:gosec // Expected Open from a variable. |
|
| 32 | 32 |
if err != nil {
|
| 33 | 33 |
return nil, nil, err |
| 34 | 34 |
} |
| ... | ... |
@@ -37,7 +40,7 @@ func open() (pty, tty *os.File, err error) {
|
| 37 | 37 |
|
| 38 | 38 |
func ptsname(f *os.File) (string, error) {
|
| 39 | 39 |
var n _C_uint |
| 40 |
- err := ioctl(f.Fd(), syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))) |
|
| 40 |
+ err := ioctl(f.Fd(), syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))) //nolint:gosec // Expected unsafe pointer for Syscall call. |
|
| 41 | 41 |
if err != nil {
|
| 42 | 42 |
return "", err |
| 43 | 43 |
} |
| ... | ... |
@@ -47,5 +50,5 @@ func ptsname(f *os.File) (string, error) {
|
| 47 | 47 |
func unlockpt(f *os.File) error {
|
| 48 | 48 |
var u _C_int |
| 49 | 49 |
// use TIOCSPTLCK with a pointer to zero to clear the lock |
| 50 |
- return ioctl(f.Fd(), syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))) |
|
| 50 |
+ return ioctl(f.Fd(), syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))) //nolint:gosec // Expected unsafe pointer for Syscall call. |
|
| 51 | 51 |
} |
| 52 | 52 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,69 @@ |
| 0 |
+//go:build netbsd |
|
| 1 |
+// +build netbsd |
|
| 2 |
+ |
|
| 3 |
+package pty |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "errors" |
|
| 7 |
+ "os" |
|
| 8 |
+ "syscall" |
|
| 9 |
+ "unsafe" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+func open() (pty, tty *os.File, err error) {
|
|
| 13 |
+ p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0)
|
|
| 14 |
+ if err != nil {
|
|
| 15 |
+ return nil, nil, err |
|
| 16 |
+ } |
|
| 17 |
+ // In case of error after this point, make sure we close the ptmx fd. |
|
| 18 |
+ defer func() {
|
|
| 19 |
+ if err != nil {
|
|
| 20 |
+ _ = p.Close() // Best effort. |
|
| 21 |
+ } |
|
| 22 |
+ }() |
|
| 23 |
+ |
|
| 24 |
+ sname, err := ptsname(p) |
|
| 25 |
+ if err != nil {
|
|
| 26 |
+ return nil, nil, err |
|
| 27 |
+ } |
|
| 28 |
+ |
|
| 29 |
+ if err := grantpt(p); err != nil {
|
|
| 30 |
+ return nil, nil, err |
|
| 31 |
+ } |
|
| 32 |
+ |
|
| 33 |
+ // In NetBSD unlockpt() does nothing, so it isn't called here. |
|
| 34 |
+ |
|
| 35 |
+ t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) |
|
| 36 |
+ if err != nil {
|
|
| 37 |
+ return nil, nil, err |
|
| 38 |
+ } |
|
| 39 |
+ return p, t, nil |
|
| 40 |
+} |
|
| 41 |
+ |
|
| 42 |
+func ptsname(f *os.File) (string, error) {
|
|
| 43 |
+ /* |
|
| 44 |
+ * from ptsname(3): The ptsname() function is equivalent to: |
|
| 45 |
+ * struct ptmget pm; |
|
| 46 |
+ * ioctl(fd, TIOCPTSNAME, &pm) == -1 ? NULL : pm.sn; |
|
| 47 |
+ */ |
|
| 48 |
+ var ptm ptmget |
|
| 49 |
+ if err := ioctl(f.Fd(), uintptr(ioctl_TIOCPTSNAME), uintptr(unsafe.Pointer(&ptm))); err != nil {
|
|
| 50 |
+ return "", err |
|
| 51 |
+ } |
|
| 52 |
+ name := make([]byte, len(ptm.Sn)) |
|
| 53 |
+ for i, c := range ptm.Sn {
|
|
| 54 |
+ name[i] = byte(c) |
|
| 55 |
+ if c == 0 {
|
|
| 56 |
+ return string(name[:i]), nil |
|
| 57 |
+ } |
|
| 58 |
+ } |
|
| 59 |
+ return "", errors.New("TIOCPTSNAME string not NUL-terminated")
|
|
| 60 |
+} |
|
| 61 |
+ |
|
| 62 |
+func grantpt(f *os.File) error {
|
|
| 63 |
+ /* |
|
| 64 |
+ * from grantpt(3): Calling grantpt() is equivalent to: |
|
| 65 |
+ * ioctl(fd, TIOCGRANTPT, 0); |
|
| 66 |
+ */ |
|
| 67 |
+ return ioctl(f.Fd(), uintptr(ioctl_TIOCGRANTPT), 0) |
|
| 68 |
+} |
| ... | ... |
@@ -1,3 +1,6 @@ |
| 1 |
+//go:build solaris |
|
| 2 |
+// +build solaris |
|
| 3 |
+ |
|
| 1 | 4 |
package pty |
| 2 | 5 |
|
| 3 | 6 |
/* based on: |
| ... | ... |
@@ -6,122 +9,134 @@ http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libc/port/gen/pt.c |
| 6 | 6 |
|
| 7 | 7 |
import ( |
| 8 | 8 |
"errors" |
| 9 |
- "golang.org/x/sys/unix" |
|
| 10 | 9 |
"os" |
| 11 | 10 |
"strconv" |
| 12 | 11 |
"syscall" |
| 13 | 12 |
"unsafe" |
| 14 | 13 |
) |
| 15 | 14 |
|
| 16 |
-const NODEV = ^uint64(0) |
|
| 17 |
- |
|
| 18 | 15 |
func open() (pty, tty *os.File, err error) {
|
| 19 |
- masterfd, err := syscall.Open("/dev/ptmx", syscall.O_RDWR|unix.O_NOCTTY, 0)
|
|
| 20 |
- //masterfd, err := syscall.Open("/dev/ptmx", syscall.O_RDWR|syscall.O_CLOEXEC|unix.O_NOCTTY, 0)
|
|
| 16 |
+ ptmxfd, err := syscall.Open("/dev/ptmx", syscall.O_RDWR|syscall.O_NOCTTY, 0)
|
|
| 21 | 17 |
if err != nil {
|
| 22 | 18 |
return nil, nil, err |
| 23 | 19 |
} |
| 24 |
- p := os.NewFile(uintptr(masterfd), "/dev/ptmx") |
|
| 20 |
+ p := os.NewFile(uintptr(ptmxfd), "/dev/ptmx") |
|
| 21 |
+ // In case of error after this point, make sure we close the ptmx fd. |
|
| 22 |
+ defer func() {
|
|
| 23 |
+ if err != nil {
|
|
| 24 |
+ _ = p.Close() // Best effort. |
|
| 25 |
+ } |
|
| 26 |
+ }() |
|
| 25 | 27 |
|
| 26 | 28 |
sname, err := ptsname(p) |
| 27 | 29 |
if err != nil {
|
| 28 | 30 |
return nil, nil, err |
| 29 | 31 |
} |
| 30 | 32 |
|
| 31 |
- err = grantpt(p) |
|
| 32 |
- if err != nil {
|
|
| 33 |
+ if err := grantpt(p); err != nil {
|
|
| 33 | 34 |
return nil, nil, err |
| 34 | 35 |
} |
| 35 | 36 |
|
| 36 |
- err = unlockpt(p) |
|
| 37 |
- if err != nil {
|
|
| 37 |
+ if err := unlockpt(p); err != nil {
|
|
| 38 | 38 |
return nil, nil, err |
| 39 | 39 |
} |
| 40 | 40 |
|
| 41 |
- slavefd, err := syscall.Open(sname, os.O_RDWR|unix.O_NOCTTY, 0) |
|
| 41 |
+ ptsfd, err := syscall.Open(sname, os.O_RDWR|syscall.O_NOCTTY, 0) |
|
| 42 | 42 |
if err != nil {
|
| 43 | 43 |
return nil, nil, err |
| 44 | 44 |
} |
| 45 |
- t := os.NewFile(uintptr(slavefd), sname) |
|
| 45 |
+ t := os.NewFile(uintptr(ptsfd), sname) |
|
| 46 | 46 |
|
| 47 |
- // pushing terminal driver STREAMS modules as per pts(7) |
|
| 48 |
- for _, mod := range([]string{"ptem", "ldterm", "ttcompat"}) {
|
|
| 49 |
- err = streams_push(t, mod) |
|
| 47 |
+ // In case of error after this point, make sure we close the pts fd. |
|
| 48 |
+ defer func() {
|
|
| 50 | 49 |
if err != nil {
|
| 50 |
+ _ = t.Close() // Best effort. |
|
| 51 |
+ } |
|
| 52 |
+ }() |
|
| 53 |
+ |
|
| 54 |
+ // pushing terminal driver STREAMS modules as per pts(7) |
|
| 55 |
+ for _, mod := range []string{"ptem", "ldterm", "ttcompat"} {
|
|
| 56 |
+ if err := streamsPush(t, mod); err != nil {
|
|
| 51 | 57 |
return nil, nil, err |
| 52 | 58 |
} |
| 53 | 59 |
} |
| 54 |
- |
|
| 55 |
- return p, t, nil |
|
| 56 |
-} |
|
| 57 | 60 |
|
| 58 |
-func minor(x uint64) uint64 {
|
|
| 59 |
- return x & 0377 |
|
| 61 |
+ return p, t, nil |
|
| 60 | 62 |
} |
| 61 | 63 |
|
| 62 |
-func ptsdev(fd uintptr) uint64 {
|
|
| 63 |
- istr := strioctl{ISPTM, 0, 0, nil}
|
|
| 64 |
- err := ioctl(fd, I_STR, uintptr(unsafe.Pointer(&istr))) |
|
| 64 |
+func ptsname(f *os.File) (string, error) {
|
|
| 65 |
+ dev, err := ptsdev(f.Fd()) |
|
| 65 | 66 |
if err != nil {
|
| 66 |
- return NODEV |
|
| 67 |
+ return "", err |
|
| 67 | 68 |
} |
| 68 |
- var status unix.Stat_t |
|
| 69 |
- err = unix.Fstat(int(fd), &status) |
|
| 70 |
- if err != nil {
|
|
| 71 |
- return NODEV |
|
| 69 |
+ fn := "/dev/pts/" + strconv.FormatInt(int64(dev), 10) |
|
| 70 |
+ |
|
| 71 |
+ if err := syscall.Access(fn, 0); err != nil {
|
|
| 72 |
+ return "", err |
|
| 72 | 73 |
} |
| 73 |
- return uint64(minor(status.Rdev)) |
|
| 74 |
+ return fn, nil |
|
| 74 | 75 |
} |
| 75 | 76 |
|
| 76 |
-func ptsname(f *os.File) (string, error) {
|
|
| 77 |
- dev := ptsdev(f.Fd()) |
|
| 78 |
- if dev == NODEV {
|
|
| 79 |
- return "", errors.New("not a master pty")
|
|
| 77 |
+func unlockpt(f *os.File) error {
|
|
| 78 |
+ istr := strioctl{
|
|
| 79 |
+ icCmd: UNLKPT, |
|
| 80 |
+ icTimeout: 0, |
|
| 81 |
+ icLen: 0, |
|
| 82 |
+ icDP: nil, |
|
| 80 | 83 |
} |
| 81 |
- fn := "/dev/pts/" + strconv.FormatInt(int64(dev), 10) |
|
| 82 |
- // access(2) creates the slave device (if the pty exists) |
|
| 83 |
- // F_OK == 0 (unistd.h) |
|
| 84 |
- err := unix.Access(fn, 0) |
|
| 85 |
- if err != nil {
|
|
| 86 |
- return "", err |
|
| 84 |
+ return ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr))) |
|
| 85 |
+} |
|
| 86 |
+ |
|
| 87 |
+func minor(x uint64) uint64 { return x & 0377 }
|
|
| 88 |
+ |
|
| 89 |
+func ptsdev(fd uintptr) (uint64, error) {
|
|
| 90 |
+ istr := strioctl{
|
|
| 91 |
+ icCmd: ISPTM, |
|
| 92 |
+ icTimeout: 0, |
|
| 93 |
+ icLen: 0, |
|
| 94 |
+ icDP: nil, |
|
| 87 | 95 |
} |
| 88 |
- return fn, nil |
|
| 96 |
+ |
|
| 97 |
+ if err := ioctl(fd, I_STR, uintptr(unsafe.Pointer(&istr))); err != nil {
|
|
| 98 |
+ return 0, err |
|
| 99 |
+ } |
|
| 100 |
+ var status syscall.Stat_t |
|
| 101 |
+ if err := syscall.Fstat(int(fd), &status); err != nil {
|
|
| 102 |
+ return 0, err |
|
| 103 |
+ } |
|
| 104 |
+ return uint64(minor(status.Rdev)), nil |
|
| 89 | 105 |
} |
| 90 | 106 |
|
| 91 |
-type pt_own struct {
|
|
| 92 |
- pto_ruid int32 |
|
| 93 |
- pto_rgid int32 |
|
| 107 |
+type ptOwn struct {
|
|
| 108 |
+ rUID int32 |
|
| 109 |
+ rGID int32 |
|
| 94 | 110 |
} |
| 95 | 111 |
|
| 96 | 112 |
func grantpt(f *os.File) error {
|
| 97 |
- if ptsdev(f.Fd()) == NODEV {
|
|
| 98 |
- return errors.New("not a master pty")
|
|
| 99 |
- } |
|
| 100 |
- var pto pt_own |
|
| 101 |
- pto.pto_ruid = int32(os.Getuid()) |
|
| 102 |
- // XXX should first attempt to get gid of DEFAULT_TTY_GROUP="tty" |
|
| 103 |
- pto.pto_rgid = int32(os.Getgid()) |
|
| 104 |
- var istr strioctl |
|
| 105 |
- istr.ic_cmd = OWNERPT |
|
| 106 |
- istr.ic_timout = 0 |
|
| 107 |
- istr.ic_len = int32(unsafe.Sizeof(istr)) |
|
| 108 |
- istr.ic_dp = unsafe.Pointer(&pto) |
|
| 109 |
- err := ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr))) |
|
| 110 |
- if err != nil {
|
|
| 113 |
+ if _, err := ptsdev(f.Fd()); err != nil {
|
|
| 114 |
+ return err |
|
| 115 |
+ } |
|
| 116 |
+ pto := ptOwn{
|
|
| 117 |
+ rUID: int32(os.Getuid()), |
|
| 118 |
+ // XXX should first attempt to get gid of DEFAULT_TTY_GROUP="tty" |
|
| 119 |
+ rGID: int32(os.Getgid()), |
|
| 120 |
+ } |
|
| 121 |
+ istr := strioctl{
|
|
| 122 |
+ icCmd: OWNERPT, |
|
| 123 |
+ icTimeout: 0, |
|
| 124 |
+ icLen: int32(unsafe.Sizeof(strioctl{})),
|
|
| 125 |
+ icDP: unsafe.Pointer(&pto), |
|
| 126 |
+ } |
|
| 127 |
+ if err := ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr))); err != nil {
|
|
| 111 | 128 |
return errors.New("access denied")
|
| 112 | 129 |
} |
| 113 | 130 |
return nil |
| 114 | 131 |
} |
| 115 | 132 |
|
| 116 |
-func unlockpt(f *os.File) error {
|
|
| 117 |
- istr := strioctl{UNLKPT, 0, 0, nil}
|
|
| 118 |
- return ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr))) |
|
| 119 |
-} |
|
| 120 |
- |
|
| 121 |
-// push STREAMS modules if not already done so |
|
| 122 |
-func streams_push(f *os.File, mod string) error {
|
|
| 123 |
- var err error |
|
| 133 |
+// streamsPush pushes STREAMS modules if not already done so. |
|
| 134 |
+func streamsPush(f *os.File, mod string) error {
|
|
| 124 | 135 |
buf := []byte(mod) |
| 136 |
+ |
|
| 125 | 137 |
// XXX I_FIND is not returning an error when the module |
| 126 | 138 |
// is already pushed even though truss reports a return |
| 127 | 139 |
// value of 1. A bug in the Go Solaris syscall interface? |
| ... | ... |
@@ -129,11 +144,9 @@ func streams_push(f *os.File, mod string) error {
|
| 129 | 129 |
// https://www.illumos.org/issues/9042 |
| 130 | 130 |
// but since we are not using libc or XPG4.2, we should not be |
| 131 | 131 |
// double-pushing modules |
| 132 |
- |
|
| 133 |
- err = ioctl(f.Fd(), I_FIND, uintptr(unsafe.Pointer(&buf[0]))) |
|
| 134 |
- if err != nil {
|
|
| 132 |
+ |
|
| 133 |
+ if err := ioctl(f.Fd(), I_FIND, uintptr(unsafe.Pointer(&buf[0]))); err != nil {
|
|
| 135 | 134 |
return nil |
| 136 | 135 |
} |
| 137 |
- err = ioctl(f.Fd(), I_PUSH, uintptr(unsafe.Pointer(&buf[0]))) |
|
| 138 |
- return err |
|
| 136 |
+ return ioctl(f.Fd(), I_PUSH, uintptr(unsafe.Pointer(&buf[0]))) |
|
| 139 | 137 |
} |
| ... | ... |
@@ -1,5 +1,3 @@ |
| 1 |
-// +build !windows |
|
| 2 |
- |
|
| 3 | 1 |
package pty |
| 4 | 2 |
|
| 5 | 3 |
import ( |
| ... | ... |
@@ -13,23 +11,8 @@ import ( |
| 13 | 13 |
// corresponding pty. |
| 14 | 14 |
// |
| 15 | 15 |
// Starts the process in a new session and sets the controlling terminal. |
| 16 |
-func Start(c *exec.Cmd) (pty *os.File, err error) {
|
|
| 17 |
- return StartWithSize(c, nil) |
|
| 18 |
-} |
|
| 19 |
- |
|
| 20 |
-// StartWithSize assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout, |
|
| 21 |
-// and c.Stderr, calls c.Start, and returns the File of the tty's |
|
| 22 |
-// corresponding pty. |
|
| 23 |
-// |
|
| 24 |
-// This will resize the pty to the specified size before starting the command. |
|
| 25 |
-// Starts the process in a new session and sets the controlling terminal. |
|
| 26 |
-func StartWithSize(c *exec.Cmd, sz *Winsize) (pty *os.File, err error) {
|
|
| 27 |
- if c.SysProcAttr == nil {
|
|
| 28 |
- c.SysProcAttr = &syscall.SysProcAttr{}
|
|
| 29 |
- } |
|
| 30 |
- c.SysProcAttr.Setsid = true |
|
| 31 |
- c.SysProcAttr.Setctty = true |
|
| 32 |
- return StartWithAttrs(c, sz, c.SysProcAttr) |
|
| 16 |
+func Start(cmd *exec.Cmd) (*os.File, error) {
|
|
| 17 |
+ return StartWithSize(cmd, nil) |
|
| 33 | 18 |
} |
| 34 | 19 |
|
| 35 | 20 |
// StartWithAttrs assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout, |
| ... | ... |
@@ -41,16 +24,16 @@ func StartWithSize(c *exec.Cmd, sz *Winsize) (pty *os.File, err error) {
|
| 41 | 41 |
// |
| 42 | 42 |
// This should generally not be needed. Used in some edge cases where it is needed to create a pty |
| 43 | 43 |
// without a controlling terminal. |
| 44 |
-func StartWithAttrs(c *exec.Cmd, sz *Winsize, attrs *syscall.SysProcAttr) (pty *os.File, err error) {
|
|
| 44 |
+func StartWithAttrs(c *exec.Cmd, sz *Winsize, attrs *syscall.SysProcAttr) (*os.File, error) {
|
|
| 45 | 45 |
pty, tty, err := Open() |
| 46 | 46 |
if err != nil {
|
| 47 | 47 |
return nil, err |
| 48 | 48 |
} |
| 49 |
- defer tty.Close() |
|
| 49 |
+ defer func() { _ = tty.Close() }() // Best effort.
|
|
| 50 | 50 |
|
| 51 | 51 |
if sz != nil {
|
| 52 | 52 |
if err := Setsize(pty, sz); err != nil {
|
| 53 |
- pty.Close() |
|
| 53 |
+ _ = pty.Close() // Best effort. |
|
| 54 | 54 |
return nil, err |
| 55 | 55 |
} |
| 56 | 56 |
} |
| ... | ... |
@@ -67,7 +50,7 @@ func StartWithAttrs(c *exec.Cmd, sz *Winsize, attrs *syscall.SysProcAttr) (pty * |
| 67 | 67 |
c.SysProcAttr = attrs |
| 68 | 68 |
|
| 69 | 69 |
if err := c.Start(); err != nil {
|
| 70 |
- _ = pty.Close() |
|
| 70 |
+ _ = pty.Close() // Best effort. |
|
| 71 | 71 |
return nil, err |
| 72 | 72 |
} |
| 73 | 73 |
return pty, err |
| 74 | 74 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,25 @@ |
| 0 |
+//go:build !windows |
|
| 1 |
+// +build !windows |
|
| 2 |
+ |
|
| 3 |
+package pty |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "os" |
|
| 7 |
+ "os/exec" |
|
| 8 |
+ "syscall" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+// StartWithSize assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout, |
|
| 12 |
+// and c.Stderr, calls c.Start, and returns the File of the tty's |
|
| 13 |
+// corresponding pty. |
|
| 14 |
+// |
|
| 15 |
+// This will resize the pty to the specified size before starting the command. |
|
| 16 |
+// Starts the process in a new session and sets the controlling terminal. |
|
| 17 |
+func StartWithSize(cmd *exec.Cmd, ws *Winsize) (*os.File, error) {
|
|
| 18 |
+ if cmd.SysProcAttr == nil {
|
|
| 19 |
+ cmd.SysProcAttr = &syscall.SysProcAttr{}
|
|
| 20 |
+ } |
|
| 21 |
+ cmd.SysProcAttr.Setsid = true |
|
| 22 |
+ cmd.SysProcAttr.Setctty = true |
|
| 23 |
+ return StartWithAttrs(cmd, ws, cmd.SysProcAttr) |
|
| 24 |
+} |
| 0 | 25 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,19 @@ |
| 0 |
+//go:build windows |
|
| 1 |
+// +build windows |
|
| 2 |
+ |
|
| 3 |
+package pty |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "os" |
|
| 7 |
+ "os/exec" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+// StartWithSize assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout, |
|
| 11 |
+// and c.Stderr, calls c.Start, and returns the File of the tty's |
|
| 12 |
+// corresponding pty. |
|
| 13 |
+// |
|
| 14 |
+// This will resize the pty to the specified size before starting the command. |
|
| 15 |
+// Starts the process in a new session and sets the controlling terminal. |
|
| 16 |
+func StartWithSize(cmd *exec.Cmd, ws *Winsize) (*os.File, error) {
|
|
| 17 |
+ return nil, ErrUnsupported |
|
| 18 |
+} |
| ... | ... |
@@ -4,31 +4,31 @@ |
| 4 | 4 |
# Does not actually test the logic, just the compilation so we make sure we don't break code depending on the lib. |
| 5 | 5 |
|
| 6 | 6 |
echo2() {
|
| 7 |
- echo $@ >&2 |
|
| 7 |
+ echo $@ >&2 |
|
| 8 | 8 |
} |
| 9 | 9 |
|
| 10 | 10 |
trap end 0 |
| 11 | 11 |
end() {
|
| 12 |
- [ "$?" = 0 ] && echo2 "Pass." || (echo2 "Fail."; exit 1) |
|
| 12 |
+ [ "$?" = 0 ] && echo2 "Pass." || (echo2 "Fail."; exit 1) |
|
| 13 | 13 |
} |
| 14 | 14 |
|
| 15 | 15 |
cross() {
|
| 16 |
- os=$1 |
|
| 17 |
- shift |
|
| 18 |
- echo2 "Build for $os." |
|
| 19 |
- for arch in $@; do |
|
| 20 |
- echo2 " - $os/$arch" |
|
| 21 |
- GOOS=$os GOARCH=$arch go build |
|
| 22 |
- done |
|
| 23 |
- echo2 |
|
| 16 |
+ os=$1 |
|
| 17 |
+ shift |
|
| 18 |
+ echo2 "Build for $os." |
|
| 19 |
+ for arch in $@; do |
|
| 20 |
+ echo2 " - $os/$arch" |
|
| 21 |
+ GOOS=$os GOARCH=$arch go build |
|
| 22 |
+ done |
|
| 23 |
+ echo2 |
|
| 24 | 24 |
} |
| 25 | 25 |
|
| 26 | 26 |
set -e |
| 27 | 27 |
|
| 28 | 28 |
cross linux amd64 386 arm arm64 ppc64 ppc64le s390x mips mipsle mips64 mips64le |
| 29 |
-cross darwin amd64 386 arm arm64 |
|
| 30 |
-cross freebsd amd64 386 arm |
|
| 31 |
-cross netbsd amd64 386 arm |
|
| 29 |
+cross darwin amd64 arm64 |
|
| 30 |
+cross freebsd amd64 386 arm arm64 |
|
| 31 |
+cross netbsd amd64 386 arm arm64 |
|
| 32 | 32 |
cross openbsd amd64 386 arm arm64 |
| 33 | 33 |
cross dragonfly amd64 |
| 34 | 34 |
cross solaris amd64 |
| ... | ... |
@@ -41,10 +41,24 @@ cross windows amd64 386 arm |
| 41 | 41 |
|
| 42 | 42 |
# Some os/arch require a different compiler. Run in docker. |
| 43 | 43 |
if ! hash docker; then |
| 44 |
- # If docker is not present, stop here. |
|
| 45 |
- return |
|
| 44 |
+ # If docker is not present, stop here. |
|
| 45 |
+ return |
|
| 46 | 46 |
fi |
| 47 | 47 |
|
| 48 | 48 |
echo2 "Build for linux." |
| 49 | 49 |
echo2 " - linux/riscv" |
| 50 |
-docker build -t test -f Dockerfile.riscv . |
|
| 50 |
+docker build -t creack-pty-test -f Dockerfile.riscv . |
|
| 51 |
+ |
|
| 52 |
+# Golang dropped support for darwin 32bits since go1.15. Make sure the lib still compile with go1.14 on those archs. |
|
| 53 |
+echo2 "Build for darwin (32bits)." |
|
| 54 |
+echo2 " - darwin/386" |
|
| 55 |
+docker build -t creack-pty-test -f Dockerfile.golang --build-arg=GOVERSION=1.14 --build-arg=GOOS=darwin --build-arg=GOARCH=386 . |
|
| 56 |
+echo2 " - darwin/arm" |
|
| 57 |
+docker build -t creack-pty-test -f Dockerfile.golang --build-arg=GOVERSION=1.14 --build-arg=GOOS=darwin --build-arg=GOARCH=arm . |
|
| 58 |
+ |
|
| 59 |
+# Run a single test for an old go version. Would be best with go1.0, but not available on Dockerhub. |
|
| 60 |
+# Using 1.6 as it is the base version for the RISCV compiler. |
|
| 61 |
+# Would also be better to run all the tests, not just one, need to refactor this file to allow for specifc archs per version. |
|
| 62 |
+echo2 "Build for linux - go1.6." |
|
| 63 |
+echo2 " - linux/amd64" |
|
| 64 |
+docker build -t creack-pty-test -f Dockerfile.golang --build-arg=GOVERSION=1.6 --build-arg=GOOS=linux --build-arg=GOARCH=amd64 . |
| 51 | 65 |
deleted file mode 100644 |
| ... | ... |
@@ -1,64 +0,0 @@ |
| 1 |
-// +build !windows,!solaris |
|
| 2 |
- |
|
| 3 |
-package pty |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "os" |
|
| 7 |
- "syscall" |
|
| 8 |
- "unsafe" |
|
| 9 |
-) |
|
| 10 |
- |
|
| 11 |
-// InheritSize applies the terminal size of pty to tty. This should be run |
|
| 12 |
-// in a signal handler for syscall.SIGWINCH to automatically resize the tty when |
|
| 13 |
-// the pty receives a window size change notification. |
|
| 14 |
-func InheritSize(pty, tty *os.File) error {
|
|
| 15 |
- size, err := GetsizeFull(pty) |
|
| 16 |
- if err != nil {
|
|
| 17 |
- return err |
|
| 18 |
- } |
|
| 19 |
- err = Setsize(tty, size) |
|
| 20 |
- if err != nil {
|
|
| 21 |
- return err |
|
| 22 |
- } |
|
| 23 |
- return nil |
|
| 24 |
-} |
|
| 25 |
- |
|
| 26 |
-// Setsize resizes t to s. |
|
| 27 |
-func Setsize(t *os.File, ws *Winsize) error {
|
|
| 28 |
- return windowRectCall(ws, t.Fd(), syscall.TIOCSWINSZ) |
|
| 29 |
-} |
|
| 30 |
- |
|
| 31 |
-// GetsizeFull returns the full terminal size description. |
|
| 32 |
-func GetsizeFull(t *os.File) (size *Winsize, err error) {
|
|
| 33 |
- var ws Winsize |
|
| 34 |
- err = windowRectCall(&ws, t.Fd(), syscall.TIOCGWINSZ) |
|
| 35 |
- return &ws, err |
|
| 36 |
-} |
|
| 37 |
- |
|
| 38 |
-// Getsize returns the number of rows (lines) and cols (positions |
|
| 39 |
-// in each line) in terminal t. |
|
| 40 |
-func Getsize(t *os.File) (rows, cols int, err error) {
|
|
| 41 |
- ws, err := GetsizeFull(t) |
|
| 42 |
- return int(ws.Rows), int(ws.Cols), err |
|
| 43 |
-} |
|
| 44 |
- |
|
| 45 |
-// Winsize describes the terminal size. |
|
| 46 |
-type Winsize struct {
|
|
| 47 |
- Rows uint16 // ws_row: Number of rows (in cells) |
|
| 48 |
- Cols uint16 // ws_col: Number of columns (in cells) |
|
| 49 |
- X uint16 // ws_xpixel: Width in pixels |
|
| 50 |
- Y uint16 // ws_ypixel: Height in pixels |
|
| 51 |
-} |
|
| 52 |
- |
|
| 53 |
-func windowRectCall(ws *Winsize, fd, a2 uintptr) error {
|
|
| 54 |
- _, _, errno := syscall.Syscall( |
|
| 55 |
- syscall.SYS_IOCTL, |
|
| 56 |
- fd, |
|
| 57 |
- a2, |
|
| 58 |
- uintptr(unsafe.Pointer(ws)), |
|
| 59 |
- ) |
|
| 60 |
- if errno != 0 {
|
|
| 61 |
- return syscall.Errno(errno) |
|
| 62 |
- } |
|
| 63 |
- return nil |
|
| 64 |
-} |
| 65 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,51 +0,0 @@ |
| 1 |
-// |
|
| 2 |
- |
|
| 3 |
-package pty |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "os" |
|
| 7 |
- "golang.org/x/sys/unix" |
|
| 8 |
-) |
|
| 9 |
- |
|
| 10 |
-const ( |
|
| 11 |
- TIOCGWINSZ = 21608 // 'T' << 8 | 104 |
|
| 12 |
- TIOCSWINSZ = 21607 // 'T' << 8 | 103 |
|
| 13 |
-) |
|
| 14 |
- |
|
| 15 |
-// Winsize describes the terminal size. |
|
| 16 |
-type Winsize struct {
|
|
| 17 |
- Rows uint16 // ws_row: Number of rows (in cells) |
|
| 18 |
- Cols uint16 // ws_col: Number of columns (in cells) |
|
| 19 |
- X uint16 // ws_xpixel: Width in pixels |
|
| 20 |
- Y uint16 // ws_ypixel: Height in pixels |
|
| 21 |
-} |
|
| 22 |
- |
|
| 23 |
-// GetsizeFull returns the full terminal size description. |
|
| 24 |
-func GetsizeFull(t *os.File) (size *Winsize, err error) {
|
|
| 25 |
- var wsz *unix.Winsize |
|
| 26 |
- wsz, err = unix.IoctlGetWinsize(int(t.Fd()), TIOCGWINSZ) |
|
| 27 |
- |
|
| 28 |
- if err != nil {
|
|
| 29 |
- return nil, err |
|
| 30 |
- } else {
|
|
| 31 |
- return &Winsize{wsz.Row, wsz.Col, wsz.Xpixel, wsz.Ypixel}, nil
|
|
| 32 |
- } |
|
| 33 |
-} |
|
| 34 |
- |
|
| 35 |
-// Get Windows Size |
|
| 36 |
-func Getsize(t *os.File) (rows, cols int, err error) {
|
|
| 37 |
- var wsz *unix.Winsize |
|
| 38 |
- wsz, err = unix.IoctlGetWinsize(int(t.Fd()), TIOCGWINSZ) |
|
| 39 |
- |
|
| 40 |
- if err != nil {
|
|
| 41 |
- return 80, 25, err |
|
| 42 |
- } else {
|
|
| 43 |
- return int(wsz.Row), int(wsz.Col), nil |
|
| 44 |
- } |
|
| 45 |
-} |
|
| 46 |
- |
|
| 47 |
-// Setsize resizes t to s. |
|
| 48 |
-func Setsize(t *os.File, ws *Winsize) error {
|
|
| 49 |
- wsz := unix.Winsize{ws.Rows, ws.Cols, ws.X, ws.Y}
|
|
| 50 |
- return unix.IoctlSetWinsize(int(t.Fd()), TIOCSWINSZ, &wsz) |
|
| 51 |
-} |
| 52 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,27 @@ |
| 0 |
+package pty |
|
| 1 |
+ |
|
| 2 |
+import "os" |
|
| 3 |
+ |
|
| 4 |
+// InheritSize applies the terminal size of pty to tty. This should be run |
|
| 5 |
+// in a signal handler for syscall.SIGWINCH to automatically resize the tty when |
|
| 6 |
+// the pty receives a window size change notification. |
|
| 7 |
+func InheritSize(pty, tty *os.File) error {
|
|
| 8 |
+ size, err := GetsizeFull(pty) |
|
| 9 |
+ if err != nil {
|
|
| 10 |
+ return err |
|
| 11 |
+ } |
|
| 12 |
+ if err := Setsize(tty, size); err != nil {
|
|
| 13 |
+ return err |
|
| 14 |
+ } |
|
| 15 |
+ return nil |
|
| 16 |
+} |
|
| 17 |
+ |
|
| 18 |
+// Getsize returns the number of rows (lines) and cols (positions |
|
| 19 |
+// in each line) in terminal t. |
|
| 20 |
+func Getsize(t *os.File) (rows, cols int, err error) {
|
|
| 21 |
+ ws, err := GetsizeFull(t) |
|
| 22 |
+ if err != nil {
|
|
| 23 |
+ return 0, 0, err |
|
| 24 |
+ } |
|
| 25 |
+ return int(ws.Rows), int(ws.Cols), nil |
|
| 26 |
+} |
| 0 | 27 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,35 @@ |
| 0 |
+//go:build !windows |
|
| 1 |
+// +build !windows |
|
| 2 |
+ |
|
| 3 |
+package pty |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "os" |
|
| 7 |
+ "syscall" |
|
| 8 |
+ "unsafe" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+// Winsize describes the terminal size. |
|
| 12 |
+type Winsize struct {
|
|
| 13 |
+ Rows uint16 // ws_row: Number of rows (in cells) |
|
| 14 |
+ Cols uint16 // ws_col: Number of columns (in cells) |
|
| 15 |
+ X uint16 // ws_xpixel: Width in pixels |
|
| 16 |
+ Y uint16 // ws_ypixel: Height in pixels |
|
| 17 |
+} |
|
| 18 |
+ |
|
| 19 |
+// Setsize resizes t to s. |
|
| 20 |
+func Setsize(t *os.File, ws *Winsize) error {
|
|
| 21 |
+ //nolint:gosec // Expected unsafe pointer for Syscall call. |
|
| 22 |
+ return ioctl(t.Fd(), syscall.TIOCSWINSZ, uintptr(unsafe.Pointer(ws))) |
|
| 23 |
+} |
|
| 24 |
+ |
|
| 25 |
+// GetsizeFull returns the full terminal size description. |
|
| 26 |
+func GetsizeFull(t *os.File) (size *Winsize, err error) {
|
|
| 27 |
+ var ws Winsize |
|
| 28 |
+ |
|
| 29 |
+ //nolint:gosec // Expected unsafe pointer for Syscall call. |
|
| 30 |
+ if err := ioctl(t.Fd(), syscall.TIOCGWINSZ, uintptr(unsafe.Pointer(&ws))); err != nil {
|
|
| 31 |
+ return nil, err |
|
| 32 |
+ } |
|
| 33 |
+ return &ws, nil |
|
| 34 |
+} |
| 0 | 35 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,23 @@ |
| 0 |
+//go:build windows |
|
| 1 |
+// +build windows |
|
| 2 |
+ |
|
| 3 |
+package pty |
|
| 4 |
+ |
|
| 5 |
+import ( |
|
| 6 |
+ "os" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+// Winsize is a dummy struct to enable compilation on unsupported platforms. |
|
| 10 |
+type Winsize struct {
|
|
| 11 |
+ Rows, Cols, X, Y uint16 |
|
| 12 |
+} |
|
| 13 |
+ |
|
| 14 |
+// Setsize resizes t to s. |
|
| 15 |
+func Setsize(*os.File, *Winsize) error {
|
|
| 16 |
+ return ErrUnsupported |
|
| 17 |
+} |
|
| 18 |
+ |
|
| 19 |
+// GetsizeFull returns the full terminal size description. |
|
| 20 |
+func GetsizeFull(*os.File) (*Winsize, error) {
|
|
| 21 |
+ return nil, ErrUnsupported |
|
| 22 |
+} |
| ... | ... |
@@ -1,9 +1,10 @@ |
| 1 |
+//go:build (mips || mipsle || mips64 || mips64le) && linux |
|
| 2 |
+// +build mips mipsle mips64 mips64le |
|
| 3 |
+// +build linux |
|
| 4 |
+ |
|
| 1 | 5 |
// Created by cgo -godefs - DO NOT EDIT |
| 2 | 6 |
// cgo -godefs types.go |
| 3 | 7 |
|
| 4 |
-// +build linux |
|
| 5 |
-// +build mips mipsle mips64 mips64le |
|
| 6 |
- |
|
| 7 | 8 |
package pty |
| 8 | 9 |
|
| 9 | 10 |
type ( |
| 10 | 11 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,17 @@ |
| 0 |
+//go:build (386 || amd64 || arm || arm64) && netbsd |
|
| 1 |
+// +build 386 amd64 arm arm64 |
|
| 2 |
+// +build netbsd |
|
| 3 |
+ |
|
| 4 |
+package pty |
|
| 5 |
+ |
|
| 6 |
+type ptmget struct {
|
|
| 7 |
+ Cfd int32 |
|
| 8 |
+ Sfd int32 |
|
| 9 |
+ Cn [1024]int8 |
|
| 10 |
+ Sn [1024]int8 |
|
| 11 |
+} |
|
| 12 |
+ |
|
| 13 |
+var ( |
|
| 14 |
+ ioctl_TIOCPTSNAME = 0x48087448 |
|
| 15 |
+ ioctl_TIOCGRANTPT = 0x20007447 |
|
| 16 |
+) |
| ... | ... |
@@ -1,13 +1,14 @@ |
| 1 |
+//go:build (386 || amd64 || arm || arm64 || mips64) && openbsd |
|
| 2 |
+// +build 386 amd64 arm arm64 mips64 |
|
| 1 | 3 |
// +build openbsd |
| 2 |
-// +build 386 amd64 arm arm64 |
|
| 3 | 4 |
|
| 4 | 5 |
package pty |
| 5 | 6 |
|
| 6 | 7 |
type ptmget struct {
|
| 7 |
- Cfd int32 |
|
| 8 |
- Sfd int32 |
|
| 9 |
- Cn [16]int8 |
|
| 10 |
- Sn [16]int8 |
|
| 8 |
+ Cfd int32 |
|
| 9 |
+ Sfd int32 |
|
| 10 |
+ Cn [16]int8 |
|
| 11 |
+ Sn [16]int8 |
|
| 11 | 12 |
} |
| 12 | 13 |
|
| 13 | 14 |
var ioctl_PTMGET = 0x40287401 |
| ... | ... |
@@ -350,7 +350,7 @@ github.com/coreos/go-systemd/v22/activation |
| 350 | 350 |
github.com/coreos/go-systemd/v22/daemon |
| 351 | 351 |
github.com/coreos/go-systemd/v22/dbus |
| 352 | 352 |
github.com/coreos/go-systemd/v22/journal |
| 353 |
-# github.com/creack/pty v1.1.11 |
|
| 353 |
+# github.com/creack/pty v1.1.18 |
|
| 354 | 354 |
## explicit; go 1.13 |
| 355 | 355 |
github.com/creack/pty |
| 356 | 356 |
# github.com/cyphar/filepath-securejoin v0.2.3 |