Alex Dierks

Custom Unix Shell

Project Background

Goal

The goal of this group assignment was to learn systems programming by creating a custom shell. The shell would run both custom commands and standard system commands.

Constraints

System() calls could not be used — only fork() and exec() were allowed.

Team

I was paired with three other students. No one had programmed on a team before or used Git extensively. Only half the team — I and one other member — had working knowledge of C.

Assignment Signifigance

This is the most challenging project I've worked on, both techincally and managerially. I showcase it not because of how well it turned out, but because of how it didn't fall apart and what I learned from it.

To illustrate the techincal difficulty of this assignment, less than half the class's submissions ran without errors, even after our professor modified the syllabus — twice — to give us double the original allocated time.

The shell after running system (echo, ls) and custom (myhistory) commands.

The Initial Plan

Work Distribution and Leadership

This project had two parts: the shell's core functionality (about 60% of the work) and four custom commands (about 10% each).

My team and I planned to split the work as follows:

  • everyone would complete one custom command
  • I would handle most (but not all) of the core functionality
  • my teammates would help where they could for the remaining core functionality

I elected to lead the project and guide work on the shell's core because I had the most C experience and free time. Overall, I planned to handle about 50% of the total work.

Documentation

Because this was my first group coding project, I planned to make a special effort to write in-code documentation to help my teammates understand how my code worked, why it was built that way, and how to use what I'd written. As the leader, I would also leave comments to help them with their work.

Organization

I set up the project to have separate files for the shell's core code and each custom command. This would reduce merge conflicts and keep the code organized.

The Main Function

Defensive programming handles unexpected commandline arguments. My documentation of the Command struct is below the path stuff added by my teammate.

The Actual Process (And What Went Wrong)

What I Did

My requests for assistance and status updates were not responded to. As a result, splitting the work became impossible, and so I designed and implemented the shell's core loop entirely on my own. This wound up being the majority (>80%) of the project effort.

Writing the core shell included

  • parsing user input
  • creating and forking child processes
  • piping commands
  • handling zombie and orphan processes
  • handling custom vs system commands
  • implementing trivial custom commands

I also wrote the myhistory command. (Many years of coding in C and C++ has made stuff like this kinda trivial, so this part was actually fun.)

Leadership and Communication

As leader, I did my best to support my teammates and track our progress.

I regularly

  • sent progress updates
  • warned about potential challenges
  • shared resources, insights, and advice
  • asked how everyone's work was going
  • offered my assistance with coding or explaining stuff

However, responses to my messages were sparse.

Custom Command Handler

Notice the abundant commentary explaining what the code is doing, plus the instructions and tips for my teammates.

Collaboration Methods

We worked separately and communicated asynchronously over Discord text chat. I did not see anyone's code until the end.

At the end of the project, we texted synchronously as I coordinated the final effort to combine everyone's code and debug the final product.

What Came in Handy

I couldn't have done this without having studied under the legendary Bill Slater, my computer science professor from Collin College. I took every course he offered, sometimes twice, because I gained so much from his hands-on learning style and challenging labs. He's the reason I know how to code — well — in C and C++. I owe him my success.

The myhistory Code

I really enjoy stuff coding like this. Only I worked on this file.

Challenges Overcome

The Challenges

This was one of the most difficult projects I've completed. Our challenges stemmed from lack of communication and the difficulty of the assignment itself.

Personnel Challenges

  1. No one responded to my messages.
    I did everything to prevent this and it happened anyway.
  2. Some teammates struggled with C.
    This wasn't known until towards the end, and we could have worked more efficiently had we known this sooner.
  3. One teammate unexpectedly left their part incomplete.
    This was despite declining multiple help offers and was discovered just before the deadline.

Technical Challenges

  1. None of us had used Git extensively.
  2. Creating a chain of piped commands was an exceptional headache.
    A single pipe was doable, but handling two or more was something else. I had to settle for a hardcoded solution over a recursive one that would have allowed for an indefinite number of pipes.
  3. Debugging over text was much more limited than seeing the behavior firsthand.
    Helping my teammates debug their code via chat was more tedious than I thought it'd be.

The Victories

I understand impostor syndrome all too well. People can be shy about their coding skills. How much of that is from the toxically-competitive nature of programming, I don't know. However, I do know that one of the most uncomfortable situations you can be in is feeling unable to ask for help for fear of being thought of as incompetent. Having teammates who, from your perspective, seem to know what they're doing makes this feeling worse.

Once I realized my teammates needed help with the language, I created example code to help them see what to do and how to do it.

Despite everything, we merged code within four hours because my documentation let everyone quickly understand what to do and how. Our program also runs most commands without crashing, which is more than I can say for my classmates' submissions.

The Results

Reception

This project earned an A. Each teammate also awarded me a peer review grade of A+ (and deemed me "the GOAT").

What I Learned

I struggled with this project, but that's why I showcase it. I felt like my skills weren't up to par because of how difficult it was for me. However, when teammates praised my leadership, coding, and problem-solving, and when I realized I did the hardest part all by myself, I realized my skills were fine, I just found it challenging because I'd never done anything like this before. And because school is designed to teach you new stuff and challenge you, that's exactly how I was supposed to feel.

What I'd Do Differently

If I did this project again, I'd make the following changes:

  • add more example code to the documentation
  • create robust template files and placeholder code for other's work
  • clarify my expectations about communication
  • keep a record of team communication in case issues develop
  • assume the worst if I can't verify my teammate's progress
My teammates said Alex, you the goat, and for real, Alex godly.
Higher praise is seldom earned.

Project Specs

Here are the technical results of the project:

  • Project Duration: 3 months
  • Team Size: 4 teammates
  • Language: C
  • IDE: Visual Studio Code
  • Version Control: Git
  • Repository Host: GitLab (expired)
  • Class: CSCE 3600, Principles of Systems Programming, University of North Texas

Skills Used

    Hard Skills:
  • Linux
  • C
  • Make
  • Systems Programming
  • Code Documentation
    Soft Skills:
  • Teamwork
  • Project Leadership
  • Organization
    Tools:
  • VS Code
  • Git
  • GitLab