Programming Assignment 2
Due 11:59PM Monday Sept 20

For this assignment you are to write a simple shell. It should enter an infinite loop which repeatedly does the following:

  1. Displays a prompt ( > )
  2. gets a command line from the user
  3. parses the command line
  4. executes the command
The command line entered by the user should consist of a command, which can be either a relative or absolute pathname, followed by zero or more arguments followed by input and output redirection. Either stdin or stdout or both or neither can be redirected.

If the user appends an ampersand (&), the process should run in background.

The following are all valid command lines

a.out
a.out arg1 arg2
a.out arg1 arg2 > outfile < infile
a.out arg1 arg2>outfile &
A variant of this assignment has been given in this class for many years. The hardest part of this for most students seems to be parsing the command line, and that is not really an important part of an operating systems course, so this has been done for you. There is a file ParseCommandLine.h which you can download. This defines a struct CommandData which will contain all of the data from the command line which you need to execute the command.

struct CommandData {
  char *command;  /* the pathname of the command */
  char *args[11]; /* arguments to the command */
  int numargs;    /* the number of arguments */
  char *infile;   /* the file for input redirection, NULL if none */
  char *outfile;  /* the file for output redirection, NULL if none */
  int  background;  /* 0 if process is to run in foreground, 1 if in background */
};
It also defines a function
int ParseCommandLine(char *line, struct CommandData *data)
which takes two arguments, the command line exactly as it is entered by the user, and a pointer to a CommandData struct (the memory for this has to have been allocate by the calling function). This function parses the command line and populates the CommandData structure. It returns 1 if there were no errors and 0 if the user entered an invalid command. In the latter case, the contents of data are undetermined.

Some characters which have special meaning for a real shell cannot be used with this shell. Command names and pathnames can only use the following characters: upper or lower case letters, digits, underscore, slash, hyphen, or dot. The <, >, and & characters have special meanings and cannot be used in file names. Any other character such as a dollar sign, star, question mark, quotation mark, comma, pipeline, double quote, or tilde, will generate an error condition in the ParseCommandLine function. Filenames and pathnames cannot have spaces in their names.

If the command is quit your program should terminate.

Your shell should execute the command, redirecting stdin and stdout as necessary, and passing arguments to the program. Note that by convention (and thus, for this assignment), argv[0] is the actual command, and you will have to fill this in. If the command line is
a.out arg1 arg2 < infile > outfile
when a.out is started, the value of argv[0] should be a.out, the value of argv[1] should be arg1, and the value of argv[2] should be arg2.

Your shell does not need to search paths. All relative path names should start at the current working directory. Note that this means that if the command line is ls, your program would reply command not found (unless there happened to be an executable with the name ls in the current directory). To run ls, the user would have to type /bin/ls (and note that your shell would have to set argv[0] to ls).