1# pty
2
3Pty is a Go package for using unix pseudo-terminals.
4
5## Install
6
7```sh
8go get github.com/creack/pty
9```
10
11## Examples
12
13Note 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.
14
15### Command
16
17```go
18package main
19
20import (
21	"io"
22	"os"
23	"os/exec"
24
25	"github.com/creack/pty"
26)
27
28func main() {
29	c := exec.Command("grep", "--color=auto", "bar")
30	f, err := pty.Start(c)
31	if err != nil {
32		panic(err)
33	}
34
35	go func() {
36		f.Write([]byte("foo\n"))
37		f.Write([]byte("bar\n"))
38		f.Write([]byte("baz\n"))
39		f.Write([]byte{4}) // EOT
40	}()
41	io.Copy(os.Stdout, f)
42}
43```
44
45### Shell
46
47```go
48package main
49
50import (
51        "io"
52        "log"
53        "os"
54        "os/exec"
55        "os/signal"
56        "syscall"
57
58        "github.com/creack/pty"
59        "golang.org/x/term"
60)
61
62func test() error {
63        // Create arbitrary command.
64        c := exec.Command("bash")
65
66        // Start the command with a pty.
67        ptmx, err := pty.Start(c)
68        if err != nil {
69                return err
70        }
71        // Make sure to close the pty at the end.
72        defer func() { _ = ptmx.Close() }() // Best effort.
73
74        // Handle pty size.
75        ch := make(chan os.Signal, 1)
76        signal.Notify(ch, syscall.SIGWINCH)
77        go func() {
78                for range ch {
79                        if err := pty.InheritSize(os.Stdin, ptmx); err != nil {
80                                log.Printf("error resizing pty: %s", err)
81                        }
82                }
83        }()
84        ch <- syscall.SIGWINCH // Initial resize.
85        defer func() { signal.Stop(ch); close(ch) }() // Cleanup signals when done.
86
87        // Set stdin in raw mode.
88        oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
89        if err != nil {
90                panic(err)
91        }
92        defer func() { _ = term.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort.
93
94        // Copy stdin to the pty and the pty to stdout.
95        // NOTE: The goroutine will keep reading until the next keystroke before returning.
96        go func() { _, _ = io.Copy(ptmx, os.Stdin) }()
97        _, _ = io.Copy(os.Stdout, ptmx)
98
99        return nil
100}
101
102func main() {
103        if err := test(); err != nil {
104                log.Fatal(err)
105        }
106}
107```
108