fd/src/exec/ticket.rs

62 lines
2.1 KiB
Rust
Raw Normal View History

2017-10-14 18:04:11 +02:00
use std::env;
2017-10-14 23:59:36 +02:00
use std::process::{Command, Stdio};
use std::sync::{Arc, Mutex};
use std::io::{self, Write};
2017-10-14 18:04:11 +02:00
lazy_static! {
/// On non-Windows systems, the `SHELL` environment variable will be used to determine the
/// preferred shell of choice for execution. Windows will simply use `cmd`.
static ref COMMAND: (String, &'static str) = if cfg!(target_os = "windows") {
("cmd".into(), "/C")
} else {
(env::var("SHELL").unwrap_or("/bin/sh".into()), "-c")
};
}
/// A state that offers access to executing a generated command.
///
/// The ticket holds a mutable reference to a string that contains the command to be executed.
/// After execution of the the command via the `then_execute()` method, the string will be
/// cleared so that a new command can be written to the string in the future.
pub struct CommandTicket<'a> {
command: &'a mut String,
2017-10-14 23:59:36 +02:00
out_perm: Arc<Mutex<()>>,
2017-10-14 18:04:11 +02:00
}
impl<'a> CommandTicket<'a> {
2017-10-14 23:59:36 +02:00
pub fn new(command: &'a mut String, out_perm: Arc<Mutex<()>>) -> CommandTicket<'a> {
CommandTicket { command, out_perm }
2017-10-14 18:04:11 +02:00
}
/// Executes the command stored within the ticket, and
/// clearing the command's buffer when finished.
pub fn then_execute(self) {
// Spawn a shell with the supplied command.
let cmd = Command::new(COMMAND.0.as_str())
.arg(COMMAND.1)
.arg(&self.command)
2017-10-14 23:59:36 +02:00
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output();
2017-10-14 18:04:11 +02:00
// Then wait for the command to exit, if it was spawned.
match cmd {
2017-10-14 23:59:36 +02:00
Ok(output) => {
// While this lock is active, this thread will be the only thread allowed
// to write it's outputs.
let _lock = self.out_perm.lock().unwrap();
let stdout = io::stdout();
let stderr = io::stderr();
let _ = stdout.lock().write_all(&output.stdout);
let _ = stderr.lock().write_all(&output.stderr);
2017-10-14 20:04:04 +02:00
}
2017-10-14 18:04:11 +02:00
Err(why) => eprintln!("fd: exec error: {}", why),
}
// Clear the buffer for later re-use.
self.command.clear();
}
}