| OpSys Fall 2006 - HW3 |
|   OpSys Home   |   Assignment   |   Requirements   |   Submitting   |   Resources |
- Unix Shell
The objectives of this assignment are:
You are to write a simple Unix shell (the shell is simple, but this assignment is not!). Your program should read commands from the user (use readline!) one line at a time, and for each line the shell attempts to process the user command.
There are two basic kinds of commands that your shell must handle:
built-in commands (that your shell handles itself) and external
programs (the shell starts a new process which then executes the
external program). The details of how to handle each of these types of
commands is shown below. Your shell must support an unlimited number
of pipes between external commands, automatically directing the output
of one external command to the input of another. Your shell must also
support I/O redirection (arranging it so that external commands will
read from, or write to, a file). Finally, your shell
will use the environment variable OSPATH as a list of
directories in which to search for external commands.
- Shell prompt
The prompt output by your shell when asking for a line of input must be the name of the current working directory followed by a space (NOT the entire path, just the name of the current directory). The result should be something like this (sample session in which user input is shown in blue):
fred ls opsys proglang rpi.gif stolenmusic fred cd opsys opsys ls hw1 hw2 hw3 opsys
- Shell internal commands
There are a few commands that your shell must recognize and deal with directly - these commands are listed below. For each of these commands, the shell should not create any new processes! You do not need to be able to support using pipes with any shell internal command.
The actual commands you need to support are shown below, you must use the exact syntax described (otherwise our testing scripts won't work with your shell).
cd:   The cd command allows the user
to change the current working directory while using your shell.
You need to support relative and absolute paths. If the user
enters the cd command with no arguments, the shell
should use the environment variable "HOME" to determine what
directory to change to. If the user does not enter any arguments and
there is no HOME environment variable (or it's value is empty), the
cd command should not change the directory.
If there is an argument to the cd command, the shell
should attempt to switch to that directory (issue the
"chdir()"
system
call). If this fails the user should be told so!
set:   The set command is basically the
same command you implemented in HW1, with the addition of the
keyword set. You need to set an environment
variable specified by the user. The full syntax is just like in
homework #1:
set varname = somevalue
print: The print command is also
just like in HW1:
print varname
The command should print out the value of an existing environment variable
where: The where command is used
to find out what executable file corresponds to a specific command.
For example, if you type "where ls", the shell should print out the
full path to the ls command (something like "/usr/bin/ls"). This
command should use the OSPATH environment variable
as a list of directories in which to look for the command. Note
that the shell needs to find a file with the right name, and the file
must be executable (or the shell should ignore it).
The OSPATH environment variable is modeled after the
PATH variable that is actually used by real Unix
shells. OSPATH is a single string that includes a list
of directorys (relative or absolute) delimited by colons. For
example, here is an OSPATH that tells the shell to
look in /usr/bin, then in /usr/local/bin
and finally in the current working directory:
set OSPATH = /usr/bin:/usr/local/bin:.
It is possible that the user types in the complete path to a file, for example the user could type "where /opt/foo/sillyface". In this case your shell should report that this is located at "/opt/foo/sillyface". Note that the user could also type "where ./foo" and you must handle this as well. In general if the command starts with either "/" or "." you need to treat the command as a complete path, otherwise treat is as a filename (that could be anywhere in the OSPATH).
Note that when the shell encounters an external command (anything
other than the 4 commands listed above), it will search for a file
based on the OSPATH - so it makes sense to write a function that
does this search - the same function can then be used by the
where command and by the shell when executing an
external command.
- Command lines involving external commands.
If the user input does not match any of the internal commands
listed above, your shell must attempt to find an executable file with
the same name as the command, and to run the command. If the command
name includes the character "/" - the user is specifying a
path to the executable file. If the command name doesn't specify a
path - your shell should assume it is a file name, and should
use OSPATH to locate the actual executable file.
Your shell must support any number of command line arguments, for
example the user could type "ls -al foo.c blah.h" and you need to make
sure the ls command receives the command line
arguments. Your shell does not need to support any special characters
like "*" or "?", so if the user types in "ls *.c" you just pass along
the "*.c" to the ls command (a real shell would replace
this with the name of all files that end in .c).
Your shell must support an unlimited number of pipes - this means
that each command line could include a number of external
commands. Note that you do not need to support pipes with internal
commands. For each pipe in the command line you need to take care of
connecting stdout of the left command to stdin of the command
following the "|". For example, if the user types "ls -al | sort", you
need to arrange is so that the ls command is run with
stdout directed to a Unix pipe, and that the sort command
is run with stdin coming from that same pipe.
Your shell must support I/O redirection. If an external command is followed by "<", it must read input from the named file. For example, the command line "sort < foo", means that sort should be fed the file foo via stdin. If an external command is followed by a ">", out must arrange it so that stdout of the command is directed to a file. For example, "ls > save" means that the ls command should save it's output to the the file named "save". It is possible that you could have both on the same command, for example: "sort < infile > outfile".
You do not need to support redirection of standard error.
Your shell should be able to handle something like this:
ls -al | cut -c31- | sort -rn > foo
If the user tries something silly (ambiguous) like this (which indicates two sources of input for the sort command):
ls -al | sort < foo
You can do whatever you want, as long as this doesn't crash your shell. An error message would, of course, be nice...
- Project Requirements
The following are the requirements for the project:
Your program must compile and run on the CS department FreeBSD
machines (freebsd.remote.cs.rpi.edu).
Your shell must use the name of the current working directory as the prompt (just the name, not the path).
Your shell must support the internal commands
chdir,
set, print and where. Feel
free to include other internal commands if you find this useful for
your own testing.
Your program must use the environment variable
OSPATH as a list of directories to search. It is
possible that this environment variable will exist when your shell
is started (inherited from the real shell), it is also possible that
it will be set using the set internal shell
command.
For command lines that do not involve an internal command, your shell must support multiple commands (including options) separated by "|", and your shell must arrange the automatic creation of Unix pipes that facilitate the connection between individual commands. Your shell must also support I/O redirection for external commands.
Your shell should print some kind of error message whenever it can't find a suitable file for an external command, or when anything unexpected happens (exec fails, can't create a pipe, etc). You must include code that checks the return value of every single ittsy-bitsy system call! All of them. Really!
Your submission must include a Makefile we can use to build your shell on the CS FreeBSD machines. See the HW1 FAQ for information on building a simple Makefile
Your submission must include a file named README that includes the following information:
Grading: Your code will be graded according to the formula below. Note that to get full credit we must be able to understand your code (it must be commented!)
| 20% | Internal commands properly implemented, this includes proper
parsing of internal commands and proper output generated by the
where and print commands. |
|---|---|
| 30% | External commands properly implemented, this includes sending command line arguments to external programs. |
| 10% | File I/O redirection (support for "<" and ">") works properly. This is only needed with external commands. |
| 20% | Pipes work with external commands properly. There should not be any limit (imposed by your program) on the number of pipes in a single command line. |
| 10% | Impossible to crash the program. Basically you need to make sure there is nothing we can do (there is no input we can send to your shell) that can cause your program to crash (for example, SEGV). Check the return value of all system calls (check for errors)!. Keep track of dynamically allocated memory (and free anything that is not needed). |
| 10% | Code quality (comments, organization, how hard is it to understand ?). |
You can get partial credit for any part.
If you code does not compile and run under FreeBSD, you will lose at least 1/2 the relevant points ( partial credit will be awarded based on visual inspection of the code).
- How to Submit
Log in to WebCT at webct.rpi.edu using your RCS id and password. Once you get to MyWebCT click on "Operating Systems", and from there go to the homework drop boxes. Submit your files (individually, zipped or tarred) to the drop box labeled HW3.
-Resources