How to send input to a program through stdin in Rust

rust, shell, stdio

Solution

This program demonstrates how you can launch external programs and stream their stdout -> stdin together:

use std::io::{BufRead, BufReader, BufWriter, Write};
use std::process::{Command, Stdio};

fn main() {
    // Create some argument vectors for lanuching external programs
    let a = vec!["view", "-h", "file.bam"];
    let outsam = vec!["view", "-bh", "-o", "rust.bam", "-"];

    let mut child = Command::new("samtools")
        .args(&a)
        .stdout(Stdio::piped())
        .spawn()
        .unwrap();
    let outchild = Command::new("samtools")
        .args(&outsam)
        .stdin(Stdio::piped())
        .spawn()
        .unwrap();

    // Create a handle and writer for the stdin of the second process
    let mut outstdin = outchild.stdin.unwrap();
    let mut writer = BufWriter::new(&mut outstdin);

    // Loop over the output from the first process
    if let Some(ref mut stdout) = child.stdout {
        for line in BufReader::new(stdout).lines() {

            let mut l: String = line.unwrap();
            // Need to add an end of line character back to the string
            let eol: &str = "\n";
            l = l + eol;

            // Print some select lines from the first child to stdin of second
            if (l.chars().skip(0).next().unwrap()) == '@' {
                // convert the string into bytes and write to second process
                let bytestring = l.as_bytes();
                writer.write_all(bytestring).unwrap();
            }
        }
    }
}

Problem

I am attempting to write a shell in Rust. One of the functions of a shell is being able to redirect input to a file, redirect a file to input, and pipe output of a program into another program. I am using the `run::process_output` functions in `std` to run programs and get their output, but I don't know how to send input as if it was stdin to a program after running it. Is there some way to create an object that is directly connected to the ran program and push in input like it was typed in stdin?

Original source