CAS CS 552
Programming Assignment 1

Due: September 21, 1999 



The purpose of this assignment is to introduce you to Java programming. You are to implement a simple shell (command interpreter) that behaves similarly (but not identically) 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 entered on a single line, separated by `&' (ampersand) characters. Your shell will create a thread for each individual command and prompt for more user input when they have all finished.

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 utilities.
cat file ... Print the contents of the named files to System.out one after the other.
cmp file1 file2 Check whether the two files have identical contents and print an appropriate message to System.out.
sort file Print the lines of file in sorted (lexicographic) order.
exit Terminate the program. You should also terminate on reaching end-of-file on
You do not need to implement pipes or re-direction of standard input and standard output, but you must be able to handle an arbitrary number of commands per line -- each with an arbitrary number of arguments separated by arbitrary amounts of white space (blanks or tabs). Only cat may take more than two arguments, but your program must gracefully recover from such errors as unknown commands, wrong number of arguments, or non-existent files by printing an error message and continuing. 


This project is not as hard as it may seem at first reading, because most of the hard parts have already been done for you by the standard Java library. It involves finding the relevant library routines and calling them properly. Your finished program will probably be under 200 lines, including comments.

Your public static void main() procedure in your primary class will be quite simple. It will be an infinite loop that prints a prompt, reads a line (in other courses, a program with an infinite loop is considered a bad thing, but in Operating systems, it's the norm!), parses it (breaks it up into its constituent commands), starts a new thread to handle each of the different commands, and then waits for all the threads to finish before printing the next prompt. 

You should find Marvin Solomon's note on Java for C++ Programmers useful.


For parsing, you may find it easier to read the entire line into a String object. The stream object, which gets the keyboard input, is of type InputStream, so it can read either single bytes or arrays of bytes. You could represent an input line as an array of bytes, but you will find it much easier to use a String instead. You may want to look into the class BufferedReader to figure out how to read a line into a String. Tokenizing a String is made almost trivial using the StringTokenizer class found in java.util


For the cat command, you should look at the class FileInputStream to see how to read data from a file. The cmp command will be similar to cat, but this time the contents of the two files will be compared, line by line. You probably want to wrap the FileInputStream in a BufferedReader for this. For sort, an efficient sorting algorithm is not required; anything that works is ok. You might want to adapt the insertion sort used in the Java for C++ Programmers note. Some of the classes that might help you here are BufferedReader and Vector

Using Threads

Your primary class will read a command line from a user and then will create threads to carry out the commands on the line. It will then wait until the threads have 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-182 in the Java book). 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. Using the second approach is recommended. 


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()). 


Note: This project must be done individually. The remaining Java projects will be done in teams of two.

Hand in your source program and a transcript of a terminal session which demonstrates your shell's ability to perform as specified; see the UNIX command script(1): Simply type the command "script". You will see the message
    Script started, file is typescript
After that, everything you type in and everything sent to the screen will be saved in the file "typescript". When you are done with your demo, type "exit" (to the UNIX shell, not to your program!), and you should get the message
    Script done, file is typescript

Submit all your .java source files, the typescript file and any other required files. Do not submit any .class files. 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 112 and CS 113, 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.

See guidelines for electronic submissions of programming assignments.

Back to CAS CS 552 home page