+#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], *cp;
+ char command[80];
- /* Prompt. */
+ /* Read command. */
printf ("--");
-
- /* Read and echo command. */
- cp = command;
- for (;;)
- {
- char c;
- read (STDIN_FILENO, &c, 1);
-
- switch (c)
- {
- case '\n':
- /* Done. */
- goto got_cmd;
-
- case '\b':
- /* Back up cursor, overwrite character, back up again. */
- printf ("\b \b");
- break;
-
- case 27: /* Escape. */
- case ('U' - 'A') + 1: /* Ctrl+U. */
- /* Clear entire line. */
- printf ("\n--");
- cp = command;
- break;
-
- default:
- /* Add character to line. */
- *cp++ = c;
- if (cp >= command + sizeof command - 1)
- goto got_cmd;
- break;
- }
- }
- got_cmd:
- *cp = '\0';
- putchar ('\n');
+ read_line (command, sizeof command);
/* Execute command. */
if (!strcmp (command, "exit"))
break;
- else if (cp == command)
+ else if (command[0] == '\0')
{
/* Empty command. */
}
printf ("Shell exiting.");
return 0;
}
+
+/* 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 '\n':
+ *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;
+}