-
Notifications
You must be signed in to change notification settings - Fork 5
/
localexec_unix.go
109 lines (94 loc) · 2.3 KB
/
localexec_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
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
//go:build !windows
// +build !windows
package wsep
import (
"bytes"
"context"
"io"
"io/ioutil"
"os"
"os/exec"
"syscall"
"github.com/creack/pty"
"golang.org/x/xerrors"
)
type localProcess struct {
// tty may be nil
tty *os.File
cmd *exec.Cmd
stdin io.WriteCloser
stdout io.Reader
stderr io.Reader
}
func (l *localProcess) Resize(_ context.Context, rows, cols uint16) error {
if l.tty == nil {
return nil
}
return pty.Setsize(l.tty, &pty.Winsize{
Rows: rows,
Cols: cols,
})
}
// Start executes the given command locally
func (l LocalExecer) Start(ctx context.Context, c Command) (Process, error) {
var (
process localProcess
err error
)
process.cmd = exec.CommandContext(ctx, c.Command, c.Args...)
process.cmd.Env = append(os.Environ(), c.Env...)
process.cmd.Dir = c.WorkingDir
if c.GID != 0 || c.UID != 0 {
process.cmd.SysProcAttr = &syscall.SysProcAttr{
Credential: &syscall.Credential{},
}
}
if c.GID != 0 {
process.cmd.SysProcAttr.Credential.Gid = c.GID
}
if c.UID != 0 {
process.cmd.SysProcAttr.Credential.Uid = c.UID
}
if c.TTY {
// This special WSEP_TTY variable helps debug unexpected TTYs.
process.cmd.Env = append(process.cmd.Env, "WSEP_TTY=true")
process.tty, err = pty.StartWithSize(process.cmd, &pty.Winsize{
Rows: c.Rows,
Cols: c.Cols,
})
if err != nil {
return nil, xerrors.Errorf("start command with pty: %w", err)
}
process.stdout = process.tty
process.stderr = ioutil.NopCloser(bytes.NewReader(nil))
process.stdin = process.tty
} else {
if c.Stdin {
process.stdin, err = process.cmd.StdinPipe()
if err != nil {
return nil, xerrors.Errorf("create pipe: %w", err)
}
} else {
process.stdin = disabledStdinWriter{}
}
process.stdout, err = process.cmd.StdoutPipe()
if err != nil {
return nil, xerrors.Errorf("create pipe: %w", err)
}
process.stderr, err = process.cmd.StderrPipe()
if err != nil {
return nil, xerrors.Errorf("create pipe: %w", err)
}
err = process.cmd.Start()
if err != nil {
return nil, xerrors.Errorf("start command: %w", err)
}
}
if l.ChildProcessPriority != nil {
pid := process.cmd.Process.Pid
niceness := *l.ChildProcessPriority
// the environment may block the niceness syscall
_ = syscall.Setpriority(syscall.PRIO_PROCESS, pid, niceness)
}
return &process, nil
}