Skip to main content

running_process_platform_internal/
foreground.rs

1//! Caller-owned foreground command execution.
2//!
3//! Unlike contained, bounded, and daemon spawning, this module intentionally
4//! does not configure process groups, sessions, descriptor inheritance,
5//! consoles, owner-death policy, or environment. The supplied `Command` is
6//! the complete native contract.
7
8use std::io;
9use std::process::{Child, Command, ExitStatus, Output};
10
11/// Start a caller-configured command and transfer its native child ownership.
12/// No containment or drop cleanup is added: the caller remains responsible for
13/// consuming pipes, termination and reaping, exactly as with `Command::spawn`.
14/// Use a contained/session API when that ownership policy is desired instead.
15pub fn spawn(command: &mut Command) -> io::Result<Child> {
16    command.spawn()
17}
18
19/// Run and return the native exit status.
20///
21/// Standard streams retain exactly the caller's `Command` configuration; the
22/// std default is inherited streams, while explicit `stdin`/`stdout`/`stderr`
23/// overrides remain in force.
24pub fn status(command: &mut Command) -> io::Result<ExitStatus> {
25    command.status()
26}
27
28/// Run with std's concurrent captured-output behavior and native exit status.
29/// Its stdio behavior is exactly `Command::output`: unspecified stdout/stderr
30/// are captured while explicit stream overrides remain caller-controlled.
31/// Every other caller-owned command property remains unchanged.
32pub fn output(command: &mut Command) -> io::Result<Output> {
33    command.output()
34}
35
36// Host-specific forms (Unix `exec`) come from the selected platform tree.
37// The Windows tree exports none, so the glob is empty there by design.
38#[allow(unused_imports)]
39pub use crate::foreground_imp::*;
40
41#[cfg(test)]
42pub(crate) mod tests {
43    use super::*;
44
45    /// Build a fixed fixture command for the per-host foreground tests. The
46    /// platform trees reuse this so every fixture `Command` is constructed in
47    /// this reviewed escape-hatch module, not a new spawn site.
48    pub(crate) fn fixture_command(program: impl AsRef<std::ffi::OsStr>) -> Command {
49        Command::new(program)
50    }
51
52    #[test]
53    fn spawn_preserves_native_missing_program_error() {
54        let directory = tempfile::tempdir().expect("private fixture directory");
55        let mut command = Command::new(directory.path().join("absent-executable"));
56        let error = spawn(&mut command).expect_err("no child should be created");
57        assert_eq!(error.kind(), io::ErrorKind::NotFound);
58    }
59}