Skip to content
Lesson 15 of 16

Step 1 of 5 · Reading · ~3 min

Read

Production Concerns

Capstone: The Whole Shell

After this lesson one program does what every earlier lesson did, in the right order: it expands variables, splits quoted input into words, expands wildcards, wires pipelines and redirections, runs the commands that must change the shell itself, and prints a plan for everything else. The tests here send lines that need several stages at once, because that is what "I built a shell" has to mean.

The pipeline, start to finish

One typed line goes through the stages in a fixed order:

StageWhat happensLesson
Tokenizequotes, backslashes, operators, IO numbers, comments1
Parameter expansion$NAME, ${NAME} and $? become text6
Field splittingunquoted expansion results split at spaces and tabs8
Pathname expansionunquoted wildcards become sorted matches7
Splitthe pipe operator cuts the line into pipeline stages2
Redirectionseach stage's <, >, >>, >& are applied left to right3, 11
Executebuiltins in the shell, everything else in a child4, 9, 10

In this lesson the first three happen inside the starter's lexer, because the shell must know which characters were quoted while it is still reading them.

Three rules the order creates

Expansion cannot create syntax. If X='a|b', then echo $X passes the single word a|b; the bar was never a token. Likewise a wildcard that came out of a variable is still expanded (P='*.c'; ls $P) but one that was quoted, or written as \*, is not.

A word that expands to nothing disappears: cmd $EMPTY x has two words. Only a quoted empty string, "", survives as an empty argument.

An assignment word such as NAME=value sets a shell variable. Its value is not field-split, so Y=$X keeps spaces intact.

Builtins and where they run

cd, exit, unset and assignments change the shell, so they must run in the shell. That holds only when the command is alone: as one stage of a pipeline, or with redirections, a command runs in a child, and cd /tmp | cat leaves the working directory unchanged. Your planner must therefore treat a builtin in a pipeline like any program.

The plan lines

For every stage of a pipeline of n commands print:

RUN <i>/<n> [word] [word] ... in=<..> out=<..> err=<..>

Each descriptor starts as - for the terminal, with standard input pipe for every stage after the first and standard output pipe for every stage before the last. Redirections change the table in order: file:<name>, append:<name>, a copy of another descriptor, or closed. Because the table is updated step by step, 2>&1 >f and >f 2>&1 differ, exactly as in the earlier lesson.

Common mistakes

  • Expanding globs before quote removal, so quoted wildcards still match.
  • Running cd for a stage of a pipeline.
  • Applying a redirection target through glob expansion.
  • Keeping a word that expanded to nothing, or dropping a quoted empty one.

Your exercise

The starter reads FILE lines (files relative to /home/user) and commands, and supplies the lexer, the wildcard matcher and the file system. You write run_line: pipeline splitting, assignments, builtins, redirection and the plan. The most likely mistake is running cd when it is only one stage of a pipeline.

Up nextJob Control: fg, bg and jobsProduction Concerns

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…