145 lines
2.8 KiB
Go
145 lines
2.8 KiB
Go
// Run process in host
|
|
package host
|
|
|
|
import (
|
|
"io"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"syscall"
|
|
|
|
goexec "sirherobrine23.com.br/go-bds/exec/v2/process"
|
|
)
|
|
|
|
var _ = goexec.RegisterProcess(NewProc, "host", "os")
|
|
|
|
func NewProc() (*Os, error) {
|
|
return &Os{}, nil
|
|
}
|
|
|
|
type Os struct {
|
|
SysProc *syscall.SysProcAttr
|
|
Rootfs string
|
|
|
|
osProc *exec.Cmd
|
|
|
|
stdin io.Reader
|
|
stdout, stderr io.Writer
|
|
}
|
|
|
|
func (w *Os) Kill() error {
|
|
if w.osProc == nil {
|
|
return goexec.ErrNoProcess
|
|
}
|
|
return w.osProc.Process.Kill()
|
|
}
|
|
|
|
func (w *Os) Close() error {
|
|
if w.osProc != nil {
|
|
return w.Signal(os.Interrupt)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (w *Os) Signal(sig os.Signal) error {
|
|
return w.osProc.Process.Signal(sig)
|
|
}
|
|
|
|
func (os *Os) Wait() error {
|
|
switch {
|
|
case os.osProc != nil && os.osProc.ProcessState != nil:
|
|
if !os.osProc.ProcessState.Success() {
|
|
return &exec.ExitError{ProcessState: os.osProc.ProcessState}
|
|
}
|
|
return nil
|
|
case os.osProc != nil && os.osProc.Process != nil:
|
|
return os.osProc.Wait()
|
|
default:
|
|
return goexec.ErrNoProcess
|
|
}
|
|
}
|
|
|
|
func (os *Os) ExitCode() (int, error) {
|
|
switch {
|
|
case os.osProc != nil && os.osProc.ProcessState != nil:
|
|
return os.osProc.ProcessState.ExitCode(), nil
|
|
case os.osProc != nil && os.osProc.Process != nil:
|
|
state, err := os.osProc.Process.Wait()
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
return state.ExitCode(), nil
|
|
default:
|
|
return -1, goexec.ErrNoProcess
|
|
}
|
|
}
|
|
|
|
func (w *Os) AttachStdin(r io.Reader) error {
|
|
w.stdin = r
|
|
return nil
|
|
}
|
|
func (w *Os) AttachStdout(w2 io.Writer) error {
|
|
w.stdout = w2
|
|
return nil
|
|
}
|
|
func (w *Os) AttachStderr(w2 io.Writer) error {
|
|
w.stderr = w2
|
|
return nil
|
|
}
|
|
|
|
func (w *Os) Start(options *goexec.Exec) error {
|
|
w.osProc = exec.Command(options.Arguments[0], options.Arguments[1:]...)
|
|
if options.Context != nil {
|
|
w.osProc = exec.CommandContext(options.Context, options.Arguments[0], options.Arguments[1:]...)
|
|
// replace to SIGINT Cancel
|
|
w.osProc.Cancel = func() error {
|
|
return w.osProc.Process.Signal(os.Interrupt)
|
|
}
|
|
}
|
|
w.osProc.SysProcAttr = w.SysProc
|
|
|
|
if err := w.osProc.Err; err != nil {
|
|
return err
|
|
}
|
|
|
|
w.osProc.Env = append(w.osProc.Env, options.Environment.ToSlice()...)
|
|
if options.Cwd != "" {
|
|
w.osProc.Dir = options.Cwd
|
|
}
|
|
|
|
// Append rootfs to dir start
|
|
if w.Rootfs != "" {
|
|
w.osProc.Dir = filepath.Join(w.Rootfs, filepath.Clean(w.osProc.Dir))
|
|
}
|
|
|
|
// attach stdin
|
|
switch {
|
|
case options.Stdin != nil:
|
|
w.osProc.Stdin = options.Stdin
|
|
case w.stdin != nil:
|
|
w.osProc.Stdin = w.stdin
|
|
}
|
|
|
|
// attach stdout
|
|
switch {
|
|
case options.Stdout != nil:
|
|
w.osProc.Stdout = options.Stdout
|
|
case w.stdout != nil:
|
|
w.osProc.Stdout = w.stdout
|
|
}
|
|
|
|
// attach stderr
|
|
switch {
|
|
case options.Stderr != nil:
|
|
w.osProc.Stderr = options.Stderr
|
|
case w.stderr != nil:
|
|
w.osProc.Stderr = w.stderr
|
|
}
|
|
|
|
// Start process
|
|
if err := w.osProc.Start(); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|