diff --git a/src/examples/shell.c b/src/examples/shell.c new file mode 100644 index 0000000000000000000000000000000000000000..6372ccc7d1678f2a6b0a325b5f7e8b6b2098b2bd --- /dev/null +++ b/src/examples/shell.c @@ -0,0 +1,104 @@ +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <syscall.h> + +static void read_line (char line[], size_t); +static bool backspace (char **pos, char line[]); + +int +main (void) +{ + printf ("Shell starting...\n"); + for (;;) + { + char command[80]; + + /* Read command. */ + printf ("--"); + read_line (command, sizeof command); + + /* Execute command. */ + if (!strcmp (command, "exit")) + break; + else if (!memcmp (command, "cd ", 3)) + { + if (!chdir (command + 3)) + printf ("\"%s\": chdir failed\n", command + 3); + } + else if (command[0] == '\0') + { + /* Empty command. */ + } + else + { + pid_t pid = exec (command); + if (pid != PID_ERROR) + printf ("\"%s\": exit code %d\n", command, wait (pid)); + else + printf ("exec failed\n"); + } + } + + printf ("Shell exiting."); + return EXIT_SUCCESS; +} + +/* Reads a line of input from the user into LINE, which has room + for SIZE bytes. Handles backspace and Ctrl+U in the ways + expected by Unix users. On return, LINE will always be + null-terminated and will not end in a new-line character. */ +static void +read_line (char line[], size_t size) +{ + char *pos = line; + for (;;) + { + char c; + read (STDIN_FILENO, &c, 1); + + switch (c) + { + case '\r': + *pos = '\0'; + putchar ('\n'); + return; + + case '\b': + backspace (&pos, line); + break; + + case ('U' - 'A') + 1: /* Ctrl+U. */ + while (backspace (&pos, line)) + continue; + break; + + default: + /* Add character to line. */ + if (pos < line + size - 1) + { + putchar (c); + *pos++ = c; + } + break; + } + } +} + +/* If *POS is past the beginning of LINE, backs up one character + position. Returns true if successful, false if nothing was + done. */ +static bool +backspace (char **pos, char line[]) +{ + if (*pos > line) + { + /* Back up cursor, overwrite character, back up + again. */ + printf ("\b \b"); + (*pos)--; + return true; + } + else + return false; +}