builds / shell / stage-3SHEET 3 / 6 · REV ASIGN IN
ASSEMBLY DIAGRAM — YOUR SHELLSCALE: LEARNING
keyboardthe outside worldCOMMAND LOOP✓ builtPROCESS LAUNCHER✓ builtFD PATCH PANEL⚙ buildingPIPE MANIFOLDstage 4SIGNAL BUSstage 5JOB BOARDstage 6
BUILTUNDER CONSTRUCTIONNOT YET IMAGINED INTO EXISTENCE
STAGE 3 · THE FD PATCH PANEL

Rewiring the Streams

stdout is not a place. It is slot 1 in a table the kernel keeps for your process.

What you're wiring up

A program does not know or care where its output goes. It writes to file descriptor 1, and fd 1 is a numbered slot in a per-process table that points at whatever the kernel was told to point it at. Redirection is the shell quietly re-plugging that slot before the program ever starts: open a file, dup2 it onto the slot, close the spare.

The timing is the whole lesson. The patching happens in the child, after fork and before exec. Do it in the parent and you have redirected your own shell's output permanently. The program being run is never consulted and needs no cooperation, which is why redirection works on every binary on the machine.

Once stdout is just slot 1, 2>&1 stops being an incantation. It means copy whatever fd 1 currently points at onto fd 2, and because it copies the current value, order matters. That is the classic interview question, and here you will build the thing the question is about.

# child fd table, after dup2, before exec
0 → terminal    1 → /tmp/out    2 → terminal

# 2>&1 copies whatever fd 1 IS at that moment
> out 2>&1   both streams land in out
2>&1 > out   only stdout lands in out

Assembly steps

[ 01 ]
Parse the redirection operators > , >> , < and 2> out of the token stream, leaving a clean argv plus a redirection list.
hint

They can appear anywhere: > out echo hi is legal. Strip them wherever you see them.

[ 02 ]
In the child, after fork and before exec, open(2) each target with the right flags, dup2 onto the right fd, and close the original.
hint

> is O_WRONLY|O_CREAT|O_TRUNC with mode 0644; >> swaps O_TRUNC for O_APPEND.

hint

Doing this in the parent would redirect the shell's own output forever. That is why the child owns it.

[ 03 ]
Support 2>&1 as a duplication of the current fd 1 onto fd 2, applied in the order the operators appeared.
hint

Process the redirection list left to right and both orderings fall out for free.

[ 04 ]
Make redirections work for builtins too, so pwd > where.txt writes the file and the next prompt still reaches the terminal.
hint

Builtins run inside the shell, so dup the original fds first, patch, run, then restore from the saved copies.

Go deeper (after it passes)

The fd table is the abstraction every later track leans on. DDIA M1 — Measure Before You Build drives processes over stdin and stdout exactly like this; you now know what its plumbing is doing underneath.