|
extern crate crossbeam; |
|
|
|
use std::io::{stdin, BufRead, BufReader}; |
|
use std::process::{Command, Stdio, ExitStatus}; |
|
use crossbeam::channel::{Sender, Receiver, unbounded}; |
|
|
|
#[derive(Debug)] |
|
enum ProcessEvent { |
|
ProcessStarted(u32), |
|
Stdout(String), |
|
Stderr(String), |
|
ProcessEnded(u32, ExitStatus), |
|
} |
|
|
|
fn run_process(line: String, output: Sender<ProcessEvent>) { |
|
let mut child = Command::new("cmd") |
|
.arg("/C") |
|
.arg(line) |
|
.stdin(Stdio::null()) |
|
.stdout(Stdio::piped()) |
|
.stderr(Stdio::piped()) |
|
.spawn() |
|
.expect("cmd doesn't exist!"); |
|
|
|
let pid = child.id(); |
|
output.send(ProcessEvent::ProcessStarted(pid)); |
|
|
|
crossbeam::thread::scope(|scope| { |
|
let child_stdout = child.stdout.as_mut().unwrap(); |
|
let child_stderr = child.stderr.as_mut().unwrap(); |
|
|
|
let stdout_thread = scope.spawn(|| { |
|
let child_stdout = BufReader::new(child_stdout); |
|
|
|
for child_line in child_stdout.lines() { |
|
if let Ok(child_line) = child_line { |
|
output.send(ProcessEvent::Stdout(child_line)) |
|
} |
|
} |
|
}); |
|
|
|
let stderr_thread = scope.spawn(|| { |
|
let child_stderr = BufReader::new(child_stderr); |
|
|
|
for child_line in child_stderr.lines() { |
|
if let Ok(child_line) = child_line { |
|
output.send(ProcessEvent::Stderr(child_line)); |
|
} |
|
} |
|
}); |
|
|
|
stdout_thread.join().unwrap(); |
|
stderr_thread.join().unwrap(); |
|
}); |
|
|
|
let status = child.wait().expect("Oops"); |
|
output.send(ProcessEvent::ProcessEnded(pid, status)); |
|
} |
|
|
|
fn process_starter(input: Receiver<String>, output: Sender<ProcessEvent>) { |
|
crossbeam::thread::scope(|scope| { |
|
for command in input { |
|
scope.spawn(|| { |
|
run_process(command, output.clone()); |
|
}); |
|
} |
|
}); |
|
} |
|
|
|
fn command_reader<R: BufRead>(source: R, output: Sender<String>) { |
|
for line in source.lines() { |
|
if let Ok(line) = line { |
|
output.send(line); |
|
} |
|
} |
|
} |
|
|
|
fn main() { |
|
println!("Now starting."); |
|
|
|
let (command_sender, command_receiver) = unbounded(); |
|
let (output_sender, output_receiver) = unbounded(); |
|
|
|
let reader_thread = std::thread::spawn(move || { |
|
command_reader(stdin().lock(), command_sender); |
|
}); |
|
let starter_thread = std::thread::spawn(move || { |
|
process_starter(command_receiver, output_sender); |
|
}); |
|
|
|
for event in output_receiver { |
|
println!("Event: {:?}", event); |
|
} |
|
|
|
starter_thread.join().unwrap(); |
|
reader_thread.join().unwrap(); |
|
} |