Phil Nelson’s UNIX Systems class at WWU guides each student through a series of six assignments, each adding more functionality to a basic shell program. At it’s start, msh can fork and eval, but not much else. By the end of the 10 week class, both the minishell and the students are much more capable.

###Features Implemented

  • Command-line parameters (inluding quoted strings and escape characters)
  • Comments
  • Built-in commands
  • Environment variable expansion
  • Nested commands– for example, envset file_contents $(cat ${FILENAME})
  • Signal handling
  • Pipelined commands
  • Input and output redirection
  • If statements and While loops (this implies that the shell interpreter is Turing Complete!)
  • Various other expansions (for example, $? is the exit code of the last command and $$ is the PID.)

Because this was a school project and the class is still being taught, I can’t provide source code here. However, if you’re interested (and not a student at WWU!), send me an email about it.

A test run of the minishell exercising some of its capabilities.

Sieve of Eratosthenes

Most of the grade for each minishell assignment is determined by a test script. The scripts are provided by the professor and they exercise the features required at each step. The test scripts are famously picky. (For example: I once struggled for hours to figure out why a particular line of my output was getting rejected. It turned out I was outputting the NUL-character in my NUL-terminated string. Since NUL is not printed, my output looked identical but was rejected by diff).

Once I’d passed the final test script, I could have called it quits. However, I decided to play with my newly finished minishell and write a test of my own.

With the addition of If statements and While loops, the language interpreted by the minishell is now Turing Complete. This means that it is (theoretically) possible for msh to compute anything that can be computed. I decided to take advantage of this, and implemented the Sieve of Eratosthenes in the language defined by my minishell.

A test run of the sieve program

Implementing this algorithm in the restricted environment of the minishell involved some complicated workarounds. For example, the only variables we have are environment variables (strings). Since the algorithm calls for an array of numbers, I use a space-separated string of base 10 numbers. To get the first element of this ‘array’, I used sed and a regex capture for a space-terminated series of digits. Anyway, here is the code, in all its ugliness.