Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/nornir

crates/mimir-driver/src/bin/mimir-capture.rs

//! `mimir-capture <stdout-file> -- <program> <args…>` — run a tool, copying its
//! stdout BYTE FOR BYTE to `<stdout-file>` while it also streams to this
//! process's stdout; stderr passes through; the exit code is the tool's.
//!
//! Why: on the CONTAINER road (nornir `code_room::container`) a tool's stdout
//! comes back through the engine's log API, which frames it — a line longer
//! than a frame (`cargo metadata`'s one-line JSON) arrives cut in pieces. The
//! file is what the consumer parses; the log stream only shows progress. No
//! shell: the tool is started with its argv.

use std::io::{Read, Write};
use std::process::{Command, ExitCode, Stdio};

fn main() -> ExitCode {
    let args: Vec<String> = std::env::args().skip(1).collect();
    let (Some(file), Some(sep)) = (args.first(), args.get(1)) else {
        eprintln!("usage: mimir-capture <stdout-file> -- <program> <args…>");
        return ExitCode::from(2);
    };
    if sep != "--" || args.len() < 3 {
        eprintln!("usage: mimir-capture <stdout-file> -- <program> <args…>");
        return ExitCode::from(2);
    }
    let mut out = match std::fs::File::create(file) {
        Ok(f) => f,
        Err(e) => {
            eprintln!("mimir-capture: cannot create {file}: {e}");
            return ExitCode::from(2);
        }
    };
    let mut child = match Command::new(&args[2]).args(&args[3..]).stdout(Stdio::piped()).stderr(Stdio::inherit()).spawn() {
        Ok(c) => c,
        Err(e) => {
            eprintln!("mimir-capture: cannot start {}: {e}", args[2]);
            return ExitCode::from(127);
        }
    };
    let mut pipe = child.stdout.take().expect("piped");
    let mut buf = [0u8; 64 * 1024];
    let stdout = std::io::stdout();
    loop {
        match pipe.read(&mut buf) {
            Ok(0) => break,
            Ok(n) => {
                if out.write_all(&buf[..n]).is_err() {
                    eprintln!("mimir-capture: writing {file} failed");
                }
                let mut s = stdout.lock();
                let _ = s.write_all(&buf[..n]);
                let _ = s.flush();
            }
            Err(e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
            Err(e) => {
                eprintln!("mimir-capture: reading the tool's stdout failed: {e}");
                break;
            }
        }
    }
    let _ = out.flush();
    match child.wait() {
        Ok(st) => match st.code() {
            Some(c) => ExitCode::from(c.clamp(0, 255) as u8),
            None => ExitCode::from(128 + 9),
        },
        Err(e) => {
            eprintln!("mimir-capture: wait failed: {e}");
            ExitCode::from(2)
        }
    }
}