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 Control(f func(fd uintptr)) error
44}
45
46// Cmd is a command that can be started attached to a pseudo-terminal.
47// This is similar to the API of exec.Cmd. The main difference is that
48// the command is started attached to a pseudo-terminal.
49// This is required as we cannot use exec.Cmd directly on Windows due to
50// limitation of starting a process attached to a pseudo-terminal.
51// See: https://github.com/golang/go/issues/62708
52type Cmd struct {
53 ctx context.Context
54 pty Pty
55 sys interface{}
56
57 // Path is the path of the command to run.
58 Path string
59
60 // Args holds command line arguments, including the command as Args[0].
61 Args []string
62
63 // Env specifies the environment of the process.
64 // If Env is nil, the new process uses the current process's environment.
65 Env []string
66
67 // Dir specifies the working directory of the command.
68 // If Dir is the empty string, the current directory is used.
69 Dir string
70
71 // SysProcAttr holds optional, operating system-specific attributes.
72 SysProcAttr *syscall.SysProcAttr
73
74 // Process is the underlying process, once started.
75 Process *os.Process
76
77 // ProcessState contains information about an exited process.
78 // If the process was started successfully, Wait or Run will populate this
79 // field when the command completes.
80 ProcessState *os.ProcessState
81
82 // Cancel is called when the command is canceled.
83 Cancel func()
84}
85
86// Start starts the specified command attached to the pseudo-terminal.
87func (c *Cmd) Start() error {
88 return c.start()
89}
90
91// Wait waits for the command to exit.
92func (c *Cmd) Wait() error {
93 return c.wait()
94}
95
96// Run runs the command and waits for it to complete.
97func (c *Cmd) Run() error {
98 if err := c.Start(); err != nil {
99 return err
100 }
101 return c.Wait()
102}