/
command_unix.go
62 lines (53 loc) · 1.14 KB
/
command_unix.go
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
//go:build !windows
package command
import (
"os"
"os/exec"
"syscall"
"github.com/pkg/errors"
"github.com/pkg/term/termios"
"golang.org/x/sys/unix"
)
func setSysProcAttrCtty(cmd *exec.Cmd) {
if cmd.SysProcAttr == nil {
cmd.SysProcAttr = &syscall.SysProcAttr{}
}
cmd.SysProcAttr.Setsid = true
cmd.SysProcAttr.Setctty = true
}
func disableEcho(fd uintptr) error {
attr, err := termios.Tcgetattr(fd)
if err != nil {
return errors.Wrap(err, "failed to get tty attr")
}
attr.Lflag &^= unix.ECHO
err = termios.Tcsetattr(fd, termios.TCSANOW, attr)
return errors.Wrap(err, "failed to set tty attr")
}
func dup(fd uintptr) (uintptr, error) {
dupFd, err := syscall.Dup(int(fd))
if err != nil {
return 0, err
}
return uintptr(dupFd), nil
}
func closeOnExec(fd uintptr) {
syscall.CloseOnExec(int(fd))
}
func signalPgid(pid int, sig os.Signal) error {
pgid, err := syscall.Getpgid(pid)
if err != nil {
return err
}
s, ok := sig.(syscall.Signal)
if !ok {
return errors.New("os: unsupported signal type")
}
if e := syscall.Kill(-pgid, s); e != nil {
if e == syscall.ESRCH {
return os.ErrProcessDone
}
return e
}
return nil
}