1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//! This library lets you execute a child process and catch its output (stdout and stderr).
//! This is useful if you want to use the output from a specific command and transform it
//! in your program.
//!
//! ⚠️ Difference to std::process::Command 🚨
//! `std::process::Command` does the same in the standard library but **with one exception**:
//! My library gives you access to stdout, stderr, **and "stdcombined"**. This way you get all output
//! lines in the order they appeared. That's the unique feature of this crate.

use std::rc::Rc;

#[macro_use]
extern crate log;

mod error;
mod pipe;
mod libc_util;
mod exec;

pub use exec::fork_exec_and_catch;

/// Holds the text output lines for stdout
/// and stderr of the executed child process.
/// The stdcombined-property holds both combined
/// in the order they appeared.
#[derive(Debug)]
pub struct ProcessOutput {
    stdout_lines: Vec<Rc<String>>,
    stderr_lines: Vec<Rc<String>>,
    // combines values from both in the
    // order they occurred
    stdcombined_lines: Vec<Rc<String>>,
}

impl ProcessOutput {

    /// Constructor.
    fn new(stdout_lines: Vec<Rc<String>>,
               stderr_lines: Vec<Rc<String>>,
               stdcombined_lines: Vec<Rc<String>>) -> Self {
        Self {
            stdout_lines,
            stderr_lines,
            stdcombined_lines
        }
    }

    pub fn stdout_lines(&self) -> &Vec<Rc<String>> {
        &self.stdout_lines
    }
    pub fn stderr_lines(&self) -> &Vec<Rc<String>> {
        &self.stderr_lines
    }
    pub fn stdcombined_lines(&self) -> &Vec<Rc<String>> {
        &self.stdcombined_lines
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    // RUst tests doesn't work with fork, dup2 and other fun :)
    // weird output.. use the test binary instead!
    /*#[test]
    fn test_fork_exec_and_catch() {
        let res = fork_exec_and_catch("echo", vec!["echo", "hallo"]);

        println!("{:#?}", res);
        // fork_exec_and_catch("sysctl", vec!["sysctl", "-a"]);
    }*/
}