Lorenz Bung vor 8 Jahren
Ursprung
Commit
d1cee663ba
4 geänderte Dateien mit 171 neuen und 47 gelöschten Zeilen
  1. 18
    19
      hw6/task1/src/main.rs
  2. 55
    3
      hw6/task2/src/command.rs
  3. 12
    1
      hw6/task2/src/main.rs
  4. 86
    24
      hw6/task2/src/shell.rs

+ 18
- 19
hw6/task1/src/main.rs Datei anzeigen

@@ -10,7 +10,7 @@ use nix::sys::wait::WaitStatus;
10 10
 use nix::unistd::ForkResult::{Child, Parent};
11 11
 use std::os::unix::io::RawFd;
12 12
 
13
-const BUFFER_SIZE : usize = 256;
13
+const BUFFER_SIZE: usize = 256;
14 14
 
15 15
 
16 16
 fn main() {
@@ -18,13 +18,12 @@ fn main() {
18 18
     let arguments: Vec<String> = args().collect();
19 19
 
20 20
     if arguments.len() > 2 {
21
-        if let Ok((reader, writer)) = pipe(){
21
+        if let Ok((reader, writer)) = pipe() {
22 22
             let numbers = arguments[1..].to_vec();
23 23
 
24 24
             let pid = fork();
25 25
             match pid {
26 26
                 Ok(Child) => {
27
-
28 27
                     match read_from_pipe(reader) {
29 28
                         Ok(msg_received) => {
30 29
                             let vec = split_into_strings(&msg_received);
@@ -36,34 +35,34 @@ fn main() {
36 35
                                         Ok(res) => println!("Sum = {}", res),
37 36
                                         Err(e) => println!("{}", e),
38 37
                                     }
39
-                                },
40
-                                Ok(Parent{..}) => {
38
+                                }
39
+                                Ok(Parent { .. }) => {
41 40
                                     if let Ok(ws) = wait() {
42
-                                        if let WaitStatus::Exited(_,_) = ws {
41
+                                        if let WaitStatus::Exited(_, _) = ws {
43 42
                                             match mul_strings(vec) {
44 43
                                                 Ok(res) => println!("Mul = {}", res),
45 44
                                                 Err(e) => println!("{}", e),
46 45
                                             }
47 46
                                         }
48 47
                                     }
49
-                                },
48
+                                }
50 49
                                 Err(_) => println!("Fatal error: Fork failed"),
51 50
                             }
52 51
 
53
-                        },
54
-                        Err(_) => {},
52
+                        }
53
+                        Err(_) => {}
55 54
                     }
56
-
57
-
58 55
                 }
59 56
 
60
-                Ok(Parent{..}) => {
57
+                Ok(Parent { .. }) => {
61 58
                     let mut args = String::new();
62 59
                     for s in numbers {
63
-                        args = concatenate_strings(&args, &concatenate_strings(&s , " "));
60
+                        args = concatenate_strings(&args, &concatenate_strings(&s, " "));
64 61
                     }
65 62
                     println!("sending to children: {}", args);
66
-                    if let Err(_) = write(writer, args.as_bytes()) { println!("Broken pipe") }
63
+                    if let Err(_) = write(writer, args.as_bytes()) {
64
+                        println!("Broken pipe")
65
+                    }
67 66
 
68 67
                     if let Err(_) = wait() {
69 68
                         println!("Waiting on children failed")
@@ -80,15 +79,15 @@ fn main() {
80 79
 
81 80
 }
82 81
 
83
-fn read_from_pipe(reader:RawFd) -> Result<String, String>{
82
+fn read_from_pipe(reader: RawFd) -> Result<String, String> {
84 83
     let mut read_buf = [0u8; BUFFER_SIZE];
85
-    match read(reader, &mut read_buf){
84
+    match read(reader, &mut read_buf) {
86 85
         Ok(bytes_read) => {
87
-            match str::from_utf8(&read_buf[0 .. bytes_read]) {
86
+            match str::from_utf8(&read_buf[0..bytes_read]) {
88 87
                 Ok(msg_received) => Ok(msg_received.to_string()),
89 88
                 Err(_) => Err("Couldn't read".to_string()),
90 89
             }
91
-        },
90
+        }
92 91
         Err(_) => Err("Couldn't read".to_string()),
93 92
     }
94 93
 }
@@ -142,4 +141,4 @@ fn mul_strings(v: Vec<String>) -> Result<i32, String> {
142 141
         }
143 142
     }
144 143
     Ok(prod)
145
-}
144
+}

+ 55
- 3
hw6/task2/src/command.rs Datei anzeigen

@@ -1,11 +1,63 @@
1
-enum Command {
1
+use std::ffi::OsString;
2
+use std::str::FromStr;
3
+use std::env;
4
+
5
+pub enum Command {
2 6
     Empty,
3 7
     Exit,
4 8
     Cd(Option<OsString>),
5 9
 }
6 10
 
7
-impl Command {}
11
+pub struct CommandNotFoundError;
8 12
 
9 13
 impl FromStr for Command {
10
-    fn from_str(s: &str) -> Result<Self, Self::Err> {}
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
+    }
11 63
 }

+ 12
- 1
hw6/task2/src/main.rs Datei anzeigen

@@ -1,8 +1,19 @@
1 1
 use std::process;
2
+use shell::{Shell, R, W};
3
+use std::io;
4
+
5
+mod command;
2 6
 mod shell;
3 7
 
8
+
4 9
 fn main() {
5
-    let mut s = Shell::new(..);
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());
6 17
     match s.start() {
7 18
         Ok(_) => process::exit(0),
8 19
         Err(_) => process::exit(1),

+ 86
- 24
hw6/task2/src/shell.rs Datei anzeigen

@@ -1,52 +1,114 @@
1
+use std::io::{BufRead, Write, Read, StdinLock, StdoutLock};
1 2
 use std::io;
2
-use std::io::prelude::*;
3
-use command;
4 3
 
5
-struct Shell<R, W> {
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> {
6 13
     pub reader: R,
7 14
     pub writer: W,
8 15
     pub should_exit: bool,
9 16
     pub name: String,
10 17
 }
11 18
 
12
-impl Shell<R, W> {
13
-    /// Creates a new Shell.
14
-    pub fn new(input: R, output: W, name: String) -> Self {
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 {
15 22
         Shell {
16
-            reader = input,
17
-            writer = output,
18
-            should_exit = false,
19
-            name = name,
23
+            reader: input,
24
+            writer: output,
25
+            should_exit: false,
26
+            name: name,
20 27
         }
21 28
     }
22
-    /// Initializes the Shell Loop
23
-    pub fn start() -> Result<Self, &str> {
24
-        shell_loop();
29
+    /// Initializes the Shell Loop.
30
+    /// Starts the shell.
31
+    pub fn start(&mut self) -> Result<(), &str> {
32
+        self.shell_loop()
25 33
     }
26
-    /// Waits for user inputs.
27
-    fn shell_loop() -> Result {
28
-        loop {
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
+            }
29 43
         }
44
+        Ok(())
30 45
     }
46
+
31 47
     /// Prints the shell prompt.
32
-    fn prompt() -> Result<Option, &str> {
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
+        }
33 67
     }
68
+
34 69
     /// Runs a command.
35
-    fn run(&str) {
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(())
36 81
     }
37 82
 }
38 83
 
39
-impl BufRead for Shell<R, W> {
40
-    fn fill_buf(&mut self) -> Result<&[u8]> {
41
-        stdin.fill_buf()
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)
42 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
+
43 99
     fn consume(&mut self, amt: usize) {
100
+        self.0.consume(amt)
44 101
     }
45 102
 }
46 103
 
47
-impl Write for Shell<R, W> {
48
-    fn write(&mut self, buf: &[u8]) -> Result<usize> {
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)
49 109
     }
50
-    fn flush(&mut self) -> Result<()> {
110
+
111
+    fn flush(&mut self) -> Result<(), io::Error> {
112
+        self.0.flush()
51 113
     }
52 114
 }

Laden…
Abbrechen
Speichern