The purpose of this assignment is to introduce you to Java programming. You are to implement a simple shell (command interpreter) that behaves similarly to the UNIX shell. When you type in a command (in response to its prompt), it will create a thread that will execute the command you entered.
Multiple commands can be chained together on a single line, The commands can either be separated by `&' (ampersand) or `;'.
If the commands are separated by `&', your shell will create a thread for each individual command and prompt for more user input when they have all finished. If they are separated by `;' (semicolon) characters, your shell will first execute the first command, and then the second, and the third, so on. When all commands are finished, the shell will print a prompt for more user input.
You don't have to handle the situation where both `&' and `;' are used in the same command line. If they both appear in the same command line, the shell should print a message saying that it cannot handle the situation and ask the user to type a new command line.
Unlike the real shell, your program doesn't have to know how to run arbitrary programs, only the following ``built-in'' commands. On the other hand, you will have to implement these commands in Java rather than using standard Unix utilties.
cat file ... | Print the contents of the named files to System.out one after the other. |
cp file1 file2 | Copy the content of file1 to file2. |
rm file ... | Remove the files from the system. |
grepstr1 file1 | Print out all the lines in file1 that contains the string str1 to System.out. |
sort file | Print the lines of file in reverse lexicographic order. |
exit | Terminate the program. You should also terminate on reaching end-of-file on System.in. If an exit command appears on the same command-line with any other commands, the program should exit after the other commands complete. |
The cp command will be similar to cat, but this time the content of one file is copied to the other file. You can copy the content either line by line or byte by byte. You probably want to wrap the FileInputStream objects in BufferedReader objects for this command.
For the rm command, you should look at the class File to see the available operations on files.
For the grep command, you need to read a line from the file, and then check whether the given string is a substring of the line. To find out whether a string is a substring of another one, you should look at the indexOf method in the String class. The indexOf methods are also explained on page 162 of the Java book.
For sort, an efficient sorting algorithm is not required; anything that works is ok. You might want to adapt the insertion sort examples/SortTest.java used in the Java notes. Some of the classes that might help you here are BufferedReader and Vector.
To get the appropriate behavior for exit you might want to set a flag
and check for it in the main loop just before printing the prompt.
Using Threads
Your primary class will read a command from a user and then will create a
thread to carry out the command. It will then wait until the thread has
finished before continuing its own execution. There are two ways to start
threads in Java. The first is to derive your class from the Thread class and
then override its run() function (see pp. 181-183 in the text). The second is to use the Runnable
interface (pp. 201-202). With this approach, you create a class that
implements Runnable
and pass an instance of this class into the constructor of a
new thread object. Although the first approach seems simpler at first,
it is has some pitfalls, so we recommend using the second approach.
Exceptions
Java requires you to place within a try block any methods that might
cause an exception. Following the try block is a catch clause
(or catch clauses) that will
be used to catch any exceptions that have been thrown
See Java for C++ Programmers
and Chapter 7 of the Java book for more information about exceptions.
Your code should deal with
exceptions in an appropriate manner. For example, exceptions such as
attempting to open a file that does not exist should
result in a message to the user and the continuation of the program.
More serious exceptions may require an error message followed by program
termination (using
System.exit()).
Grading
Hand in your source program, a README file, and a transcript of a terminal session which demonstrates your shell's ability
to perform as specified (see script(1)). Be sure that you use test data adequate to exercise
your program's capabilities. You should follow all the principles of software engineering you learned in
CS 302 and CS 367, including top-down design, good indentation, meaningful variable names, modularity,
and helpful comments. You will be graded not only on the basis of correctness, but also programming
style and completeness of test data.
Other Stuff
For those of you writing your programs on the Solaris machines, you might consider using
a makefile to aid in compilation. Those of you using DOS may want to look into doskey,
a little program that provides for easy command manipulation. Feel free to send any other
work-saving methods you find to one of the TAs
Shankar, or
Mei-Guei,
and they will distribute them to the class.