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
hint
They can appear anywhere: > out echo hi is legal. Strip them wherever you see them.
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.
hint
Process the redirection list left to right and both orderings fall out for free.
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.