Files
slicer-service/internal/cli/cli.go
2026-03-21 15:35:50 +02:00

105 lines
2.2 KiB
Go

package cli
import (
"context"
"errors"
"io"
"os/exec"
"regexp"
"strings"
)
var re = regexp.MustCompile(`\w|\%|^(\+|,|\.|:|\/|\\|=|_|-|[a-z]|[A-Z]|[0-9]|\s)+$`)
func validateCliArgument(arg string) bool {
return re.Match([]byte(arg))
}
func validateCliArguments(args []string) bool {
for _, p := range args {
if !validateCliArgument(p) {
return false
}
}
return true
}
func execNoCheck(ctx context.Context, command string, args []string) (string, string, error) {
cmd := exec.CommandContext(ctx, command, args...)
cmdStr := cmd.String()
pStdout, err := cmd.StdoutPipe()
if err != nil {
return "", cmdStr, err
}
pStderr, err := cmd.StderrPipe()
if err != nil {
return "", cmdStr, err
}
err = cmd.Start()
if err != nil {
return "", cmdStr, err
}
stdout, _ := io.ReadAll(pStdout)
stderr, _ := io.ReadAll(pStderr)
err = cmd.Wait()
if err != nil {
return "", cmdStr, errors.New(err.Error() + " | " + string(stderr) + " | " + string(stdout))
}
return string(stdout), cmdStr, nil
}
type Pipe struct {
Command string
Args []string
}
func (p *Pipe) IsSanatory() bool {
return validateCliArguments(p.Args) && validateCliArgument(p.Command)
}
func (p *Pipe) Execute(ctx context.Context) (string, string, error) {
if !p.IsSanatory() {
return "", "", errors.New("failed to execute cli command: " + p.Command + " " + strings.Join(p.Args, " ") + " some arguments are not allowed")
} else {
return execNoCheck(ctx, p.Command, p.Args)
}
}
func ExecuteCLIPipeLine(ctx context.Context, pipes []Pipe) (string, string, error) {
pipeLen := len(pipes)
if pipeLen == 0 {
return "", "", errors.New("failed to execute cli command: no pipes provided")
}
argLen := 0
for _, p := range pipes {
if !p.IsSanatory() {
return "", "", errors.New("failed to execute cli command: " + p.Command + " " + strings.Join(p.Args, " ") + " some arguments are not allowed")
}
argLen += len(p.Args) + 1
}
command := "/bin/sh"
var args []string = []string{}
args = append(args, "-c")
pipeLen -= 1
cmdArg := ""
for i, p := range pipes {
cmdArg += p.Command + " " + strings.Join(p.Args, " ")
if i != pipeLen {
cmdArg += " | "
}
}
args = append(args, cmdArg)
return execNoCheck(ctx, command, args)
}