6
1
mirror of https://git.mills.io/saltyim/saltyim.git synced 2024-06-30 18:51:03 +00:00
prologic-saltyim/internal/exec/cmd.go
mlctrez 969a263d06 support for contacts, multiple chat threads, and persistence (#77)
Co-authored-by: James Mills <prologic@shortcircuit.net.au>
Co-authored-by: James Mills <james@mills.io>
Co-authored-by: mlctrez <mlctrez@gmail.com>
Reviewed-on: https://git.mills.io/saltyim/saltyim/pulls/77
Co-authored-by: mlctrez <mlctrez@noreply@mills.io>
Co-committed-by: mlctrez <mlctrez@noreply@mills.io>
2022-03-28 21:49:01 +00:00

49 lines
1.1 KiB
Go

package exec
import (
"context"
"io"
"os/exec"
"syscall"
"time"
)
const (
DefaultRunCmdTimeout = time.Second * 3
)
// RunCmd executes the given command and arguments and stdin and ensures the
// command takes no longer than the timeout before the command is terminated.
func RunCmd(timeout time.Duration, env []string, command string, stdin io.Reader, args ...string) (string, error) {
var (
ctx context.Context
cancel context.CancelFunc
)
if timeout > 0 {
ctx, cancel = context.WithTimeout(context.Background(), timeout)
} else {
ctx, cancel = context.WithCancel(context.Background())
}
defer cancel()
cmd := exec.CommandContext(ctx, command, args...)
cmd.Env = append(cmd.Env, env...)
cmd.Stdin = stdin
out, err := cmd.CombinedOutput()
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
if ws, ok := exitError.Sys().(syscall.WaitStatus); ok && ws.Signal() == syscall.SIGKILL {
err = &ErrCommandKilled{Err: err, Signal: ws.Signal()}
} else {
err = &ErrCommandFailed{Err: err, Status: exitError.ExitCode()}
}
}
return string(out), err
}
return string(out), nil
}