diff options
| author | Ophestra Umiker <cat@ophivana.moe> | 2024-10-07 15:37:52 +0900 |
|---|---|---|
| committer | Ophestra Umiker <cat@ophivana.moe> | 2024-10-07 15:37:52 +0900 |
| commit | 85407dd3c09ffbc4c102baa90249ded685badd12 (patch) | |
| tree | b4b3cabd25fe317a70c0ea0fcdab555e89f75a47 /helper/direct.go | |
| parent | 6a2802cf309fb9758756c56ef05c9354d9cb9003 (diff) | |
helper: helper.Helper interface
For upcoming bwrap implementation of helper.Helper
Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
Diffstat (limited to 'helper/direct.go')
| -rw-r--r-- | helper/direct.go | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/helper/direct.go b/helper/direct.go new file mode 100644 index 00000000..24f9e75d --- /dev/null +++ b/helper/direct.go @@ -0,0 +1,93 @@ +package helper + +import ( + "errors" + "io" + "os/exec" + "sync" +) + +// direct wraps *exec.Cmd and manages status and args fd. +// Args is always 3 and status if set is always 4. +type direct struct { + // helper pipes + // cannot be nil + p *pipes + + // returns an array of arguments passed directly + // to the helper process + argF func(argsFD, statFD int) []string + + lock sync.RWMutex + *exec.Cmd +} + +func (h *direct) StartNotify(ready chan error) error { + h.lock.Lock() + defer h.lock.Unlock() + + // Check for doubled Start calls before we defer failure cleanup. If the prior + // call to Start succeeded, we don't want to spuriously close its pipes. + if h.Cmd.Process != nil { + return errors.New("exec: already started") + } + + h.p.ready = ready + if argsFD, statFD, err := h.p.prepareCmd(h.Cmd); err != nil { + return err + } else { + h.Cmd.Args = append(h.Cmd.Args, h.argF(argsFD, statFD)...) + } + + if ready != nil { + h.Cmd.Env = append(h.Cmd.Env, FortifyHelper+"=1", FortifyStatus+"=1") + } else { + h.Cmd.Env = append(h.Cmd.Env, FortifyHelper+"=1", FortifyStatus+"=0") + } + + if err := h.Cmd.Start(); err != nil { + return err + } + if err := h.p.readyWriteArgs(); err != nil { + return err + } + + return nil +} + +func (h *direct) Wait() error { + h.lock.RLock() + defer h.lock.RUnlock() + + if h.Cmd.Process == nil { + return errors.New("exec: not started") + } + if h.Cmd.ProcessState != nil { + return errors.New("exec: Wait was already called") + } + + defer h.p.mustClosePipes() + return h.Cmd.Wait() +} + +func (h *direct) Close() error { + return h.p.closeStatus() +} + +func (h *direct) Start() error { + return h.StartNotify(nil) +} + +func (h *direct) Unwrap() *exec.Cmd { + return h.Cmd +} + +// New initialises a new direct Helper instance with wt as the null-terminated argument writer. +// Function argF returns an array of arguments passed directly to the child process. +func New(wt io.WriterTo, name string, argF func(argsFD, statFD int) []string) Helper { + if wt == nil { + panic("attempted to create helper with invalid argument writer") + } + + return &direct{p: &pipes{args: wt}, argF: argF, Cmd: execCommand(name)} +} |
