Assignment 2: Tiny Shell

Due: February 17, 2026

For this assignment, you will translate your tsh assignment from COMP 321 into Rust. The goal of this assignment is to familiarize you with more advanced Rust concepts, including unsafe Rust, concurrency, and system calls.

Translating Your Solution

You should start with your C solution from COMP 321 and translate it into Rust. The Rust version should have the same functionality as your original solution (was supposed to have). You should think carefully about what external libraries you want to use and why. Don't just use an external library because AI suggests it.

You should run the same tests you were originally provided to test your code using the provided sdriver.pl test driver. Your Rust solution should pass all of the test cases. Recall that you were not given a complete set of test cases, so you should add your own additional test cases to ensure correctness of the shell.

Logistics

You will find all of the materials for this assignment in the tsh directory of the provided GitHub repository for the class.

For your work on this assignment, you should create a new private GitHub repository in the class organization with the name tsh-<netid> (where <netid> is replaced with your Rice NetID). The repository should contain your Rust solution, the provided testing infrastructure, and a README.md file that describes how to build, run, and test your code.

You should have a functioning solution on GitHub by the end of Thursday, February 12th.

Code Review

To evaluate your solution, you will participate in a code review process during class. Given that you will all be implementing the same program, it does not make sense to go through a traditional code review process, as that will likely become extremely repetitive. Instead, we will divide you up into groups of 2 students each and split the process over two days.

Day 1: Presentations

On the first day, each pair will give a 15-minute presentation. The audience may ask clarifying questions, but detailed feedback is reserved for Day 2. Presentations should cover at least the following:

  1. Key differences between the two solutions.
  2. Identify some parts of your C solutions that were potentially vulnerable to memory safety bugs (if you were to have made a common mistake, for example) and discuss how the Rust implementations mitigate those potential vulnerabilities.
  3. Details about concurrency, signal handling, the use of unsafe code, and the error-handling strategy.
  4. Which aspects of each solution are stronger and why.

Your participation grade will reflect your portion of the presentation; split the time roughly evenly between group members.

You should take notes throughout the presentations to prepare for Day 2.

Day 2: Group Critique

On the second day, the class will critique and discuss all the solutions. Please review classmates' repositories on GitHub before class so discussion can focus on tradeoffs, best practices, and potential issues.

In particular, be prepared to discuss the following:

  1. Rust has no first-class way of representing Unix signals. What impact did this have on the solutions? In contrast, Go uses channels to expose signals, how might this be better or worse than Rust?
  2. Compare the error handling in your original C program to the error handling in Rust. Did Rust enforce more disciplined error handling? How many errors were ignored in your C program that were explcitly dealt with in Rust? Are there places where the Rust program could terminate? For example, how is fork failure handled?