@@ -7,18 +7,16 @@ import (
77 "log/slog"
88 "os/exec"
99 "strings"
10- "sync"
1110 "syscall"
11+
12+ "github.com/creack/pty"
1213)
1314
1415type ExecerCallback func (c * Command , line string , err error , done bool )
1516
1617type Execer struct {
1718 Command * Command
1819 Callback ExecerCallback
19-
20- mu sync.Mutex
21- proc * exec.Cmd
2220}
2321
2422func NewExecer (c * Command , cb ExecerCallback ) * Execer {
@@ -34,64 +32,50 @@ func (e *Execer) Start() {
3432 parts := strings .Fields (e .Command .Exec )
3533 cmd := exec .Command (parts [0 ], parts [1 :]... )
3634 cmd .Dir = e .Command .Cwd
37- cmd .SysProcAttr = & syscall.SysProcAttr {
38- Setpgid : true ,
39- }
40-
41- stdout , err := cmd .StdoutPipe ()
42- if err != nil {
43- e .Callback (e .Command , "" , err , true )
44- return
45- }
4635
47- stderr , err := cmd . StderrPipe ( )
36+ ptmx , err := pty . Start ( cmd )
4837 if err != nil {
4938 e .Callback (e .Command , "" , err , true )
5039 return
5140 }
5241
53- if err := cmd .Start (); err != nil {
54- e .Callback (e .Command , "" , err , true )
55- return
56- }
57-
5842 slog .Info ("Starting command" , "cmd" , strings .Join (cmd .Args , " " ), "PID" , cmd .Process .Pid )
5943
60- e .mu .Lock ()
61- e .proc = cmd
62- e .mu .Unlock ()
44+ e .Command . mu .Lock ()
45+ e .Command . proc = cmd
46+ e .Command . mu .Unlock ()
6347
6448 go func () {
65- r := io .MultiReader (stdout , stderr )
49+ r := io .MultiReader (ptmx )
6650 scanner := bufio .NewScanner (r )
6751
6852 for scanner .Scan () {
69- e .mu .Lock ()
53+ e .Command . mu .Lock ()
7054 e .Callback (e .Command , fmt .Sprintf ("%s" , scanner .Text ()), nil , false )
71- e .mu .Unlock ()
55+ e .Command . mu .Unlock ()
7256 }
7357 }()
7458 err = cmd .Wait ()
75- e .mu .Lock ()
59+ e .Command . mu .Lock ()
7660 e .Callback (e .Command , "" , err , true )
77- e .mu .Unlock ()
61+ e .Command . mu .Unlock ()
7862}
7963
8064func (e * Execer ) Stop () error {
81- e .mu .Lock ()
82- defer e .mu .Unlock ()
65+ e .Command . mu .Lock ()
66+ defer e .Command . mu .Unlock ()
8367
84- if e .proc != nil && e .proc .Process != nil {
85- slog .Debug ("killing proc" , "PID" , e .proc .Process .Pid )
86- pgid , err := syscall .Getpgid (e .proc .Process .Pid )
68+ if e .Command . proc != nil && e . Command .proc .Process != nil {
69+ slog .Debug ("killing proc" , "PID" , e .Command . proc .Process .Pid )
70+ pgid , err := syscall .Getpgid (e .Command . proc .Process .Pid )
8771 if err == nil {
8872 err = syscall .Kill (- pgid , syscall .SIGKILL )
89- slog .Debug ("killed process group" , "PID" , e .proc .Process .Pid , "error" , err )
73+ slog .Debug ("killed process group" , "PID" , e .Command . proc .Process .Pid , "error" , err )
9074 } else {
91- err = e .proc .Process .Kill ()
92- slog .Debug ("killed process" , "PID" , e .proc .Process .Pid , "error" , err )
75+ err = e .Command . proc .Process .Kill ()
76+ slog .Debug ("killed process" , "PID" , e .Command . proc .Process .Pid , "error" , err )
9377 }
94- e .proc = nil
78+ e .Command . proc = nil
9579 return err
9680 }
9781
0 commit comments