You've already forked agentic-coding-workflow
TTY
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
//go:build !windows
|
||||
|
||||
package terminal
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
|
||||
"github.com/creack/pty"
|
||||
|
||||
procgrp "github.com/yan1h/agent-coding-workflow/internal/infra/proc"
|
||||
)
|
||||
|
||||
// startPTY 在真 PTY 中拉起 shell(Unix)。
|
||||
//
|
||||
// 关于进程组:pty.StartWithSize 内部会设置 SysProcAttr.Setsid,使 shell 成为新
|
||||
// 会话的首进程,其进程组 pgid == pid。因此这里**不**调用 group.Prepare(它设的
|
||||
// Setpgid 与 Setsid 同时设置在 Go exec 下是非法/冗余的);group.Adopt 直接记录
|
||||
// pgid = cmd.Process.Pid,TerminateGroup 向 -pgid 发信号即可整树终止 shell 及其
|
||||
// 派生的全部子孙进程。
|
||||
func startPTY(shell string, env []string, rows, cols uint16) (*ptySession, error) {
|
||||
cmd := exec.Command(shell)
|
||||
cmd.Env = env
|
||||
|
||||
ptmx, err := pty.StartWithSize(cmd, &pty.Winsize{Rows: rows, Cols: cols})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
group := procgrp.NewGroup()
|
||||
if err := group.Adopt(cmd); err != nil {
|
||||
_ = ptmx.Close()
|
||||
if cmd.Process != nil {
|
||||
_ = cmd.Process.Kill()
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ptySession{
|
||||
cmd: cmd,
|
||||
group: group,
|
||||
rw: ptmx,
|
||||
resizeFn: func(r, c uint16) error {
|
||||
return pty.Setsize(ptmx, &pty.Winsize{Rows: r, Cols: c})
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user