builds / shell / stage-1SHEET 1 / 6 · REV ASIGN IN
ASSEMBLY DIAGRAM — YOUR SHELLSCALE: LEARNING
keyboardthe outside worldCOMMAND LOOP⚙ buildingPROCESS LAUNCHERstage 2FD PATCH PANELstage 3PIPE MANIFOLDstage 4SIGNAL BUSstage 5JOB BOARDstage 6
BUILTUNDER CONSTRUCTIONNOT YET IMAGINED INTO EXISTENCE
STAGE 1 · THE COMMAND LOOP

The Console Comes Alive

A shell is a program that reads a line, breaks it into words, and acts on it.

What you're wiring up

Strip away the mystique and a shell is a REPL. Read a line, split it into words, do something, print a prompt, repeat. What makes it a shell rather than a calculator is that the evaluate step will eventually be the operating system itself. This stage builds everything except that step: the loop and the word-splitter.

Splitting on spaces is not enough, because quotes exist. Single quotes make everything inside literal; double quotes hold a group of words together while preserving the spaces between them. A small state machine that walks the line one character at a time handles both cleanly, and it is the seed of every lexer you will ever write.

Then you meet the first genuinely shell-shaped idea: some commands cannot be separate programs. If cd ran as a child process, the child would change its own working directory and then exit, leaving yours untouched. So cd and exit must run inside the shell. Builtin versus external is a distinction you will carry through every remaining stage.

# you type
__tokens a "b c" 'd  e'

# the tokenizer must produce, one per line
a
b c
d  e

Assembly steps

[ 01 ]
Print a $ prompt, read one line from stdin, echo the parsed words back one per line, and loop until EOF, exiting with status 0.
hint

getline(3) handles arbitrary-length input for you; do not hand-roll a fixed buffer.

hint

getline returns -1 at EOF (Ctrl-D). A zero-length line is not EOF, it just loops again.

[ 02 ]
Build the tokenizer: split on whitespace, honor single quotes as fully literal and double quotes as space-preserving groups.
hint

A NORMAL / IN_SQUOTE / IN_DQUOTE state machine beats clever tricks; strtok cannot do quotes at all.

[ 03 ]
Implement the builtins exit [n], cd <dir>, and pwd. Anything else prints mysh: command not found: <name> to stderr for now.
hint

chdir(2) plus getcwd(3) is the whole of cd and pwd.

hint

On a cd failure, print the kernel's own reason with strerror(errno) rather than inventing wording.

[ 04 ]
Keep a last_status integer. exit with no argument exits with the status of the last command.
hint

Builtins set it too: a failed cd is status 1. This variable becomes the $? machinery in Stage 2.

Go deeper (after it passes)

The quote-aware tokenizer is a lexer in miniature. build-your-own-interpreter takes the same skill and grows it into full lexing and parsing. Your builtin dispatch table is also the Command pattern in C, the subject of HFDP M5 — The Programmable Remote.