github.com/kyleu/dbaudit@v0.0.2-0.20240321155047-ff2f2c940496/app/util/process.go (about)

     1  // Package util - Content managed by Project Forge, see [projectforge.md] for details.
     2  package util
     3  
     4  import (
     5  	"bytes"
     6  	"io"
     7  	"os"
     8  	"os/exec"
     9  	"strings"
    10  
    11  	"github.com/buildkite/shellwords"
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  func StartProcess(cmd string, path string, in io.Reader, out io.Writer, er io.Writer, env ...string) (*exec.Cmd, error) {
    16  	args, err := shellwords.Split(cmd)
    17  	if err != nil {
    18  		return nil, err
    19  	}
    20  	if len(args) == 0 {
    21  		return nil, errors.New("no arguments provided")
    22  	}
    23  	firstArg := args[0]
    24  
    25  	if !strings.Contains(firstArg, "/") && !strings.Contains(firstArg, "\\") {
    26  		firstArg, err = exec.LookPath(firstArg)
    27  		if err != nil {
    28  			return nil, errors.Wrapf(err, "unable to look up cmd [%s]", firstArg)
    29  		}
    30  	}
    31  
    32  	if in == nil {
    33  		in = os.Stdin
    34  	}
    35  	if out == nil {
    36  		out = os.Stdout
    37  	}
    38  	if er == nil {
    39  		er = os.Stderr
    40  	}
    41  
    42  	c := &exec.Cmd{Path: firstArg, Args: args, Env: env, Stdin: in, Stdout: out, Stderr: er, Dir: path}
    43  	err = c.Start()
    44  	if err != nil {
    45  		return nil, errors.Wrapf(err, "unable to start [%s] (%T)", cmd, err)
    46  	}
    47  	return c, nil
    48  }
    49  
    50  func RunProcess(cmd string, path string, in io.Reader, out io.Writer, er io.Writer, env ...string) (int, error) {
    51  	c, err := StartProcess(cmd, path, in, out, er, env...)
    52  	if err != nil {
    53  		return -1, err
    54  	}
    55  	err = c.Wait()
    56  	if err != nil {
    57  		ec, ok := err.(*exec.ExitError) //nolint:errorlint
    58  		if ok {
    59  			return ec.ExitCode(), nil
    60  		}
    61  		return -1, errors.Wrapf(err, "unable to run [%s] (%T)", cmd, err)
    62  	}
    63  	return 0, nil
    64  }
    65  
    66  func RunProcessSimple(cmd string, path string) (int, string, error) {
    67  	var buf bytes.Buffer
    68  	ec, err := RunProcess(cmd, path, nil, &buf, &buf)
    69  	if err != nil {
    70  		return -1, "", err
    71  	}
    72  	return ec, buf.String(), nil
    73  }