Assignment 3: Shelling Things
Out on:
February 11, 2008
Due by:
February 27, 2008, 11:00 am (before lecture)
Collaboration:
Pairs
Grading:
Packaging 10%, Style 10%, Performance 10%, Design 10%, Functionality 60%
Overview
The third assignment is all about writing your own shell. You'll need a partner for this one, watch out for details on the course mailing list. The assignment comes in two parts, mostly to help you decide how much effort you want to put into it. In the first part you implement the basic functionality of a shell, in the second part you extend the shell in various ways. I suggest that you try to finish Problem 1 by February 18, 2008, that way you'll have another week for extensions.
Problem 1: Shell Core (50%)
A shell is the most common interface between a Unix user and the Unix system. It is responsible for parsing and executing your commands. A minimalist shell will do nothing more than this, a good one will add file redirection, pipes, backticks, environment variables, aliases, wildcard expansion, running commands in the background, a command history, and a host of other features.
Your shell should not make use of existing "shell-like" functionality, you should build everything from "ground up"; if in doubt, a quick email to the discussion list might be a good idea before you start using something we'll deduct points for. Anyway, here are the core features that your shell must implement.
- prompt for a command and read a command
- parse the command (setting up argc and argv) and execute the command
-
support the
PATHenvironment variable as expected of a shell - make sure that signals are handled as expected of a shell
-
the "
cd" command to change the current working directory; be sure to handle all relevant errors for this (not a directory, permission denied, file not found, etc)
Not much to do for a basic shell, is there? But if you feel tired for some reason, this at least gets you half of the points (provided you do it correctly of course).
Problem 2: Shell Extensions (50%)
Here is where the fun part of the assignment starts.
You can try to implement as many of these as you like,
or make up more as you go along; also see the Hints
section below... :-)
Just be sure to document all the functionality
you have implemented in your README file so we know
what to look for.
-
Implement pipes,
that is the "
|" operation. For a command string "A | B", let A's standard output feed into B's standard input. You should handle repeated pipes as in "du | sort -rn | less" as well. -
Implement backticks, that is the "
`" operation. For a quick introduction compareecho unameagainstecho 'uname'againstecho `uname`. -
Implement file redirection, that is the "
<", ">", and ">>" operations. For example "ls > fooshould store the directory listing in the filefoo. -
Implement background commands, that is the "
&" operation. Check for backgrounded process termination each time before printing your shell prompt and print out a message for each process that terminated. -
Implement wildcard substitution or
globbing.
This is similar to yet different from regular expressions.
If there are files
1.txtand10.txtin the current directory, the command "A ?.txt" should expand to "A 1.txt" while the command "A *.txt" should expand to "A 1.txt 10.txt" instead. An asterisk stands for "zero or more" letters, while a question mark stands for "exactly one" letter. - Implement a command history. The up and down arrow keys should scroll through a history of the last 100 or so commands that you have entered.
-
Implement escape characters. For whitespace and any special characters
that you have implemented, if they are preceded by a "
\", then interpret them as non-special characters. -
Implement aliases.
Use either
bashortcshsyntax. -
Implement environment variables.
Use either
bashortcshsyntax. -
Implement environment variable substitution.
Replace "
$NAME" with the value of the variableNAME. You should allow for substitution everywhere it is sensible, using the "${NAME}" syntax if necessary. Experiment withbashif necessary.
If you have implemented something in addition to
all these features, be sure you explain how to use your feature in
your README file.
Hints
- Feel free to use the functions for error handling from our text, and (of course) actually handle all error conditions that can arise.
- Modularize your code "properly" into key abstractions. Functions are your friends, independent compilation is your friend, etc.
-
Remember that you can put shell commands into a file and then
do "
sh file" to run them? Maybe your shell should be able to do that as well... -
Ideas for more features? The
manpages for a variety of Unix shells such asbashortcshorzshorfishor whatever should provide plenty of ideas. Adding a builtinlscommand might be good exercise as well. Finally, I think a full-screen curses-based shell with screen splitting and status lines would be cool. Or you could allow arbitrary text-based windows... :-)
Deliverables
Please turn in a
gzip
compressed
tarball
of your assignment;
the filename should be
cs211-assign-3-login1-login2.tar.gz
with login? replaced by your Unix login names
on ugradx.cs.jhu.edu.
The tarball should contain no derived files whatsoever
(i.e. no executable files),
but allow building all derived files.
Include a README file that briefly explains what your
programs do and contains any other notes you want us to check out
before grading.
We expect that your Makefile handles "the usual" targets
like clean and test aside from all
(which is the main way we will build your program).
Include other "common" files such as INSTALL describing
how to install your tool, CREDITS to pay your respects
to the people whose code you're reusing, and LICENSE
to describe copyright and distribution terms if you feel like it.
You can look at any number of "famous" open source projects to see
what kind of structure is appropriate;
gif2png
is a relatively small example, but you don't need everything in
there.
Aside from your code, what you really need is a README
and a Makefile that works. :-)
Grading
For reference, here is a short explanation of the grading criteria.
Packaging refers to the proper organization of the
stuff you hand in, following the guidelines for Deliverables above.
Style refers to C programming style, including
things like consistent indentation, appropriate identifiers,
useful comments, suitable documentation, etc.
Simple, clean, readable code is what you should be aiming for.
Performance refers to the amount of resources
your program needs to produce the required results; this can
include space, time, and other metrics.
Design refers to proper modularization and the
proper choice of algorithms and data structures; often this can
be judged by asking "How hard would it be to add feature X?"
and "How hard is it to replace algorithm X with algorithm Y?".
Functionality refers to your programs being
able to do what they should according to the specification
given above; if the specification is ambiguous and you had
to make a certain choice, defend that choice in your
README file; if the specification is too general
and you had to add certain restrictions, defend those in your
README file as well.
If your programs cannot be built on ugradx.cs.jhu.edu
you will get no points whatsoever.
If your programs cannot be built without warnings using
gcc -ansi -pedantic -Wall -Wextra -std=c99 -O
we will take off 10% (except if you document a very good reason).
If your programs cannot be built using make we will
take off 10%.
If your programs fail miserably even once,
i.e. terminate with an exception of any kind or dump core,
we will take off 10%.
Finally, make sure to include your name and email address in
every file you turn in!
Kudos
This assignment is based on a similar assignment designed by Titus Winters at the University of California, Riverside. Thanks a bunch, dude! :-)