WeCodeAcademy

Step 3: Built-in commands

Some commands cannot be separate programs. cd changes the shell's own current folder; if it ran in a child process, the change would vanish when the child exited. So cd, pwd and exit are built-ins handled inside the shell with system calls chdir and getcwd. Watch the folder change in the output.

ExampleC
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#define MAX_ARGS 16

int tokenize(char *line, char *argv[]) {
  int argc = 0;
  char *p = line;
  while (*p != '\0' && argc < MAX_ARGS - 1) {
    while (*p == ' ') p++;
    if (*p == '\0') break;
    argv[argc++] = p;
    while (*p != '\0' && *p != ' ') p++;
    if (*p != '\0') *p++ = '\0';
  }
  argv[argc] = NULL;
  return argc;
}

// Built-ins must run inside the shell itself: a child process cannot change the shell's folder.
// Returns 1 if the command was a built-in.
int run_builtin(int argc, char *argv[]) {
  if (strcmp(argv[0], "pwd") == 0) {
    char buf[256];
    printf("%s\n", getcwd(buf, sizeof(buf)));
    return 1;
  }
  if (strcmp(argv[0], "cd") == 0) {
    const char *target = argc > 1 ? argv[1] : "/";
    if (chdir(target) != 0) printf("cd: no such directory: %s\n", target);
    return 1;
  }
  if (strcmp(argv[0], "exit") == 0) {
    printf("bye\n");
    exit(0);
  }
  return 0;
}

int main(void) {
  char *script[] = { "cd /usr", "pwd", "cd /nowhere/at/all", "pwd", "cd", "pwd" };
  char *argv[MAX_ARGS];
  for (int i = 0; i < 6; i++) {
    char line[100];
    strcpy(line, script[i]);
    printf("tiny> %s\n", line);
    int argc = tokenize(line, argv);
    if (argc > 0) run_builtin(argc, argv);
  }
  return 0;
}
Output
tiny> cd /usr
tiny> pwd
/usr
tiny> cd /nowhere/at/all
cd: no such directory: /nowhere/at/all
tiny> pwd
/usr
tiny> cd
tiny> pwd
/

Notice that the failed cd /nowhere/at/all reports an error, leaves the folder unchanged (pwd still says /usr), and the shell carries on: a shell must never crash on a bad command. A bare cd goes to / here (a real shell goes to your home folder).

Quick check

Why can cd not be a separate program?

Finish the quick check (and any code exercise) to complete this lesson, or mark it done yourself.

Tip: use the left and right arrow keys to move between lessons.