+#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. */
- for (cp = command; cp < command + sizeof command - 1; cp++)
- {
- read (STDIN_FILENO, cp, 1);
- putchar (*cp);
- if (*cp == '\n')
- break;
- }
- *cp = '\0';
+ read_line (command, sizeof command);
/* Execute command. */
- if (cp > command)
+ if (!strcmp (command, "exit"))
+ break;
+ else if (command[0] == '\0')
+ {
+ /* Empty command. */
+ }
+ else
{
pid_t pid = exec (command);
if (pid != PID_ERROR)
- join (pid);
+ printf ("\"%s\": exit code %d\n", command, wait (pid));
else
printf ("exec failed\n");
}
}
+
+ 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;
}