-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathshell_wrapper.go
More file actions
121 lines (92 loc) · 1.87 KB
/
shell_wrapper.go
File metadata and controls
121 lines (92 loc) · 1.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package main
import (
"os"
"os/exec"
"syscall"
pty "github.com/creack/pty"
)
type ShellWrapper struct {
command []string
cmd *exec.Cmd
// we output stdout and stderr to this channel
outputChannel chan interface{}
// we get notified when to quit
quitChannel chan bool
pty *os.File
}
type ShellExit struct {
ExitCode int
}
func NewShellWrapper(command []string) *ShellWrapper {
return &ShellWrapper{
command: command,
outputChannel: make(chan interface{}),
quitChannel: make(chan bool),
}
}
func (s *ShellWrapper) Start() error {
// Implement the logic to start the shell command
// This is a placeholder implementation
c := exec.Command(s.command[0], s.command[1:]...)
s.cmd = c
attrs := syscall.SysProcAttr{
// Setpgid: true,
Setsid: true,
Setctty: true,
}
f, err := pty.StartWithAttrs(c, nil, &attrs)
s.pty = f
if err != nil {
return err
}
stdoutChannel := make(chan []byte)
go func() {
for {
buf := make([]byte, 1024)
n, err := f.Read(buf)
if err != nil {
break
}
stdoutChannel <- buf[:n]
}
}()
go func() {
err := c.Wait()
if err != nil {
Error("Error waiting for command: %v", err)
}
Debug("Command exited with code: %d", c.ProcessState.ExitCode())
s.outputChannel <- ShellExit{
ExitCode: c.ProcessState.ExitCode(),
}
}()
go func() {
defer c.Process.Kill()
for {
select {
case data := <-stdoutChannel:
s.outputChannel <- data
case <-s.quitChannel:
return
}
}
}()
return nil
}
func (s *ShellWrapper) Stop() {
close(s.quitChannel)
}
func (s *ShellWrapper) PushInput(input []byte) {
if s.pty != nil {
s.pty.Write(input)
}
}
func (s *ShellWrapper) ResizeTerminal(width, height uint32) {
Debug("Resizing terminal to %d x %d\n", width, height)
if s.pty != nil {
pty.Setsize(s.pty, &pty.Winsize{
Cols: uint16(width),
Rows: uint16(height),
})
}
}