build-a-shell / lesson-07.md
Lesson 07 · Builtins

The builtin table and exit

Some commands have to run inside the shell itself, not in a child process. Today you add the dispatch that recognizes those builtins before forking, and implement the first one - exit.

The goal

Check whether the first word names a builtin and, if so, run it in the shell; make `exit` end the shell with a given status.

Start here - the target
TO DO
Scenario: Dispatching a builtin instead of forking
Giventhe line "exit 3"
Whenthe shell processes it
Thenthe shell itself terminates with status 3
Anda bare "exit" terminates the shell with status 0
Background

Most commands run in a child process, but a few cannot: they need to change the shell’s own state. exit is the clearest example - a child process exiting would not end your shell, so exit has to run in the shell process itself. These in-process commands are called builtins, and the shell checks for them before it forks.

Set up that check as a small dispatch keyed on the first word - today it has one entry, exit, but you will add cd, pwd, and type over the next few lessons, so give it room to grow (a table or a switch, not a one-off if you will regret). exit reads an optional status argument (exit 3 leaves with 3) and defaults to 0. Everything the dispatch does not recognize falls through to the fork/exec path you already built.

Make it work
// look up argv[0] BEFORE forking
if (strcmp(words[0], "exit") == 0) {
int code = (n > 1) ? atoi(words[1]) : 0;
exit(code);
}
// ...otherwise fall through to fork/exec as before
CheckpointDONE
Your shell has a builtin dispatch and a working `exit` command. Commit and stop here.