Implementing a Unix Shell
My senior research project was implementing a Unix shell in the Rust language. Here’s a few things I discovered along the way.
This page is not complete! I will continue to update it with more information throughout April and May as I continue writing my final paper on this project.
Goals
Implementation
Execution
This was actually pretty straightforward. When you’re writing a shell in C, normally what you do is use the fork()
system call, which creates a child process and returns its process ID (PID). In Rust, we don’t have to bother with as much lower-level stuff because of a struct called std::process::Command
, which provides some easy methods for us to just load up whatever command we want and run it.
1 |
|
Changing Directories
One of the most vital commands in any shell is cd
, which stands for “change directory”. cd
is a builtin, meaning that its functionality is literally written into the code of the shell (unlike the vast majority of programs, which are separate executables).
It just so happens that there’s a function for that, too! std::env::set_current_dir
actually changes our directory. We just need to figure out which directory to go to, which is easier said than done because of shortcuts like ..
(parent directory) and ~
(home directory). For example, assuming my home directory is /home/shreyas
, ~/Music/../Code/senior-research/src/main.rs
is the same thing as /home/shreyas/Code/senior-research/src/main.rs
, but a program won’t necessarily view them as the same. The following code helps canonicalize paths so that you get taken to the right place.
1 |
|
I discovered some time after this that std::fs::canonicalize
exists and does basically what I want, but I haven’t gotten around to replacing canonical_path
with it yet.
History
The shell currently tries to open ~/.shell_history
on startup, and if it doesn’t find the file, it panics and exits. I need to fix that error handling. For now, just run touch ~/.shell_history
and try again.
Interface
The interface of the shell relied heavily on the termion
library to interface with the terminal.
The Input Bug
Here’s how it looks now:
1 |
|
Yeah, it’s long.
Usage
The shell has issues with interactive commands. If you run python
, most of the characters are captured by the shell instead of passing through to the Python console. Running another shell like bash
or zsh
causes the shell process to be suspended as soon as you start typing. I don’t really know what causes this behavior.