Joshua Rutschmann 8 vuotta sitten
vanhempi
commit
41d5ecdb0a
5 muutettua tiedostoa jossa 318 lisäystä ja 24 poistoa
  1. 114
    24
      hw6/task1/src/main.rs
  2. 6
    0
      hw6/task2/Cargo.toml
  3. 63
    0
      hw6/task2/src/command.rs
  4. 21
    0
      hw6/task2/src/main.rs
  5. 114
    0
      hw6/task2/src/shell.rs

+ 114
- 24
hw6/task1/src/main.rs Näytä tiedosto

@@ -3,37 +3,75 @@ use std::process;
3 3
 
4 4
 extern crate nix;
5 5
 
6
-use nix::unistd::{fork, getpid};
6
+use nix::unistd::{fork, pipe, read, write};
7 7
 use nix::sys::wait::wait;
8
+use std::str;
8 9
 use nix::sys::wait::WaitStatus;
9 10
 use nix::unistd::ForkResult::{Child, Parent};
11
+use std::os::unix::io::RawFd;
10 12
 
11
-fn main() {
13
+const BUFFER_SIZE: usize = 256;
12 14
 
13
- let arguments: Vec<String> = args().collect();
14 15
 
15
-    if arguments.len() != 0 {
16
-   
16
+fn main() {
17 17
 
18
-    let pid = fork();
19
-    match pid {
20
-        Ok(Child) => {
21
-            println!("hello, I am child (pid:{})", getpid());
22
-        }
18
+    let arguments: Vec<String> = args().collect();
19
+
20
+    if arguments.len() > 2 {
21
+        if let Ok((reader, writer)) = pipe() {
22
+            let numbers = arguments[1..].to_vec();
23
+
24
+            let pid = fork();
25
+            match pid {
26
+                Ok(Child) => {
27
+                    match read_from_pipe(reader) {
28
+                        Ok(msg_received) => {
29
+                            let vec = split_into_strings(&msg_received);
30
+
31
+                            let pid = fork();
32
+                            match pid {
33
+                                Ok(Child) => {
34
+                                    match sum_strings(vec) {
35
+                                        Ok(res) => println!("Sum = {}", res),
36
+                                        Err(e) => println!("{}", e),
37
+                                    }
38
+                                }
39
+                                Ok(Parent { .. }) => {
40
+                                    if let Ok(ws) = wait() {
41
+                                        if let WaitStatus::Exited(_, _) = ws {
42
+                                            match mul_strings(vec) {
43
+                                                Ok(res) => println!("Mul = {}", res),
44
+                                                Err(e) => println!("{}", e),
45
+                                            }
46
+                                        }
47
+                                    }
48
+                                }
49
+                                Err(_) => println!("Fatal error: Fork failed"),
50
+                            }
51
+
52
+                        }
53
+                        Err(_) => {}
54
+                    }
55
+                }
23 56
 
24
-        Ok(Parent { child }) => {
25
-            if let Ok(ws) = wait() {
26
-                if let WaitStatus::Exited(child_pid, exit_code) = ws {
27
-                
57
+                Ok(Parent { .. }) => {
58
+                    let mut args = String::new();
59
+                    for s in numbers {
60
+                        args = concatenate_strings(&args, &concatenate_strings(&s, " "));
61
+                    }
62
+                    println!("sending to children: {}", args);
63
+                    if let Err(_) = write(writer, args.as_bytes()) {
64
+                        println!("Broken pipe")
65
+                    }
66
+
67
+                    if let Err(_) = wait() {
68
+                        println!("Waiting on children failed")
69
+                    }
28 70
                 }
71
+
72
+                Err(_) => {}
29 73
             }
30 74
         }
31
-
32
-        Err(_) => {}
33
-    }
34
-
35
-
36
-
37 75
     } else {
38 76
         println!("Correct usage: number number <number> ...");
39 77
         process::exit(1)
@@ -41,14 +79,66 @@ fn main() {
41 79
 
42 80
 }
43 81
 
44
-fn concatenate_strings(){
82
+fn read_from_pipe(reader: RawFd) -> Result<String, String> {
83
+    let mut read_buf = [0u8; BUFFER_SIZE];
84
+    match read(reader, &mut read_buf) {
85
+        Ok(bytes_read) => {
86
+            match str::from_utf8(&read_buf[0..bytes_read]) {
87
+                Ok(msg_received) => Ok(msg_received.to_string()),
88
+                Err(_) => Err("Couldn't read".to_string()),
89
+            }
90
+        }
91
+        Err(_) => Err("Couldn't read".to_string()),
92
+    }
45 93
 }
46 94
 
47
-fn split_into_strings(){
95
+/// Concats the two given String *references* and returns them as a String.
96
+fn concatenate_strings<'a>(s1: &'a str, s2: &'a str) -> String {
97
+    s1.to_string() + s2
48 98
 }
49 99
 
50
-fn sum_strings(){
100
+/// Splits the given String reference and returns it as Vector.
101
+fn split_into_strings<'a>(s1: &'a str) -> Vec<String> {
102
+    s1.to_string()
103
+        .split_whitespace()
104
+        .map(|s| s.to_string())
105
+        .collect()
51 106
 }
52 107
 
53
-fn mul_strings(){
108
+/// Calculates the sum of the given Strings and returns them as a Result.
109
+fn sum_strings(v: Vec<String>) -> Result<i32, String> {
110
+    let mut sum = 0;
111
+    for x in v {
112
+        match x.parse::<i32>() {
113
+            Ok(val) => {
114
+                match i32::checked_add(sum, val) {
115
+                    Some(y) => {
116
+                        sum = y;
117
+                    }
118
+                    None => return Err("Overflow would happen in sum_strings()".to_string()),
119
+                }
120
+            }
121
+            Err(_) => return Err("Given String is not a int".to_string()),
122
+        }
123
+    }
124
+    Ok(sum)
125
+}
126
+
127
+/// Calculates the product of the given Strings and returns them as a Result.
128
+fn mul_strings(v: Vec<String>) -> Result<i32, String> {
129
+    let mut prod = 1;
130
+    for x in v {
131
+        match x.parse::<i32>() {
132
+            Ok(val) => {
133
+                match i32::checked_mul(prod, val) {
134
+                    Some(y) => {
135
+                        prod = y;
136
+                    }
137
+                    None => return Err("Overflow would happen in mul_strings()".to_string()),
138
+                }
139
+            }
140
+            Err(_) => return Err("Given String is not a int".to_string()),
141
+        }
142
+    }
143
+    Ok(prod)
54 144
 }

+ 6
- 0
hw6/task2/Cargo.toml Näytä tiedosto

@@ -0,0 +1,6 @@
1
+[package]
2
+name = "task2"
3
+version = "0.1.0"
4
+authors = ["Lorenz Bung <lorenz.bung@googlemail.com>"]
5
+
6
+[dependencies]

+ 63
- 0
hw6/task2/src/command.rs Näytä tiedosto

@@ -0,0 +1,63 @@
1
+use std::ffi::OsString;
2
+use std::str::FromStr;
3
+use std::env;
4
+
5
+pub enum Command {
6
+    Empty,
7
+    Exit,
8
+    Cd(Option<OsString>),
9
+}
10
+
11
+pub struct CommandNotFoundError;
12
+
13
+impl FromStr for Command {
14
+    type Err = CommandNotFoundError;
15
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
16
+
17
+        let mut parts = s.split_whitespace();
18
+
19
+        match parts.next() {
20
+            Some("exit") => Ok(Command::Exit),
21
+            Some("cd") => Ok(Command::parse_cd(parts.next())),
22
+            Some(cmd) => {
23
+                //For use in next homework, to execute programs.
24
+                let _ = cmd;
25
+                Err(CommandNotFoundError)
26
+            }
27
+            None => Ok(Command::Empty),
28
+        }
29
+    }
30
+}
31
+
32
+
33
+impl Command {
34
+    /// If the passed String exists, set the path of the Cd in the enum
35
+    pub fn parse_cd(cmd: Option<&str>) -> Self {
36
+        match cmd {
37
+            None => Command::Cd(None),
38
+            Some(dest) => Command::Cd(Some(OsString::from(dest))),
39
+        }
40
+    }
41
+
42
+    pub fn exec_cd(&self) {
43
+        if let Command::Cd(None) = *self {
44
+            let possible_home = env::home_dir();
45
+
46
+            if let Some(home) = possible_home {
47
+                let home_path = home.as_path();
48
+                let _ = env::set_current_dir(home_path);
49
+            }
50
+
51
+        }
52
+
53
+        if let Command::Cd(Some(ref path)) = *self {
54
+            match path.to_str() {
55
+                Some(_) => {
56
+                    let _ = env::set_current_dir(path);
57
+                }
58
+                None => {}
59
+            }
60
+
61
+        }
62
+    }
63
+}

+ 21
- 0
hw6/task2/src/main.rs Näytä tiedosto

@@ -0,0 +1,21 @@
1
+use std::process;
2
+use shell::{Shell, R, W};
3
+use std::io;
4
+
5
+mod command;
6
+mod shell;
7
+
8
+
9
+fn main() {
10
+    let stdin = io::stdin();
11
+    let input = R(stdin.lock());
12
+
13
+    let stdout = io::stdout();
14
+    let output = W(stdout.lock());
15
+
16
+    let mut s = Shell::new(input, output, "schell".to_string());
17
+    match s.start() {
18
+        Ok(_) => process::exit(0),
19
+        Err(_) => process::exit(1),
20
+    }
21
+}

+ 114
- 0
hw6/task2/src/shell.rs Näytä tiedosto

@@ -0,0 +1,114 @@
1
+use std::io::{BufRead, Write, Read, StdinLock, StdoutLock};
2
+use std::io;
3
+
4
+use command::*;
5
+use std::str::FromStr;
6
+use std::env;
7
+
8
+///Tuple-Structs which hold Std-in and -out locks.
9
+pub struct R<'a>(pub StdinLock<'a>);
10
+pub struct W<'a>(pub StdoutLock<'a>);
11
+
12
+pub struct Shell<R, W> {
13
+    pub reader: R,
14
+    pub writer: W,
15
+    pub should_exit: bool,
16
+    pub name: String,
17
+}
18
+
19
+impl<'a> Shell<R<'a>, W<'a>> {
20
+    /// Creates a new Shell with a name, input and output.
21
+    pub fn new(input: R<'a>, output: W<'a>, name: String) -> Self {
22
+        Shell {
23
+            reader: input,
24
+            writer: output,
25
+            should_exit: false,
26
+            name: name,
27
+        }
28
+    }
29
+    /// Initializes the Shell Loop.
30
+    /// Starts the shell.
31
+    pub fn start(&mut self) -> Result<(), &str> {
32
+        self.shell_loop()
33
+    }
34
+
35
+    /// Loops while exit hasn't been called.
36
+    /// When *prompt()* returns (the user hit enter) a Command is created through the FromStr-Trait.
37
+    /// If the Command-creation succeeds, run the command.
38
+    fn shell_loop(&mut self) -> Result<(), &str> {
39
+        while !self.should_exit {
40
+            if let Ok(line) = self.prompt() {
41
+                let _ = Command::from_str(&line).and_then(|cmd| self.run(cmd));
42
+            }
43
+        }
44
+        Ok(())
45
+    }
46
+
47
+    /// Prints the shell prompt.
48
+    /// Waits for user input and returns the read line.
49
+    fn prompt(&mut self) -> Result<String, &str> {
50
+        match env::current_dir() {
51
+            Ok(pwd) => {
52
+                let _ = self.writer.write(
53
+                    format!("{} {} > ", self.name, pwd.display())
54
+                        .as_bytes(),
55
+                );
56
+                let _ = self.writer.flush();
57
+
58
+                let mut line: String = String::new();
59
+                let read_result = self.reader.read_line(&mut line);
60
+                match read_result {
61
+                    Ok(_) => Ok(line),
62
+                    Err(_) => Err("Error reading."),
63
+                }
64
+            }
65
+            Err(_) => return Err("Path Error"),
66
+        }
67
+    }
68
+
69
+    /// Runs a command.
70
+    /// Currently only `cd` and `exit` are working.
71
+    fn run(&mut self, command: Command) -> Result<(), CommandNotFoundError> {
72
+
73
+        match command {
74
+            Command::Empty => {}
75
+            Command::Exit => self.should_exit = true,
76
+            Command::Cd(_) => {
77
+                command.exec_cd();
78
+            }
79
+        }
80
+        Ok(())
81
+    }
82
+}
83
+
84
+/// Implement Read-Trait for Tuple-Struct R
85
+/// Simply calls `read` of StdinLock
86
+impl<'a> Read for R<'a> {
87
+    fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
88
+        self.0.read(buf)
89
+    }
90
+}
91
+
92
+/// Implement BufRead-Trait for Tuple-Struct R
93
+/// Simply calls `fill_buff` and `consume` from StdinLock
94
+impl<'a> BufRead for R<'a> {
95
+    fn fill_buf(&mut self) -> Result<&[u8], io::Error> {
96
+        self.0.fill_buf()
97
+    }
98
+
99
+    fn consume(&mut self, amt: usize) {
100
+        self.0.consume(amt)
101
+    }
102
+}
103
+
104
+/// Implement Write-Trait for Tuple-Struct W
105
+/// Simply calls `write` and `flush` from StdoutLock
106
+impl<'a> Write for W<'a> {
107
+    fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
108
+        self.0.write(buf)
109
+    }
110
+
111
+    fn flush(&mut self) -> Result<(), io::Error> {
112
+        self.0.flush()
113
+    }
114
+}

Loading…
Peruuta
Tallenna