| 64 | } |
| 65 | |
| 66 | func runJSONShellHook(ctx context.Context, command string, payload any) error { |
| 67 | command = strings.TrimSpace(command) |
| 68 | if command == "" { |
| 69 | return nil |
| 70 | } |
| 71 | data, err := json.Marshal(payload) |
| 72 | if err != nil { |
| 73 | return fmt.Errorf("encode poll hook payload: %w", err) |
| 74 | } |
| 75 | data = append(data, '\n') |
| 76 | |
| 77 | var cmd *exec.Cmd |
| 78 | if os.PathSeparator == '\\' { |
| 79 | cmd = exec.CommandContext(ctx, "cmd.exe", "/D", "/S", "/C", command) //nolint:gosec // command is an explicit local operator-provided hook. |
| 80 | } else { |
| 81 | cmd = exec.CommandContext(ctx, "/bin/sh", "-c", command) //nolint:gosec // command is an explicit local operator-provided hook. |
| 82 | } |
| 83 | cmd.Stdin = bytes.NewReader(data) |
| 84 | cmd.Stdout = stderrWriter(ctx) |
| 85 | cmd.Stderr = stderrWriter(ctx) |
| 86 | if err := cmd.Run(); err != nil { |
| 87 | if ctx.Err() != nil { |
| 88 | return ctx.Err() |
| 89 | } |
| 90 | return fmt.Errorf("shell hook failed: %w", err) |
| 91 | } |
| 92 | return nil |
| 93 | } |
| 94 | |
| 95 | func expandPollStatePath(raw string) (string, error) { |
| 96 | raw = strings.TrimSpace(raw) |