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

cd

Changing directory is the builtin that most clearly cannot be a child process. Today you implement `cd`, including the error case where the target does not exist, so a bad path never silently moves you.

The goal

Implement `cd <path>` to change the shell's working directory, reporting an error and leaving the directory unchanged when the path is invalid.

Start here - the target
TO DO
Scenario: Changing the working directory
Giventhe shell runs "cd /"
Whena following "pwd" runs
Thenit prints "/"
Andrunning "cd /no/such/dir" prints an error, sets status 1, and leaves the working directory unchanged
Background

Here is the builtin that makes the “builtins must run in-process” rule concrete. If cd ran in a child, the child would change its directory and then exit, leaving the shell exactly where it started - useless. So cd calls the operating system’s change-directory function on the shell process itself, and every later command inherits the new location.

The other half of cd is failing well. Ask the OS to move; if it refuses - because the path does not exist, or is not a directory, or you lack permission - report a clear error, set the status to 1, and crucially do not pretend you moved. A shell that silently stays put on a failed cd is a shell that loses your place. Confirm the move with pwd, which you built yesterday for exactly this.

Make it work
if (strcmp(words[0], "cd") == 0) {
if (chdir(words[1]) != 0) { // ask the OS to move
fprintf(stderr, "cd: %s: %s\n", words[1], strerror(errno));
last_status = 1;
} else last_status = 0;
return;
}
CheckpointDONE
`cd` moves your shell around the filesystem, and a bad path fails loudly. Commit and stop here.