mash
I built a simple shell. You know the thing were you type commands and then magically something happens on your computer?
This is it. Here’s what I built in a little more detail:
Features
-
Executable execution: This is obviously a requirement for any shell and one of the core features of
mash.
-
Basic Builtins:
mash supports some of the most important (or simple) builtins. Here is a quick list
-
IO Interconnection (pipes, etc…): This was by far the most difficult feature to implement. Now though you can
pipe stdin, out and err freely between any combination of builtin and external command.
-
Command Chronic: History is saved, can be viewed and executed. Also includes history persistence for good
measure.
-
Advanced Aliasing: Not really that advanced, but you know… that was the best thing I could come up with for A.
Anyways, mash supports creating and removing aliases for commands and aliases are resolved recursively to support
using aliases within aliases, if you need that for whatever reason. Plus persistence between sessions to make them
actually useful.
Storytime
I originally started this project about half a year ago at codecrafters.io. I finished the
core tasks no problem, but when I got to IO redirection my architecture started to fall apart (There wasn’t any notion
of expressions, it was just pure string manipulation). Then, when flavortown started, I finally convinced myself to
write a proper parser. In the end the parser wasn’t really much of a problem, as I had written one before. Finding a
data-structure that somehow combined Commands and Builtins proved to be much more difficult, because I didn’t do my
research.
First I followed some examples on how to redirect IO, but they only showed the convenient way if you have a
fixed pattern, which didn’t work if you wanted to create arbitrary connections between commands. Only after wasting a
bunch of time trying a lot of different strategies I realized you could also just create a new OS-pipe manually and use
that.
I just realized how long this has become and that I should stop ranting, but there is one more thing I wanted to talk
about: mash probably has more dead code than any of my other projects. I created a lot of infrastructure for future
expansions, which I ended up never creating. So in the unlikely case that anyone would like to add something like stdin
from a file that is really easy to do. You’re welcome.
End
Creating a shell was a neat experience and actually not that difficult once I got my overall design figured
out. But I suppose you could say that about anything: Once you figured it out, it became easy.
If anyone actually took the time to read all of this: Thank you! That means a lot to me. I hope you learned something
new or at least found it interesting to read. Cheers!