1package pty
2
3import (
4 "context"
5 "errors"
6 "io"
7 "os"
8 "syscall"
9)
10
11var (
12 // ErrInvalidCommand is returned when the command is invalid.
13 ErrInvalidCommand = errors.New("pty: invalid command")
14)
15
16// New returns a new pseudo-terminal.
17func New() (Pty, error) {
18 return newPty()
19}
20
21// Pty is a pseudo-terminal interface.
22type Pty interface {
23 io.ReadWriteCloser
24
25 // Name returns the name of the pseudo-terminal.
26 // On Windows, this will always be "windows-pty".
27 // On Unix, this will return the name of the slave end of the
28 // pseudo-terminal TTY.
29 Name() string
30
31 // Command returns a command that can be used to start a process
32 // attached to the pseudo-terminal.
33 Command(name string, args ...string) *Cmd
34
35 // CommandContext returns a command that can be used to start a process
36 // attached to the pseudo-terminal.
37 CommandContext(ctx context.Context, name string, args ...string) *Cmd
38
39 // Resize resizes the pseudo-terminal.
40 Resize(rows, cols int) error
41
42 // Control access to the underlying file descriptor in a blocking manner.
43 // Not implemented on Windows.
44 Control(f func(fd uintptr)) error
45}
46
47// Cmd is a command that can be started attached to a pseudo-terminal.
48// This is similar to the API of exec.Cmd. The main difference is that
49// the command is started attached to a pseudo-terminal.
50// This is required as we cannot use exec.Cmd directly on Windows due to
51// limitation of starting a process attached to a pseudo-terminal.
52// See: https://github.com/golang/go/issues/62708
53type Cmd struct {
54 ctx context.Context
55 pty Pty
56 sys interface{}
57
58 // Path is the path of the command to run.
59 Path string
60
61 // Args holds command line arguments, including the command as Args[0].
62 Args []string
63
64 // Env specifies the environment of the process.
65 // If Env is nil, the new process uses the current process's environment.
66 Env []string
67
68 // Dir specifies the working directory of the command.
69 // If Dir is the empty string, the current directory is used.
70 Dir string
71
72 // SysProcAttr holds optional, operating system-specific attributes.
73 SysProcAttr *syscall.SysProcAttr
74
75 // Process is the underlying process, once started.
76 Process *os.Process
77
78 // ProcessState contains information about an exited process.
79 // If the process was started successfully, Wait or Run will populate this
80 // field when the command completes.
81 ProcessState *os.ProcessState
82
83 // Cancel is called when the command is canceled.
84 Cancel func() error
85}
86
87// Start starts the specified command attached to the pseudo-terminal.
88func (c *Cmd) Start() error {
89 return c.start()
90}
91
92// Wait waits for the command to exit.
93func (c *Cmd) Wait() error {
94 return c.wait()
95}
96
97// Run runs the command and waits for it to complete.
98func (c *Cmd) Run() error {
99 if err := c.Start(); err != nil {
100 return err
101 }
102 return c.Wait()
103}