Skip to content

Commit 81f49c3

Browse files
committed
fix: escape subcommands passed to run
1 parent 81fa5c0 commit 81f49c3

File tree

1 file changed

+60
-2
lines changed

1 file changed

+60
-2
lines changed

src/runner.rs

+60-2
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,66 @@ pub fn run(package: &Package, binary: Option<String>, params: &Vec<String>) -> b
123123
));
124124
args.extend(params.iter().cloned());
125125

126-
let command = format!("docker {}", args.join(" "));
127-
run_command(&command, Some(buffer))
126+
let command = "docker";
127+
run_command_with_args(command, &args, Some(buffer))
128+
}
129+
130+
fn run_command_with_args(command: &str, args: &[String], stdin_buffer: Option<Vec<u8>>) -> bool {
131+
debug!("Running command: {} {:?}", command, args);
132+
133+
let mut child = Command::new(command)
134+
.args(args)
135+
.stdout(Stdio::piped()) // Redirect stdout to a pipe
136+
.stderr(Stdio::piped()) // Redirect stderr to a pipe
137+
.stdin(Stdio::piped()) // Set stdin to piped to write the buffer later
138+
.spawn() // Spawn the command
139+
.expect("Failed to spawn command");
140+
141+
// If stdin_buffer is Some, write it to the child's stdin
142+
if let Some(buffer) = stdin_buffer {
143+
let child_stdin = child.stdin.as_mut().expect("Failed to open stdin");
144+
child_stdin
145+
.write_all(&buffer)
146+
.expect("Failed to write to stdin");
147+
}
148+
149+
// Function to log output from a pipe
150+
fn log_output<R: BufRead>(reader: R, log_fn: impl Fn(&str)) {
151+
for line in reader.lines() {
152+
match line {
153+
Ok(line) => log_fn(&line),
154+
Err(e) => error!("Failed to read line from output: {}", e),
155+
}
156+
}
157+
}
158+
159+
// Read the child's stdout and stderr in separate threads and log them
160+
let stdout = child.stdout.take().expect("Failed to open stdout");
161+
let stderr = child.stderr.take().expect("Failed to open stderr");
162+
163+
let stdout_thread = std::thread::spawn(move || {
164+
log_output(BufReader::new(stdout), |line| info!("{}", line));
165+
});
166+
167+
let stderr_thread = std::thread::spawn(move || {
168+
log_output(BufReader::new(stderr), |line| error!("{}", line));
169+
});
170+
171+
// Wait for the command to complete
172+
let status = child.wait();
173+
174+
// Wait for the logging threads to finish
175+
let _ = stdout_thread.join();
176+
let _ = stderr_thread.join();
177+
178+
// Check the command status
179+
match status {
180+
Ok(status) => status.success(),
181+
Err(e) => {
182+
error!("Command failed to complete: {}", e);
183+
false
184+
}
185+
}
128186
}
129187

130188
pub fn pull(package: &Package) -> bool {

0 commit comments

Comments
 (0)