| 1516 | } |
| 1517 | |
| 1518 | fn build_remote_exec_command(req: &ExecSandboxRequest) -> Result<String, String> { |
| 1519 | let mut parts = Vec::new(); |
| 1520 | let mut env_entries = req.environment.iter().collect::<Vec<_>>(); |
| 1521 | env_entries.sort_by_key(|(a, _)| *a); |
| 1522 | for (key, value) in env_entries { |
| 1523 | parts.push(format!("{key}={}", shell_escape(value)?)); |
| 1524 | } |
| 1525 | for arg in &req.command { |
| 1526 | parts.push(shell_escape(arg)?); |
| 1527 | } |
| 1528 | let command = parts.join(" "); |
| 1529 | let result = if req.workdir.is_empty() { |
| 1530 | command |
| 1531 | } else { |
| 1532 | format!("cd {} && {command}", shell_escape(&req.workdir)?) |
| 1533 | }; |
| 1534 | if result.len() > MAX_COMMAND_STRING_LEN { |
| 1535 | return Err(format!( |
| 1536 | "assembled command string exceeds {MAX_COMMAND_STRING_LEN} byte limit" |
| 1537 | )); |
| 1538 | } |
| 1539 | Ok(result) |
| 1540 | } |
| 1541 | |
| 1542 | /// Execute a command over an SSH transport relayed through a supervisor session. |
| 1543 | /// |