Skip to content

Commit 6f65ddb

Browse files
Merge pull request #11 from Jonstep101010/writeup
add documentation
2 parents d85ef40 + 6a59810 commit 6f65ddb

File tree

4 files changed

+40
-11
lines changed

4 files changed

+40
-11
lines changed

README.md

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,35 @@
1-
# minishell
1+
# [minishell](https://gh.jschwabe.site/42_minishell)-rs
2+
3+
A gradual rewrite of a [c2rust](https://github.com/immunant/c2rust) transpiled [codebase](https://gh.jschwabe.site/42_minishell).
4+
5+
Discover how C language programming constructs can be implemented in a more concise way.
6+
7+
## goals
8+
1. see where rust syntax and std containers can enable better readability or code structure
9+
2. discover where [`CString`](https://doc.rust-lang.org/stable/std/ffi/struct.CString.html), [`CStr`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html) and `&[u8]` ([u8](https://doc.rust-lang.org/stable/std/primitive.u8.html)) can find usage and reduce interactions with `char *`
10+
3. replace `extern "C"` and [libc](https://docs.rs/libc/latest/libc/) usage with [nix](https://docs.rs/nix/latest/nix/) wrappers, enabling more idiomatic (and less error prone?) usage of unix system functions.
11+
4. provide me with an excuse to write rust code
12+
## journey
13+
### context
14+
15+
The original implementation used loads of custom glue that could have been replaced with libc functions (strtok, strcoll, scanf/sprintf, fprintf).
16+
17+
This was fine as a school project and provided me with ample opportunities for refactoring in the rust version.
18+
19+
### key takeaways
20+
- since rust is not c, interacting with raw pointers is more error prone due to its memory model and my assumptions about memory derived from c
21+
- signal handling was easier to do in c, I ended up removing it as it caused weird bugs
22+
- even though rust has [`Command`](https://doc.rust-lang.org/std/process/struct.Command.html), it was not used. I adapted my execution logic to be more idiomatic by using nix wrappers (the reason for most [`unsafe`](https://doc.rust-lang.org/std/keyword.unsafe.html) usage)
23+
- taking advantage of rust's rich type system can improve readability and facilitate quick iteration - [choosing the correct tool is key](https://doc.rust-lang.org/std/)
24+
25+
## process
26+
### tactics
27+
1. transpile, then simplify some operations, mostly aligning types (e.g. [`libc::size_t`](https://docs.rs/libc/latest/libc/type.size_t.html) for [`u64`](https://doc.rust-lang.org/core/primitive.u64.html)/[`usize`](https://doc.rust-lang.org/core/primitive.usize.html)), removing non-needed casts and replacing [`.offset()`](https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.offset) with [`.add()`](https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.add)
28+
2. multiple failed rewrites of core functionality caused by newly introduced logic bugs - mitigated by comprehensive [test cases](https://docs.rs/rstest/latest/rstest/attr.rstest.html#test-parametrized-cases)
29+
3. issues with readability, naming - resolved by using more idiomatic constructs: [`Option`](https://doc.rust-lang.org/std/option/enum.Option.html), [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html), [tuples](https://doc.rust-lang.org/std/primitive.tuple.html), [slices](https://doc.rust-lang.org/std/primitive.slice.html) instead of [references](https://doc.rust-lang.org/std/primitive.reference.html), [`impl`](https://doc.rust-lang.org/std/keyword.impl.html) for structs
30+
4. remove duplicate or dead code replaced by std ([`format!`](https://doc.rust-lang.org/std/macro.format.html), [`vec![]`](https://doc.rust-lang.org/std/macro.vec.html), ...)
31+
32+
### strategy
33+
1. document & simplify original logic
34+
2. create adaptable tests, wrappers fitting both c-like and idiomatic rust outputs
35+
3. apply TDD feedback loop while simplifying logic and reducing [`unsafe`](https://doc.rust-lang.org/std/keyword.unsafe.html)

src/execution/execute_pipes.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ unsafe fn exec_last(shell: &mut t_shell, i: usize, prevpipe: *mut i32) {
2121
_ => (),
2222
},
2323
Ok(ForkResult::Child) => {
24-
// check signals child
24+
// previously: check signals child
2525
if shell.token_vec[i].has_redir {
2626
do_heredocs(&shell.token_vec[i], &mut *prevpipe, &shell.env);
2727
}
@@ -47,7 +47,7 @@ unsafe fn exec_pipe(shell: &mut t_shell, i: usize, prevpipe: *mut i32) {
4747
*prevpipe = pipefd[0_usize];
4848
}
4949
Ok(ForkResult::Child) => {
50-
// check signals child
50+
// previously: check signals child
5151
libc::close(pipefd[0_usize]);
5252
libc::dup2(pipefd[1_usize], 1);
5353
libc::close(pipefd[1_usize]);

src/main.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@
44

55
extern crate libc;
66

7-
// to spend more time ;\
8-
// handle signals? removed - non-functional - partially working in rustyline
9-
// use tempfile for heredoc (if possible!)
10-
117
mod environment;
128
mod execution;
139
mod lexer;
@@ -18,7 +14,7 @@ use rustyline::{DefaultEditor, Result, error::ReadlineError};
1814

1915
pub fn main() -> Result<()> {
2016
let mut shell = t_shell::new();
21-
// check signals
17+
// previously: check signals
2218
let mut rl = DefaultEditor::new()?;
2319
loop {
2420
let readline = rl.readline("minishell> ");
@@ -35,7 +31,6 @@ pub fn main() -> Result<()> {
3531
} else if shell.tokenize(trimmed_line).is_none() {
3632
continue;
3733
} else {
38-
// dbg!(&shell.token_vec);
3934
crate::execution::execute_commands(&mut shell);
4035
}
4136
}

src/msh.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ pub(crate) struct t_token {
3939
#[derive(Clone, Debug, PartialEq)]
4040
pub(crate) struct t_arg {
4141
pub elem_str: String,
42-
pub type_0: e_arg, // wrapped enum attribute
43-
pub redir: Option<e_redir>, // enum wrapping string
42+
pub type_0: e_arg,
43+
pub redir: Option<e_redir>,
4444
}
4545

4646
impl t_arg {

0 commit comments

Comments
 (0)