Import upstream version 1.1.8, md5 e7956100803c8469a69596a0619e4427
Debian Janitor
3 years ago
0 | FROM golang:1.12 | |
1 | ||
2 | # Clone and complie a riscv compatible version of the go compiler. | |
3 | RUN git clone https://review.gerrithub.io/riscv/riscv-go /riscv-go | |
4 | # riscvdev branch HEAD as of 2019-06-29. | |
5 | RUN cd /riscv-go && git checkout 04885fddd096d09d4450726064d06dd107e374bf | |
6 | ENV PATH=/riscv-go/misc/riscv:/riscv-go/bin:$PATH | |
7 | RUN cd /riscv-go/src && GOROOT_BOOTSTRAP=$(go env GOROOT) ./make.bash | |
8 | ENV GOROOT=/riscv-go | |
9 | ||
10 | # Make sure we compile. | |
11 | WORKDIR pty | |
12 | ADD . . | |
13 | RUN GOOS=linux GOARCH=riscv go build |
0 | Copyright (c) 2011 Keith Rarick | |
0 | Copyright (c) 2019 Keith Rarick | |
1 | 1 | |
2 | 2 | Permission is hereby granted, free of charge, to any person |
3 | 3 | obtaining a copy of this software and associated |
0 | 0 | # pty |
1 | 1 | |
2 | Pty is a Go package for using unix pseudo-terminals. | |
2 | This Go module has moved to <https://github.com/creack/pty>. | |
3 | 3 | |
4 | ## Install | |
4 | Existing clients will continue to work. | |
5 | 5 | |
6 | go get github.com/creack/pty | |
6 | New clients should use the new module import path | |
7 | `github.com/creack/pty`. | |
7 | 8 | |
8 | ## Example | |
9 | ||
10 | ### Command | |
11 | ||
12 | ```go | |
13 | package main | |
14 | ||
15 | import ( | |
16 | "github.com/creack/pty" | |
17 | "io" | |
18 | "os" | |
19 | "os/exec" | |
20 | ) | |
21 | ||
22 | func main() { | |
23 | c := exec.Command("grep", "--color=auto", "bar") | |
24 | f, err := pty.Start(c) | |
25 | if err != nil { | |
26 | panic(err) | |
27 | } | |
28 | ||
29 | go func() { | |
30 | f.Write([]byte("foo\n")) | |
31 | f.Write([]byte("bar\n")) | |
32 | f.Write([]byte("baz\n")) | |
33 | f.Write([]byte{4}) // EOT | |
34 | }() | |
35 | io.Copy(os.Stdout, f) | |
36 | } | |
37 | ``` | |
38 | ||
39 | ### Shell | |
40 | ||
41 | ```go | |
42 | package main | |
43 | ||
44 | import ( | |
45 | "io" | |
46 | "log" | |
47 | "os" | |
48 | "os/exec" | |
49 | "os/signal" | |
50 | "syscall" | |
51 | ||
52 | "github.com/creack/pty" | |
53 | "golang.org/x/crypto/ssh/terminal" | |
54 | ) | |
55 | ||
56 | func test() error { | |
57 | // Create arbitrary command. | |
58 | c := exec.Command("bash") | |
59 | ||
60 | // Start the command with a pty. | |
61 | ptmx, err := pty.Start(c) | |
62 | if err != nil { | |
63 | return err | |
64 | } | |
65 | // Make sure to close the pty at the end. | |
66 | defer func() { _ = ptmx.Close() }() // Best effort. | |
67 | ||
68 | // Handle pty size. | |
69 | ch := make(chan os.Signal, 1) | |
70 | signal.Notify(ch, syscall.SIGWINCH) | |
71 | go func() { | |
72 | for range ch { | |
73 | if err := pty.InheritSize(os.Stdin, ptmx); err != nil { | |
74 | log.Printf("error resizing pty: %s", err) | |
75 | } | |
76 | } | |
77 | }() | |
78 | ch <- syscall.SIGWINCH // Initial resize. | |
79 | ||
80 | // Set stdin in raw mode. | |
81 | oldState, err := terminal.MakeRaw(int(os.Stdin.Fd())) | |
82 | if err != nil { | |
83 | panic(err) | |
84 | } | |
85 | defer func() { _ = terminal.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort. | |
86 | ||
87 | // Copy stdin to the pty and the pty to stdout. | |
88 | go func() { _, _ = io.Copy(ptmx, os.Stdin) }() | |
89 | _, _ = io.Copy(os.Stdout, ptmx) | |
90 | ||
91 | return nil | |
92 | } | |
93 | ||
94 | func main() { | |
95 | if err := test(); err != nil { | |
96 | log.Fatal(err) | |
97 | } | |
98 | } | |
99 | ``` |
0 | // Package pty provides functions for working with Unix terminals. | |
1 | package pty | |
2 | ||
3 | import ( | |
4 | "errors" | |
5 | "os" | |
6 | ) | |
7 | ||
8 | // ErrUnsupported is returned if a function is not | |
9 | // available on the current platform. | |
10 | var ErrUnsupported = errors.New("unsupported") | |
11 | ||
12 | // Opens a pty and its corresponding tty. | |
13 | func Open() (pty, tty *os.File, err error) { | |
14 | return open() | |
15 | } |
0 | github.com/creack/pty v1.1.7 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A= | |
1 | github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= |
0 | // +build !windows,!solaris | |
1 | ||
2 | package pty | |
3 | ||
4 | import "syscall" | |
5 | ||
6 | func ioctl(fd, cmd, ptr uintptr) error { | |
7 | _, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, cmd, ptr) | |
8 | if e != 0 { | |
9 | return e | |
10 | } | |
11 | return nil | |
12 | } |
0 | // +build darwin dragonfly freebsd netbsd openbsd | |
1 | ||
2 | package pty | |
3 | ||
4 | // from <sys/ioccom.h> | |
5 | const ( | |
6 | _IOC_VOID uintptr = 0x20000000 | |
7 | _IOC_OUT uintptr = 0x40000000 | |
8 | _IOC_IN uintptr = 0x80000000 | |
9 | _IOC_IN_OUT uintptr = _IOC_OUT | _IOC_IN | |
10 | _IOC_DIRMASK = _IOC_VOID | _IOC_OUT | _IOC_IN | |
11 | ||
12 | _IOC_PARAM_SHIFT = 13 | |
13 | _IOC_PARAM_MASK = (1 << _IOC_PARAM_SHIFT) - 1 | |
14 | ) | |
15 | ||
16 | func _IOC_PARM_LEN(ioctl uintptr) uintptr { | |
17 | return (ioctl >> 16) & _IOC_PARAM_MASK | |
18 | } | |
19 | ||
20 | func _IOC(inout uintptr, group byte, ioctl_num uintptr, param_len uintptr) uintptr { | |
21 | return inout | (param_len&_IOC_PARAM_MASK)<<16 | uintptr(group)<<8 | ioctl_num | |
22 | } | |
23 | ||
24 | func _IO(group byte, ioctl_num uintptr) uintptr { | |
25 | return _IOC(_IOC_VOID, group, ioctl_num, 0) | |
26 | } | |
27 | ||
28 | func _IOR(group byte, ioctl_num uintptr, param_len uintptr) uintptr { | |
29 | return _IOC(_IOC_OUT, group, ioctl_num, param_len) | |
30 | } | |
31 | ||
32 | func _IOW(group byte, ioctl_num uintptr, param_len uintptr) uintptr { | |
33 | return _IOC(_IOC_IN, group, ioctl_num, param_len) | |
34 | } | |
35 | ||
36 | func _IOWR(group byte, ioctl_num uintptr, param_len uintptr) uintptr { | |
37 | return _IOC(_IOC_IN_OUT, group, ioctl_num, param_len) | |
38 | } |
0 | package pty | |
1 | ||
2 | import ( | |
3 | "golang.org/x/sys/unix" | |
4 | "unsafe" | |
5 | ) | |
6 | ||
7 | const ( | |
8 | // see /usr/include/sys/stropts.h | |
9 | I_PUSH = uintptr((int32('S')<<8 | 002)) | |
10 | I_STR = uintptr((int32('S')<<8 | 010)) | |
11 | I_FIND = uintptr((int32('S')<<8 | 013)) | |
12 | // see /usr/include/sys/ptms.h | |
13 | ISPTM = (int32('P') << 8) | 1 | |
14 | UNLKPT = (int32('P') << 8) | 2 | |
15 | PTSSTTY = (int32('P') << 8) | 3 | |
16 | ZONEPT = (int32('P') << 8) | 4 | |
17 | OWNERPT = (int32('P') << 8) | 5 | |
18 | ) | |
19 | ||
20 | type strioctl struct { | |
21 | ic_cmd int32 | |
22 | ic_timout int32 | |
23 | ic_len int32 | |
24 | ic_dp unsafe.Pointer | |
25 | } | |
26 | ||
27 | func ioctl(fd, cmd, ptr uintptr) error { | |
28 | return unix.IoctlSetInt(int(fd), uint(cmd), int(ptr)) | |
29 | } |
0 | #!/usr/bin/env bash | |
1 | ||
2 | GOOSARCH="${GOOS}_${GOARCH}" | |
3 | case "$GOOSARCH" in | |
4 | _* | *_ | _) | |
5 | echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2 | |
6 | exit 1 | |
7 | ;; | |
8 | esac | |
9 | ||
10 | GODEFS="go tool cgo -godefs" | |
11 | ||
12 | $GODEFS types.go |gofmt > ztypes_$GOARCH.go | |
13 | ||
14 | case $GOOS in | |
15 | freebsd|dragonfly|openbsd) | |
16 | $GODEFS types_$GOOS.go |gofmt > ztypes_$GOOSARCH.go | |
17 | ;; | |
18 | esac |
0 | package pty | |
1 | ||
2 | import ( | |
3 | "errors" | |
4 | "os" | |
5 | "syscall" | |
6 | "unsafe" | |
7 | ) | |
8 | ||
9 | func open() (pty, tty *os.File, err error) { | |
10 | pFD, err := syscall.Open("/dev/ptmx", syscall.O_RDWR|syscall.O_CLOEXEC, 0) | |
11 | if err != nil { | |
12 | return nil, nil, err | |
13 | } | |
14 | p := os.NewFile(uintptr(pFD), "/dev/ptmx") | |
15 | // In case of error after this point, make sure we close the ptmx fd. | |
16 | defer func() { | |
17 | if err != nil { | |
18 | _ = p.Close() // Best effort. | |
19 | } | |
20 | }() | |
21 | ||
22 | sname, err := ptsname(p) | |
23 | if err != nil { | |
24 | return nil, nil, err | |
25 | } | |
26 | ||
27 | if err := grantpt(p); err != nil { | |
28 | return nil, nil, err | |
29 | } | |
30 | ||
31 | if err := unlockpt(p); err != nil { | |
32 | return nil, nil, err | |
33 | } | |
34 | ||
35 | t, err := os.OpenFile(sname, os.O_RDWR, 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 | n := make([]byte, _IOC_PARM_LEN(syscall.TIOCPTYGNAME)) | |
44 | ||
45 | err := ioctl(f.Fd(), syscall.TIOCPTYGNAME, uintptr(unsafe.Pointer(&n[0]))) | |
46 | if err != nil { | |
47 | return "", err | |
48 | } | |
49 | ||
50 | for i, c := range n { | |
51 | if c == 0 { | |
52 | return string(n[:i]), nil | |
53 | } | |
54 | } | |
55 | return "", errors.New("TIOCPTYGNAME string not NUL-terminated") | |
56 | } | |
57 | ||
58 | func grantpt(f *os.File) error { | |
59 | return ioctl(f.Fd(), syscall.TIOCPTYGRANT, 0) | |
60 | } | |
61 | ||
62 | func unlockpt(f *os.File) error { | |
63 | return ioctl(f.Fd(), syscall.TIOCPTYUNLK, 0) | |
64 | } |
0 | package pty | |
1 | ||
2 | import ( | |
3 | "errors" | |
4 | "os" | |
5 | "strings" | |
6 | "syscall" | |
7 | "unsafe" | |
8 | ) | |
9 | ||
10 | // same code as pty_darwin.go | |
11 | func open() (pty, tty *os.File, err error) { | |
12 | p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0) | |
13 | if err != nil { | |
14 | return nil, nil, err | |
15 | } | |
16 | // In case of error after this point, make sure we close the ptmx fd. | |
17 | defer func() { | |
18 | if err != nil { | |
19 | _ = p.Close() // Best effort. | |
20 | } | |
21 | }() | |
22 | ||
23 | sname, err := ptsname(p) | |
24 | if err != nil { | |
25 | return nil, nil, err | |
26 | } | |
27 | ||
28 | if err := grantpt(p); err != nil { | |
29 | return nil, nil, err | |
30 | } | |
31 | ||
32 | if err := unlockpt(p); err != nil { | |
33 | return nil, nil, err | |
34 | } | |
35 | ||
36 | t, err := os.OpenFile(sname, os.O_RDWR, 0) | |
37 | if err != nil { | |
38 | return nil, nil, err | |
39 | } | |
40 | return p, t, nil | |
41 | } | |
42 | ||
43 | func grantpt(f *os.File) error { | |
44 | _, err := isptmaster(f.Fd()) | |
45 | return err | |
46 | } | |
47 | ||
48 | func unlockpt(f *os.File) error { | |
49 | _, err := isptmaster(f.Fd()) | |
50 | return err | |
51 | } | |
52 | ||
53 | func isptmaster(fd uintptr) (bool, error) { | |
54 | err := ioctl(fd, syscall.TIOCISPTMASTER, 0) | |
55 | return err == nil, err | |
56 | } | |
57 | ||
58 | var ( | |
59 | emptyFiodgnameArg fiodgnameArg | |
60 | ioctl_FIODNAME = _IOW('f', 120, unsafe.Sizeof(emptyFiodgnameArg)) | |
61 | ) | |
62 | ||
63 | func ptsname(f *os.File) (string, error) { | |
64 | name := make([]byte, _C_SPECNAMELEN) | |
65 | fa := fiodgnameArg{Name: (*byte)(unsafe.Pointer(&name[0])), Len: _C_SPECNAMELEN, Pad_cgo_0: [4]byte{0, 0, 0, 0}} | |
66 | ||
67 | err := ioctl(f.Fd(), ioctl_FIODNAME, uintptr(unsafe.Pointer(&fa))) | |
68 | if err != nil { | |
69 | return "", err | |
70 | } | |
71 | ||
72 | for i, c := range name { | |
73 | if c == 0 { | |
74 | s := "/dev/" + string(name[:i]) | |
75 | return strings.Replace(s, "ptm", "pts", -1), nil | |
76 | } | |
77 | } | |
78 | return "", errors.New("TIOCPTYGNAME string not NUL-terminated") | |
79 | } |
0 | package pty | |
1 | ||
2 | import ( | |
3 | "errors" | |
4 | "os" | |
5 | "syscall" | |
6 | "unsafe" | |
7 | ) | |
8 | ||
9 | func posixOpenpt(oflag int) (fd int, err error) { | |
10 | r0, _, e1 := syscall.Syscall(syscall.SYS_POSIX_OPENPT, uintptr(oflag), 0, 0) | |
11 | fd = int(r0) | |
12 | if e1 != 0 { | |
13 | err = e1 | |
14 | } | |
15 | return fd, err | |
16 | } | |
17 | ||
18 | func open() (pty, tty *os.File, err error) { | |
19 | fd, err := posixOpenpt(syscall.O_RDWR | syscall.O_CLOEXEC) | |
20 | if err != nil { | |
21 | return nil, nil, err | |
22 | } | |
23 | p := os.NewFile(uintptr(fd), "/dev/pts") | |
24 | // In case of error after this point, make sure we close the pts fd. | |
25 | defer func() { | |
26 | if err != nil { | |
27 | _ = p.Close() // Best effort. | |
28 | } | |
29 | }() | |
30 | ||
31 | sname, err := ptsname(p) | |
32 | if err != nil { | |
33 | return nil, nil, err | |
34 | } | |
35 | ||
36 | t, err := os.OpenFile("/dev/"+sname, os.O_RDWR, 0) | |
37 | if err != nil { | |
38 | return nil, nil, err | |
39 | } | |
40 | return p, t, nil | |
41 | } | |
42 | ||
43 | func isptmaster(fd uintptr) (bool, error) { | |
44 | err := ioctl(fd, syscall.TIOCPTMASTER, 0) | |
45 | return err == nil, err | |
46 | } | |
47 | ||
48 | var ( | |
49 | emptyFiodgnameArg fiodgnameArg | |
50 | ioctlFIODGNAME = _IOW('f', 120, unsafe.Sizeof(emptyFiodgnameArg)) | |
51 | ) | |
52 | ||
53 | func ptsname(f *os.File) (string, error) { | |
54 | master, err := isptmaster(f.Fd()) | |
55 | if err != nil { | |
56 | return "", err | |
57 | } | |
58 | if !master { | |
59 | return "", syscall.EINVAL | |
60 | } | |
61 | ||
62 | const n = _C_SPECNAMELEN + 1 | |
63 | var ( | |
64 | buf = make([]byte, n) | |
65 | arg = fiodgnameArg{Len: n, Buf: (*byte)(unsafe.Pointer(&buf[0]))} | |
66 | ) | |
67 | if err := ioctl(f.Fd(), ioctlFIODGNAME, uintptr(unsafe.Pointer(&arg))); err != nil { | |
68 | return "", err | |
69 | } | |
70 | ||
71 | for i, c := range buf { | |
72 | if c == 0 { | |
73 | return string(buf[:i]), nil | |
74 | } | |
75 | } | |
76 | return "", errors.New("FIODGNAME string not NUL-terminated") | |
77 | } |
0 | package pty | |
1 | ||
2 | import ( | |
3 | "os" | |
4 | "strconv" | |
5 | "syscall" | |
6 | "unsafe" | |
7 | ) | |
8 | ||
9 | func open() (pty, tty *os.File, err error) { | |
10 | p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0) | |
11 | if err != nil { | |
12 | return nil, nil, err | |
13 | } | |
14 | // In case of error after this point, make sure we close the ptmx fd. | |
15 | defer func() { | |
16 | if err != nil { | |
17 | _ = p.Close() // Best effort. | |
18 | } | |
19 | }() | |
20 | ||
21 | sname, err := ptsname(p) | |
22 | if err != nil { | |
23 | return nil, nil, err | |
24 | } | |
25 | ||
26 | if err := unlockpt(p); err != nil { | |
27 | return nil, nil, err | |
28 | } | |
29 | ||
30 | t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) | |
31 | if err != nil { | |
32 | return nil, nil, err | |
33 | } | |
34 | return p, t, nil | |
35 | } | |
36 | ||
37 | func ptsname(f *os.File) (string, error) { | |
38 | var n _C_uint | |
39 | err := ioctl(f.Fd(), syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))) | |
40 | if err != nil { | |
41 | return "", err | |
42 | } | |
43 | return "/dev/pts/" + strconv.Itoa(int(n)), nil | |
44 | } | |
45 | ||
46 | func unlockpt(f *os.File) error { | |
47 | var u _C_int | |
48 | // use TIOCSPTLCK with a pointer to zero to clear the lock | |
49 | return ioctl(f.Fd(), syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))) | |
50 | } |
0 | package pty | |
1 | ||
2 | import ( | |
3 | "os" | |
4 | "syscall" | |
5 | "unsafe" | |
6 | ) | |
7 | ||
8 | func open() (pty, tty *os.File, err error) { | |
9 | /* | |
10 | * from ptm(4): | |
11 | * The PTMGET command allocates a free pseudo terminal, changes its | |
12 | * ownership to the caller, revokes the access privileges for all previous | |
13 | * users, opens the file descriptors for the pty and tty devices and | |
14 | * returns them to the caller in struct ptmget. | |
15 | */ | |
16 | ||
17 | p, err := os.OpenFile("/dev/ptm", os.O_RDWR|syscall.O_CLOEXEC, 0) | |
18 | if err != nil { | |
19 | return nil, nil, err | |
20 | } | |
21 | defer p.Close() | |
22 | ||
23 | var ptm ptmget | |
24 | if err := ioctl(p.Fd(), uintptr(ioctl_PTMGET), uintptr(unsafe.Pointer(&ptm))); err != nil { | |
25 | return nil, nil, err | |
26 | } | |
27 | ||
28 | pty = os.NewFile(uintptr(ptm.Cfd), "/dev/ptm") | |
29 | tty = os.NewFile(uintptr(ptm.Sfd), "/dev/ptm") | |
30 | ||
31 | return pty, tty, nil | |
32 | } |
0 | package pty | |
1 | ||
2 | /* based on: | |
3 | http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libc/port/gen/pt.c | |
4 | */ | |
5 | ||
6 | import ( | |
7 | "errors" | |
8 | "golang.org/x/sys/unix" | |
9 | "os" | |
10 | "strconv" | |
11 | "syscall" | |
12 | "unsafe" | |
13 | ) | |
14 | ||
15 | const NODEV = ^uint64(0) | |
16 | ||
17 | func open() (pty, tty *os.File, err error) { | |
18 | masterfd, err := syscall.Open("/dev/ptmx", syscall.O_RDWR|unix.O_NOCTTY, 0) | |
19 | //masterfd, err := syscall.Open("/dev/ptmx", syscall.O_RDWR|syscall.O_CLOEXEC|unix.O_NOCTTY, 0) | |
20 | if err != nil { | |
21 | return nil, nil, err | |
22 | } | |
23 | p := os.NewFile(uintptr(masterfd), "/dev/ptmx") | |
24 | ||
25 | sname, err := ptsname(p) | |
26 | if err != nil { | |
27 | return nil, nil, err | |
28 | } | |
29 | ||
30 | err = grantpt(p) | |
31 | if err != nil { | |
32 | return nil, nil, err | |
33 | } | |
34 | ||
35 | err = unlockpt(p) | |
36 | if err != nil { | |
37 | return nil, nil, err | |
38 | } | |
39 | ||
40 | slavefd, err := syscall.Open(sname, os.O_RDWR|unix.O_NOCTTY, 0) | |
41 | if err != nil { | |
42 | return nil, nil, err | |
43 | } | |
44 | t := os.NewFile(uintptr(slavefd), sname) | |
45 | ||
46 | // pushing terminal driver STREAMS modules as per pts(7) | |
47 | for _, mod := range([]string{"ptem", "ldterm", "ttcompat"}) { | |
48 | err = streams_push(t, mod) | |
49 | if err != nil { | |
50 | return nil, nil, err | |
51 | } | |
52 | } | |
53 | ||
54 | return p, t, nil | |
55 | } | |
56 | ||
57 | func minor(x uint64) uint64 { | |
58 | return x & 0377 | |
59 | } | |
60 | ||
61 | func ptsdev(fd uintptr) uint64 { | |
62 | istr := strioctl{ISPTM, 0, 0, nil} | |
63 | err := ioctl(fd, I_STR, uintptr(unsafe.Pointer(&istr))) | |
64 | if err != nil { | |
65 | return NODEV | |
66 | } | |
67 | var status unix.Stat_t | |
68 | err = unix.Fstat(int(fd), &status) | |
69 | if err != nil { | |
70 | return NODEV | |
71 | } | |
72 | return uint64(minor(status.Rdev)) | |
73 | } | |
74 | ||
75 | func ptsname(f *os.File) (string, error) { | |
76 | dev := ptsdev(f.Fd()) | |
77 | if dev == NODEV { | |
78 | return "", errors.New("not a master pty") | |
79 | } | |
80 | fn := "/dev/pts/" + strconv.FormatInt(int64(dev), 10) | |
81 | // access(2) creates the slave device (if the pty exists) | |
82 | // F_OK == 0 (unistd.h) | |
83 | err := unix.Access(fn, 0) | |
84 | if err != nil { | |
85 | return "", err | |
86 | } | |
87 | return fn, nil | |
88 | } | |
89 | ||
90 | type pt_own struct { | |
91 | pto_ruid int32 | |
92 | pto_rgid int32 | |
93 | } | |
94 | ||
95 | func grantpt(f *os.File) error { | |
96 | if ptsdev(f.Fd()) == NODEV { | |
97 | return errors.New("not a master pty") | |
98 | } | |
99 | var pto pt_own | |
100 | pto.pto_ruid = int32(os.Getuid()) | |
101 | // XXX should first attempt to get gid of DEFAULT_TTY_GROUP="tty" | |
102 | pto.pto_rgid = int32(os.Getgid()) | |
103 | var istr strioctl | |
104 | istr.ic_cmd = OWNERPT | |
105 | istr.ic_timout = 0 | |
106 | istr.ic_len = int32(unsafe.Sizeof(istr)) | |
107 | istr.ic_dp = unsafe.Pointer(&pto) | |
108 | err := ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr))) | |
109 | if err != nil { | |
110 | return errors.New("access denied") | |
111 | } | |
112 | return nil | |
113 | } | |
114 | ||
115 | func unlockpt(f *os.File) error { | |
116 | istr := strioctl{UNLKPT, 0, 0, nil} | |
117 | return ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr))) | |
118 | } | |
119 | ||
120 | // push STREAMS modules if not already done so | |
121 | func streams_push(f *os.File, mod string) error { | |
122 | var err error | |
123 | buf := []byte(mod) | |
124 | // XXX I_FIND is not returning an error when the module | |
125 | // is already pushed even though truss reports a return | |
126 | // value of 1. A bug in the Go Solaris syscall interface? | |
127 | // XXX without this we are at risk of the issue | |
128 | // https://www.illumos.org/issues/9042 | |
129 | // but since we are not using libc or XPG4.2, we should not be | |
130 | // double-pushing modules | |
131 | ||
132 | err = ioctl(f.Fd(), I_FIND, uintptr(unsafe.Pointer(&buf[0]))) | |
133 | if err != nil { | |
134 | return nil | |
135 | } | |
136 | err = ioctl(f.Fd(), I_PUSH, uintptr(unsafe.Pointer(&buf[0]))) | |
137 | return err | |
138 | } |
0 | // +build !linux,!darwin,!freebsd,!dragonfly,!openbsd,!solaris | |
1 | ||
2 | package pty | |
3 | ||
4 | import ( | |
5 | "os" | |
6 | ) | |
7 | ||
8 | func open() (pty, tty *os.File, err error) { | |
9 | return nil, nil, ErrUnsupported | |
10 | } |
0 | // +build !windows | |
1 | ||
2 | package pty | |
3 | ||
4 | import ( | |
5 | "os" | |
6 | "os/exec" | |
7 | "syscall" | |
8 | ) | |
9 | ||
10 | // Start 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 | func Start(c *exec.Cmd) (pty *os.File, err error) { | |
14 | return StartWithSize(c, nil) | |
15 | } | |
16 | ||
17 | // StartWithSize assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout, | |
18 | // and c.Stderr, calls c.Start, and returns the File of the tty's | |
19 | // corresponding pty. | |
20 | // | |
21 | // This will resize the pty to the specified size before starting the command | |
22 | func StartWithSize(c *exec.Cmd, sz *Winsize) (pty *os.File, err error) { | |
23 | pty, tty, err := Open() | |
24 | if err != nil { | |
25 | return nil, err | |
26 | } | |
27 | defer tty.Close() | |
28 | if sz != nil { | |
29 | err = Setsize(pty, sz) | |
30 | if err != nil { | |
31 | pty.Close() | |
32 | return nil, err | |
33 | } | |
34 | } | |
35 | if c.Stdout == nil { | |
36 | c.Stdout = tty | |
37 | } | |
38 | if c.Stderr == nil { | |
39 | c.Stderr = tty | |
40 | } | |
41 | if c.Stdin == nil { | |
42 | c.Stdin = tty | |
43 | } | |
44 | if c.SysProcAttr == nil { | |
45 | c.SysProcAttr = &syscall.SysProcAttr{} | |
46 | } | |
47 | c.SysProcAttr.Setctty = true | |
48 | c.SysProcAttr.Setsid = true | |
49 | c.SysProcAttr.Ctty = int(tty.Fd()) | |
50 | err = c.Start() | |
51 | if err != nil { | |
52 | pty.Close() | |
53 | return nil, err | |
54 | } | |
55 | return pty, err | |
56 | } |
0 | // Package pty is a wrapper for github.com/creack/pty, which provides | |
1 | // functions for working with Unix terminals. | |
2 | // | |
3 | // This package is deprecated. Existing clients will continue to work, | |
4 | // but no further updates will happen here. New clients should use | |
5 | // github.com/creack/pty directly. | |
6 | package pty | |
7 | ||
8 | import ( | |
9 | "os" | |
10 | "os/exec" | |
11 | ||
12 | "github.com/creack/pty" | |
13 | newpty "github.com/creack/pty" | |
14 | ) | |
15 | ||
16 | // ErrUnsupported is returned if a function is not available on the | |
17 | // current platform. | |
18 | // | |
19 | // Deprecated; please use github.com/creack/pty instead. | |
20 | var ErrUnsupported = pty.ErrUnsupported | |
21 | ||
22 | // Winsize describes the terminal size. | |
23 | // | |
24 | // Deprecated; please use github.com/creack/pty instead. | |
25 | type Winsize = pty.Winsize | |
26 | ||
27 | // Getsize returns the number of rows (lines) and cols (positions in | |
28 | // each line) in terminal t. | |
29 | // | |
30 | // Deprecated; please use github.com/creack/pty instead. | |
31 | func Getsize(t *os.File) (rows, cols int, err error) { return pty.Getsize(t) } | |
32 | ||
33 | // GetsizeFull returns the full terminal size description. | |
34 | // | |
35 | // Deprecated; please use github.com/creack/pty instead. | |
36 | func GetsizeFull(t *os.File) (size *Winsize, err error) { | |
37 | return pty.GetsizeFull(t) | |
38 | } | |
39 | ||
40 | // InheritSize applies the terminal size of pty to tty. This should be | |
41 | // run in a signal handler for syscall.SIGWINCH to automatically | |
42 | // resize the tty when the pty receives a window size change | |
43 | // notification. | |
44 | // | |
45 | // Deprecated; please use github.com/creack/pty instead. | |
46 | func InheritSize(pty, tty *os.File) error { return newpty.InheritSize(pty, tty) } | |
47 | ||
48 | // Opens a pty and its corresponding tty. | |
49 | // | |
50 | // Deprecated; please use github.com/creack/pty instead. | |
51 | func Open() (pty, tty *os.File, err error) { return newpty.Open() } | |
52 | ||
53 | // Setsize resizes t to s. | |
54 | // | |
55 | // Deprecated; please use github.com/creack/pty instead. | |
56 | func Setsize(t *os.File, ws *Winsize) error { return pty.Setsize(t, ws) } | |
57 | ||
58 | // Start assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout, | |
59 | // and c.Stderr, calls c.Start, and returns the File of the tty's | |
60 | // corresponding pty. | |
61 | // | |
62 | // Deprecated; please use github.com/creack/pty instead. | |
63 | func Start(c *exec.Cmd) (pty *os.File, err error) { return newpty.Start(c) } | |
64 | ||
65 | // StartWithSize assigns a pseudo-terminal tty os.File to c.Stdin, | |
66 | // c.Stdout, and c.Stderr, calls c.Start, and returns the File of the | |
67 | // tty's corresponding pty. | |
68 | // | |
69 | // This will resize the pty to the specified size before starting the | |
70 | // command. | |
71 | // | |
72 | // Deprecated; please use github.com/creack/pty instead. | |
73 | func StartWithSize(c *exec.Cmd, sz *Winsize) (pty *os.File, err error) { | |
74 | return newpty.StartWithSize(c, sz) | |
75 | } |
0 | #!/usr/bin/env sh | |
1 | ||
2 | # Test script checking that all expected os/arch compile properly. | |
3 | # Does not actually test the logic, just the compilation so we make sure we don't break code depending on the lib. | |
4 | ||
5 | echo2() { | |
6 | echo $@ >&2 | |
7 | } | |
8 | ||
9 | trap end 0 | |
10 | end() { | |
11 | [ "$?" = 0 ] && echo2 "Pass." || (echo2 "Fail."; exit 1) | |
12 | } | |
13 | ||
14 | cross() { | |
15 | os=$1 | |
16 | shift | |
17 | echo2 "Build for $os." | |
18 | for arch in $@; do | |
19 | echo2 " - $os/$arch" | |
20 | GOOS=$os GOARCH=$arch go build | |
21 | done | |
22 | echo2 | |
23 | } | |
24 | ||
25 | set -e | |
26 | ||
27 | cross linux amd64 386 arm arm64 ppc64 ppc64le s390x mips mipsle mips64 mips64le | |
28 | cross darwin amd64 386 arm arm64 | |
29 | cross freebsd amd64 386 arm | |
30 | cross netbsd amd64 386 arm | |
31 | cross openbsd amd64 386 | |
32 | cross dragonfly amd64 | |
33 | cross solaris amd64 | |
34 | ||
35 | # Not expected to work but should still compile. | |
36 | cross windows amd64 386 arm | |
37 | ||
38 | # TODO: Fix compilation error on openbsd/arm. | |
39 | # TODO: Merge the solaris PR. | |
40 | ||
41 | # Some os/arch require a different compiler. Run in docker. | |
42 | if ! hash docker; then | |
43 | # If docker is not present, stop here. | |
44 | return | |
45 | fi | |
46 | ||
47 | echo2 "Build for linux." | |
48 | echo2 " - linux/riscv" | |
49 | docker build -t test -f Dockerfile.riscv . |
0 | // +build ignore | |
1 | ||
2 | package pty | |
3 | ||
4 | /* | |
5 | #define _KERNEL | |
6 | #include <sys/conf.h> | |
7 | #include <sys/param.h> | |
8 | #include <sys/filio.h> | |
9 | */ | |
10 | import "C" | |
11 | ||
12 | const ( | |
13 | _C_SPECNAMELEN = C.SPECNAMELEN /* max length of devicename */ | |
14 | ) | |
15 | ||
16 | type fiodgnameArg C.struct_fiodname_args |
0 | // +build ignore | |
1 | ||
2 | package pty | |
3 | ||
4 | /* | |
5 | #include <sys/param.h> | |
6 | #include <sys/filio.h> | |
7 | */ | |
8 | import "C" | |
9 | ||
10 | const ( | |
11 | _C_SPECNAMELEN = C.SPECNAMELEN /* max length of devicename */ | |
12 | ) | |
13 | ||
14 | type fiodgnameArg C.struct_fiodgname_arg |
0 | // +build ignore | |
1 | ||
2 | package pty | |
3 | ||
4 | /* | |
5 | #include <sys/time.h> | |
6 | #include <stdlib.h> | |
7 | #include <sys/tty.h> | |
8 | */ | |
9 | import "C" | |
10 | ||
11 | type ptmget C.struct_ptmget | |
12 | ||
13 | var ioctl_PTMGET = C.PTMGET |
0 | // +build !windows,!solaris | |
1 | ||
2 | package pty | |
3 | ||
4 | import ( | |
5 | "os" | |
6 | "syscall" | |
7 | "unsafe" | |
8 | ) | |
9 | ||
10 | // InheritSize applies the terminal size of pty to tty. This should be run | |
11 | // in a signal handler for syscall.SIGWINCH to automatically resize the tty when | |
12 | // the pty receives a window size change notification. | |
13 | func InheritSize(pty, tty *os.File) error { | |
14 | size, err := GetsizeFull(pty) | |
15 | if err != nil { | |
16 | return err | |
17 | } | |
18 | err = Setsize(tty, size) | |
19 | if err != nil { | |
20 | return err | |
21 | } | |
22 | return nil | |
23 | } | |
24 | ||
25 | // Setsize resizes t to s. | |
26 | func Setsize(t *os.File, ws *Winsize) error { | |
27 | return windowRectCall(ws, t.Fd(), syscall.TIOCSWINSZ) | |
28 | } | |
29 | ||
30 | // GetsizeFull returns the full terminal size description. | |
31 | func GetsizeFull(t *os.File) (size *Winsize, err error) { | |
32 | var ws Winsize | |
33 | err = windowRectCall(&ws, t.Fd(), syscall.TIOCGWINSZ) | |
34 | return &ws, err | |
35 | } | |
36 | ||
37 | // Getsize returns the number of rows (lines) and cols (positions | |
38 | // in each line) in terminal t. | |
39 | func Getsize(t *os.File) (rows, cols int, err error) { | |
40 | ws, err := GetsizeFull(t) | |
41 | return int(ws.Rows), int(ws.Cols), err | |
42 | } | |
43 | ||
44 | // Winsize describes the terminal size. | |
45 | type Winsize struct { | |
46 | Rows uint16 // ws_row: Number of rows (in cells) | |
47 | Cols uint16 // ws_col: Number of columns (in cells) | |
48 | X uint16 // ws_xpixel: Width in pixels | |
49 | Y uint16 // ws_ypixel: Height in pixels | |
50 | } | |
51 | ||
52 | func windowRectCall(ws *Winsize, fd, a2 uintptr) error { | |
53 | _, _, errno := syscall.Syscall( | |
54 | syscall.SYS_IOCTL, | |
55 | fd, | |
56 | a2, | |
57 | uintptr(unsafe.Pointer(ws)), | |
58 | ) | |
59 | if errno != 0 { | |
60 | return syscall.Errno(errno) | |
61 | } | |
62 | return nil | |
63 | } |
0 | // | |
1 | ||
2 | package pty | |
3 | ||
4 | import ( | |
5 | "os" | |
6 | "golang.org/x/sys/unix" | |
7 | ) | |
8 | ||
9 | const ( | |
10 | TIOCGWINSZ = 21608 // 'T' << 8 | 104 | |
11 | TIOCSWINSZ = 21607 // 'T' << 8 | 103 | |
12 | ) | |
13 | ||
14 | // Winsize describes the terminal size. | |
15 | type Winsize struct { | |
16 | Rows uint16 // ws_row: Number of rows (in cells) | |
17 | Cols uint16 // ws_col: Number of columns (in cells) | |
18 | X uint16 // ws_xpixel: Width in pixels | |
19 | Y uint16 // ws_ypixel: Height in pixels | |
20 | } | |
21 | ||
22 | // GetsizeFull returns the full terminal size description. | |
23 | func GetsizeFull(t *os.File) (size *Winsize, err error) { | |
24 | var wsz *unix.Winsize | |
25 | wsz, err = unix.IoctlGetWinsize(int(t.Fd()), TIOCGWINSZ) | |
26 | ||
27 | if err != nil { | |
28 | return nil, err | |
29 | } else { | |
30 | return &Winsize{wsz.Row, wsz.Col, wsz.Xpixel, wsz.Ypixel}, nil | |
31 | } | |
32 | } | |
33 | ||
34 | // Get Windows Size | |
35 | func Getsize(t *os.File) (rows, cols int, err error) { | |
36 | var wsz *unix.Winsize | |
37 | wsz, err = unix.IoctlGetWinsize(int(t.Fd()), TIOCGWINSZ) | |
38 | ||
39 | if err != nil { | |
40 | return 80, 25, err | |
41 | } else { | |
42 | return int(wsz.Row), int(wsz.Col), nil | |
43 | } | |
44 | } | |
45 | ||
46 | // Setsize resizes t to s. | |
47 | func Setsize(t *os.File, ws *Winsize) error { | |
48 | wsz := unix.Winsize{ws.Rows, ws.Cols, ws.X, ws.Y} | |
49 | return unix.IoctlSetWinsize(int(t.Fd()), TIOCSWINSZ, &wsz) | |
50 | } |
0 | // Created by cgo -godefs - DO NOT EDIT | |
1 | // cgo -godefs types.go | |
2 | ||
3 | package pty | |
4 | ||
5 | type ( | |
6 | _C_int int32 | |
7 | _C_uint uint32 | |
8 | ) |
0 | // Created by cgo -godefs - DO NOT EDIT | |
1 | // cgo -godefs types.go | |
2 | ||
3 | package pty | |
4 | ||
5 | type ( | |
6 | _C_int int32 | |
7 | _C_uint uint32 | |
8 | ) |
0 | // Created by cgo -godefs - DO NOT EDIT | |
1 | // cgo -godefs types.go | |
2 | ||
3 | package pty | |
4 | ||
5 | type ( | |
6 | _C_int int32 | |
7 | _C_uint uint32 | |
8 | ) |
0 | // Created by cgo -godefs - DO NOT EDIT | |
1 | // cgo -godefs types.go | |
2 | ||
3 | // +build arm64 | |
4 | ||
5 | package pty | |
6 | ||
7 | type ( | |
8 | _C_int int32 | |
9 | _C_uint uint32 | |
10 | ) |
0 | // Created by cgo -godefs - DO NOT EDIT | |
1 | // cgo -godefs types_dragonfly.go | |
2 | ||
3 | package pty | |
4 | ||
5 | const ( | |
6 | _C_SPECNAMELEN = 0x3f | |
7 | ) | |
8 | ||
9 | type fiodgnameArg struct { | |
10 | Name *byte | |
11 | Len uint32 | |
12 | Pad_cgo_0 [4]byte | |
13 | } |
0 | // Created by cgo -godefs - DO NOT EDIT | |
1 | // cgo -godefs types_freebsd.go | |
2 | ||
3 | package pty | |
4 | ||
5 | const ( | |
6 | _C_SPECNAMELEN = 0x3f | |
7 | ) | |
8 | ||
9 | type fiodgnameArg struct { | |
10 | Len int32 | |
11 | Buf *byte | |
12 | } |
0 | // Created by cgo -godefs - DO NOT EDIT | |
1 | // cgo -godefs types_freebsd.go | |
2 | ||
3 | package pty | |
4 | ||
5 | const ( | |
6 | _C_SPECNAMELEN = 0x3f | |
7 | ) | |
8 | ||
9 | type fiodgnameArg struct { | |
10 | Len int32 | |
11 | Pad_cgo_0 [4]byte | |
12 | Buf *byte | |
13 | } |
0 | // Created by cgo -godefs - DO NOT EDIT | |
1 | // cgo -godefs types_freebsd.go | |
2 | ||
3 | package pty | |
4 | ||
5 | const ( | |
6 | _C_SPECNAMELEN = 0x3f | |
7 | ) | |
8 | ||
9 | type fiodgnameArg struct { | |
10 | Len int32 | |
11 | Buf *byte | |
12 | } |
0 | // Created by cgo -godefs - DO NOT EDIT | |
1 | // cgo -godefs types.go | |
2 | ||
3 | // +build linux | |
4 | // +build mips mipsle mips64 mips64le | |
5 | ||
6 | package pty | |
7 | ||
8 | type ( | |
9 | _C_int int32 | |
10 | _C_uint uint32 | |
11 | ) |
0 | // Created by cgo -godefs - DO NOT EDIT | |
1 | // cgo -godefs types_openbsd.go | |
2 | ||
3 | package pty | |
4 | ||
5 | type ptmget struct { | |
6 | Cfd int32 | |
7 | Sfd int32 | |
8 | Cn [16]int8 | |
9 | Sn [16]int8 | |
10 | } | |
11 | ||
12 | var ioctl_PTMGET = 0x40287401 |
0 | // Created by cgo -godefs - DO NOT EDIT | |
1 | // cgo -godefs types_openbsd.go | |
2 | ||
3 | package pty | |
4 | ||
5 | type ptmget struct { | |
6 | Cfd int32 | |
7 | Sfd int32 | |
8 | Cn [16]int8 | |
9 | Sn [16]int8 | |
10 | } | |
11 | ||
12 | var ioctl_PTMGET = 0x40287401 |
0 | // +build ppc64 | |
1 | ||
2 | // Created by cgo -godefs - DO NOT EDIT | |
3 | // cgo -godefs types.go | |
4 | ||
5 | package pty | |
6 | ||
7 | type ( | |
8 | _C_int int32 | |
9 | _C_uint uint32 | |
10 | ) |
0 | // +build ppc64le | |
1 | ||
2 | // Created by cgo -godefs - DO NOT EDIT | |
3 | // cgo -godefs types.go | |
4 | ||
5 | package pty | |
6 | ||
7 | type ( | |
8 | _C_int int32 | |
9 | _C_uint uint32 | |
10 | ) |