Inspiration
Every developer uses a shell every day but most people have no idea what's actually happening when they type a command. We wanted to find out by building one ourselves — no libraries, just C and raw system calls.
What it does
MyShell is a working Unix shell. You can pipe commands together, redirect input and output to files, use environment variables, run things in the background, and use built-ins like cd and export — pretty much what you'd expect from a real shell.
How we built it
The shell reads a line, breaks it into tokens, figures out what commands are being run and how they're connected, then executes them. For pipelines, it creates all the pipes upfront, forks a child process for each command, and wires them together so each command reads from the previous one's output. Built-ins like cd are a special case — they have to run in the parent process, otherwise changing directories in a child process does nothing.
Challenges
The trickiest bug was a race condition with $? (the last exit status). Our signal handler was updating it in the background, which could overwrite the exit code of whatever foreground command just finished. The fix was to only update $? in the foreground wait path and keep the signal handler out of it. We also spent a lot of time on pipe file descriptor leaks — if a child doesn't close the pipe ends it doesn't need, the next command just hangs forever waiting for input that never comes.
What we learned
Honestly, how much work a shell is doing every time you hit enter. Fork, exec, file descriptor inheritance, signal delivery — it all has to work together perfectly or things just silently hang or give the wrong exit code.
Log in or sign up for Devpost to join the conversation.