package provider import ( "fmt" "os/exec" "strings" "github.com/kami/hexis/internal/domain" ) type SystemdProvider struct{} func NewSystemdProvider() *SystemdProvider { return &SystemdProvider{} } func (p *SystemdProvider) Name() string { return "systemd" } func (p *SystemdProvider) Execute(capability *domain.Capability, req *domain.ExecuteRequest) (map[string]any, error) { unitName := req.TargetEntityID if unitName == "" { unitName = capability.TargetEntityID } if !isValidUnitName(unitName) { return nil, fmt.Errorf("invalid unit name: %q", unitName) } var cmd *exec.Cmd switch capability.Operation { case "restart": cmd = exec.Command("systemctl", "restart", unitName) case "start": cmd = exec.Command("systemctl", "start", unitName) case "stop": cmd = exec.Command("systemctl", "stop", unitName) case "status": cmd = exec.Command("systemctl", "status", unitName) case "reload": cmd = exec.Command("systemctl", "reload", unitName) case "enable": cmd = exec.Command("systemctl", "enable", unitName) case "disable": cmd = exec.Command("systemctl", "disable", unitName) default: return nil, fmt.Errorf("unsupported systemd operation: %s", capability.Operation) } output, err := cmd.CombinedOutput() if err != nil { return map[string]any{ "stdout": string(output), "exit_code": cmd.ProcessState.ExitCode(), }, fmt.Errorf("systemctl %s failed: %w\n%s", capability.Operation, err, string(output)) } return map[string]any{ "stdout": string(output), "exit_code": 0, }, nil } func isValidUnitName(name string) bool { if name == "" || strings.Contains(name, "..") || strings.Contains(name, "/") || strings.Contains(name, ";") || strings.Contains(name, "|") || strings.Contains(name, "$") || strings.Contains(name, "`") || strings.Contains(name, "'") || strings.Contains(name, `"`) || strings.Contains(name, "\\") { return false } return true }