I realized a while back that I learn a new language best when I work on an actual program on it, as opposed to just following tutorials and reading books. So, I decided to look around for a fun program to write in order to learn rust. Back in college, as part of a network programming class, I was tasked with writing a rudimentary shell, and I can remember how much fun it was, so I decided to write a basic shell in rust.
Now, rust has a decent enough FFI, so I ended up at the execvp function, which accepts two arguments: a c_char*
and a c_char**
. After much ado, I ended up with the following piece of code:
unsafe {
let command_str = "ls".to_c_str();
let args_str = "-l".to_c_str();
libc::execvp(command_str.as_bytes().as_ptr() as *i8,
[ args_str.as_bytes().as_ptr() as *i8 ].as_ptr());
}
I can’t say that I’m particularly happy with that long chain of function calls, but it is how it is. However, the exec*
family of system calls replace the entire process memory of the calling process with that of the calling process, which is why the Fork-exec technique is required. So, I looked up whether fork
is available as part of Rust’s FFI, and sure enough it is. But when I put a call to fork
in my code, I immediately got an error saying error: unresolved name libc::fork
. So I looked up the rust code in src/libstd/libc.rs
, and it turns out that the fork
function is not exposed on the win32
platform. And the reason for this is that MinGW does not support forking processes. Cygwin does have support for it, but as the StackOverflow answer mentions, it isn’t pretty.
In the interest of not writing different code for different platforms, I’ve decided to use the system function call instead, which does the job admirably.