| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- use std::env::args;
- use std::process;
-
- extern crate nix;
-
- use nix::unistd::{fork, pipe, read, write};
- use nix::sys::wait::wait;
- use std::str;
- use nix::sys::wait::WaitStatus;
- use nix::unistd::ForkResult::{Child, Parent};
- use std::os::unix::io::RawFd;
-
- const BUFFER_SIZE : usize = 256;
-
-
- fn main() {
-
- let arguments: Vec<String> = args().collect();
-
- if arguments.len() > 2 {
- if let Ok((reader, writer)) = pipe(){
- let numbers = arguments[1..].to_vec();
-
- let pid = fork();
- match pid {
- Ok(Child) => {
-
- match read_from_pipe(reader) {
- Ok(msg_received) => {
- let vec = split_into_strings(&msg_received);
-
- let pid = fork();
- match pid {
- Ok(Child) => {
- match sum_strings(vec) {
- Ok(res) => println!("Sum = {}", res),
- Err(e) => println!("{}", e),
- }
- },
- Ok(Parent{..}) => {
- if let Ok(ws) = wait() {
- if let WaitStatus::Exited(_,_) = ws {
- match mul_strings(vec) {
- Ok(res) => println!("Mul = {}", res),
- Err(e) => println!("{}", e),
- }
- }
- }
- },
- Err(_) => println!("Fatal error: Fork failed"),
- }
-
- },
- Err(_) => {},
- }
-
-
- }
-
- Ok(Parent{..}) => {
- let mut args = String::new();
- for s in numbers {
- args = concatenate_strings(&args, &concatenate_strings(&s , " "));
- }
- println!("sending to children: {}", args);
- if let Err(_) = write(writer, args.as_bytes()) { println!("Broken pipe") }
-
- if let Err(_) = wait() {
- println!("Waiting on children failed")
- }
- }
-
- Err(_) => {}
- }
- }
- } else {
- println!("Correct usage: number number <number> ...");
- process::exit(1)
- }
-
- }
-
- fn read_from_pipe(reader:RawFd) -> Result<String, String>{
- let mut read_buf = [0u8; BUFFER_SIZE];
- match read(reader, &mut read_buf){
- Ok(bytes_read) => {
- match str::from_utf8(&read_buf[0 .. bytes_read]) {
- Ok(msg_received) => Ok(msg_received.to_string()),
- Err(_) => Err("Couldn't read".to_string()),
- }
- },
- Err(_) => Err("Couldn't read".to_string()),
- }
- }
-
- /// Concats the two given String *references* and returns them as a String.
- fn concatenate_strings<'a>(s1: &'a str, s2: &'a str) -> String {
- s1.to_string() + s2
- }
-
- /// Splits the given String reference and returns it as Vector.
- fn split_into_strings<'a>(s1: &'a str) -> Vec<String> {
- s1.to_string()
- .split_whitespace()
- .map(|s| s.to_string())
- .collect()
- }
-
- /// Calculates the sum of the given Strings and returns them as a Result.
- fn sum_strings(v: Vec<String>) -> Result<i32, String> {
- let mut sum = 0;
- for x in v {
- match x.parse::<i32>() {
- Ok(val) => {
- match i32::checked_add(sum, val) {
- Some(y) => {
- sum = y;
- }
- None => return Err("Overflow would happen in sum_strings()".to_string()),
- }
- }
- Err(_) => return Err("Given String is not a int".to_string()),
- }
- }
- Ok(sum)
- }
-
- /// Calculates the product of the given Strings and returns them as a Result.
- fn mul_strings(v: Vec<String>) -> Result<i32, String> {
- let mut prod = 1;
- for x in v {
- match x.parse::<i32>() {
- Ok(val) => {
- match i32::checked_mul(prod, val) {
- Some(y) => {
- prod = y;
- }
- None => return Err("Overflow would happen in mul_strings()".to_string()),
- }
- }
- Err(_) => return Err("Given String is not a int".to_string()),
- }
- }
- Ok(prod)
- }
|