mirror of
https://github.com/watchexec/watchexec.git
synced 2024-11-17 09:38:31 +01:00
101 lines
2 KiB
Rust
101 lines
2 KiB
Rust
|
use std::fmt;
|
||
|
|
||
|
use tokio::process::Command as TokioCommand;
|
||
|
use tracing::trace;
|
||
|
|
||
|
use super::{Command, Program};
|
||
|
|
||
|
impl Command {
|
||
|
/// Obtain a [`tokio::process::Command`].
|
||
|
pub fn to_spawnable(&self) -> TokioCommand {
|
||
|
trace!(program=?self.program, "constructing command");
|
||
|
|
||
|
#[cfg_attr(not(unix), allow(unused_mut))]
|
||
|
let mut cmd = match &self.program {
|
||
|
Program::Exec { prog, args, .. } => {
|
||
|
let mut c = TokioCommand::new(prog);
|
||
|
c.args(args);
|
||
|
c
|
||
|
}
|
||
|
|
||
|
Program::Shell {
|
||
|
shell,
|
||
|
args,
|
||
|
command,
|
||
|
} => {
|
||
|
let mut c = TokioCommand::new(shell.prog.clone());
|
||
|
|
||
|
// Avoid quoting issues on Windows by using raw_arg everywhere
|
||
|
#[cfg(windows)]
|
||
|
{
|
||
|
for opt in &shell.options {
|
||
|
c.raw_arg(opt);
|
||
|
}
|
||
|
if let Some(progopt) = &shell.program_option {
|
||
|
c.raw_arg(progopt);
|
||
|
}
|
||
|
c.raw_arg(command);
|
||
|
for arg in args {
|
||
|
c.raw_arg(arg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[cfg(not(windows))]
|
||
|
{
|
||
|
c.args(shell.options.clone());
|
||
|
if let Some(progopt) = &shell.program_option {
|
||
|
c.arg(progopt);
|
||
|
}
|
||
|
c.arg(command);
|
||
|
for arg in args {
|
||
|
c.arg(arg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
c
|
||
|
}
|
||
|
};
|
||
|
|
||
|
#[cfg(unix)]
|
||
|
if self.options.reset_sigmask {
|
||
|
use nix::sys::signal::{sigprocmask, SigSet, SigmaskHow};
|
||
|
unsafe {
|
||
|
cmd.pre_exec(|| {
|
||
|
let mut oldset = SigSet::empty();
|
||
|
let newset = SigSet::all();
|
||
|
trace!(unblocking=?newset, "resetting process sigmask");
|
||
|
sigprocmask(SigmaskHow::SIG_UNBLOCK, Some(&newset), Some(&mut oldset))?;
|
||
|
trace!(?oldset, "sigmask reset");
|
||
|
Ok(())
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cmd
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl fmt::Display for Program {
|
||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||
|
match self {
|
||
|
Self::Exec { prog, args, .. } => {
|
||
|
write!(f, "{}", prog.display())?;
|
||
|
for arg in args {
|
||
|
write!(f, " {arg}")?;
|
||
|
}
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
Self::Shell { command, .. } => {
|
||
|
write!(f, "{command}")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl fmt::Display for Command {
|
||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||
|
write!(f, "{}", self.program)
|
||
|
}
|
||
|
}
|