| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | //go:build windows |
| 4 | |
| 5 | package nagios |
| 6 | |
| 7 | import ( |
| 8 | "fmt" |
| 9 | "os" |
| 10 | "path/filepath" |
| 11 | "strings" |
| 12 | ) |
| 13 | |
| 14 | // rewriteScriptCommand detects Windows script files (.ps1, .bat, .cmd) |
| 15 | // and rewrites the command to invoke them through the appropriate interpreter. |
| 16 | // This allows users to set plugin directly to a script path without manually |
| 17 | // configuring the interpreter. |
| 18 | func rewriteScriptCommand(pluginPath string, args []string) (string, []string, error) { |
| 19 | lower := strings.ToLower(pluginPath) |
| 20 | |
| 21 | switch { |
| 22 | case strings.HasSuffix(lower, ".ps1"): |
| 23 | psPath, err := findPowerShell() |
| 24 | if err != nil { |
| 25 | return "", nil, fmt.Errorf("plugin '%s' is a PowerShell script but powershell.exe was not found: %w", pluginPath, err) |
| 26 | } |
| 27 | newArgs := make([]string, 0, 5+len(args)) |
| 28 | newArgs = append(newArgs, "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", pluginPath) |
| 29 | newArgs = append(newArgs, args...) |
| 30 | return psPath, newArgs, nil |
| 31 | |
| 32 | case strings.HasSuffix(lower, ".bat"), strings.HasSuffix(lower, ".cmd"): |
| 33 | cmdPath, err := findCmd() |
| 34 | if err != nil { |
| 35 | return "", nil, fmt.Errorf("plugin '%s' is a batch script but cmd.exe was not found: %w", pluginPath, err) |
| 36 | } |
| 37 | newArgs := make([]string, 0, 2+len(args)) |
| 38 | newArgs = append(newArgs, "/c", pluginPath) |
| 39 | newArgs = append(newArgs, args...) |
| 40 | return cmdPath, newArgs, nil |
| 41 | } |
| 42 | |
| 43 | return pluginPath, args, nil |
| 44 | } |
| 45 | |
| 46 | func findPowerShell() (string, error) { |
| 47 | sysRoot := os.Getenv("SystemRoot") |
| 48 | if sysRoot == "" { |
| 49 | sysRoot = `C:\Windows` |
| 50 | } |
| 51 | path := filepath.Join(sysRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe") |
| 52 | if _, err := os.Stat(path); err != nil { |
| 53 | return "", fmt.Errorf("powershell.exe not found at %s: %w", path, err) |
| 54 | } |
| 55 | return path, nil |
| 56 | } |
| 57 | |
| 58 | func findCmd() (string, error) { |
| 59 | // ComSpec is the standard Windows env var pointing to cmd.exe. |
| 60 | if comSpec := os.Getenv("ComSpec"); comSpec != "" { |
| 61 | if _, err := os.Stat(comSpec); err == nil { |
| 62 | return comSpec, nil |
| 63 | } |
| 64 | } |
| 65 | sysRoot := os.Getenv("SystemRoot") |
| 66 | if sysRoot == "" { |
| 67 | sysRoot = `C:\Windows` |
| 68 | } |
| 69 | path := filepath.Join(sysRoot, "System32", "cmd.exe") |
| 70 | if _, err := os.Stat(path); err != nil { |
| 71 | return "", fmt.Errorf("cmd.exe not found at %s: %w", path, err) |
| 72 | } |
| 73 | return path, nil |
| 74 | } |