13
"plemya-x.ru/fakeroot"
14
"mvdan.cc/sh/v3/expand"
15
"mvdan.cc/sh/v3/interp"
18
// FakerootExecHandler was extracted from github.com/mvdan/sh/interp/handler.go
19
// and modified to run commands in a fakeroot environent.
20
func FakerootExecHandler(killTimeout time.Duration) interp.ExecHandlerFunc {
21
return func(ctx context.Context, args []string) error {
22
hc := interp.HandlerCtx(ctx)
23
path, err := interp.LookPathDir(hc.Dir, hc.Env, args[0])
25
fmt.Fprintln(hc.Stderr, err)
26
return interp.NewExitStatus(127)
38
err = fakeroot.Apply(cmd)
45
if done := ctx.Done(); done != nil {
49
if killTimeout <= 0 || runtime.GOOS == "windows" {
50
_ = cmd.Process.Signal(os.Kill)
54
// TODO: don't temporarily leak this goroutine
55
// if the program stops itself with the
58
time.Sleep(killTimeout)
59
_ = cmd.Process.Signal(os.Kill)
61
_ = cmd.Process.Signal(os.Interrupt)
68
switch x := err.(type) {
70
// started, but errored - default to 1 if OS
71
// doesn't have exit statuses
72
if status, ok := x.Sys().(syscall.WaitStatus); ok {
73
if status.Signaled() {
77
return interp.NewExitStatus(uint8(128 + status.Signal()))
79
return interp.NewExitStatus(uint8(status.ExitStatus()))
81
return interp.NewExitStatus(1)
84
fmt.Fprintf(hc.Stderr, "%v\n", err)
85
return interp.NewExitStatus(127)
92
// execEnv was extracted from github.com/mvdan/sh/interp/vars.go
93
func execEnv(env expand.Environ) []string {
94
list := make([]string, 0, 64)
95
env.Each(func(name string, vr expand.Variable) bool {
97
// If a variable is set globally but unset in the
98
// runner, we need to ensure it's not part of the final
99
// list. Seems like zeroing the element is enough.
100
// This is a linear search, but this scenario should be
101
// rare, and the number of variables shouldn't be large.
102
for i, kv := range list {
103
if strings.HasPrefix(kv, name+"=") {
108
if vr.Exported && vr.Kind == expand.String {
109
list = append(list, name+"="+vr.String())