Assignment 2 -- 50 points

Due: Monday, September 29.

Summary: Implement the Fantastically Inane SHell, hereafter known as fish. This interactive shell will allow you to change subdirectories, and execute external Unix programs. For extra credit, it will be able to run processes in the background, similarly to ksh.

Detail: When fish is first executed, it should print out a "fish$" prompt, and allow the user to input a single line of text. This line of text should be parsed (I suggest using the strtok() function for this) into separate words (separated by spaces or tabs) and stored in a "char *arg[]" so it can be passed to execvp().

Once fish calls execvp() to run the external program, it should call wait() to wait for the process to complete before issuing another prompt. (This won't be the case if you're implementing the extra credit, below.)

Not all commands will be sent to exec, however. The shell will implement two internal commands: cd and exit.

The cd command takes a single argument: the name of the directory to change to. fish will pass this argument to the system call chdir() to actually change its directory.

The exit command can take a numerical argument which will be used to for fish's call to exit(). If no argument is given, fish will call exit(0).

Both cd and exit should check to see that the correct command line arguments are passed to them, and should print out a message to stderr in case of error.

Misc notes: External commands must be executed using the fork/exec combination! Use of the system() library call is not allowed.

You don't need to implement any special shell features like wildcards, quotes, escapes, variable substitution, job control, aliases, non-interactive processing, script flow control, etc., etc. Relax.

Extra Credit: For 7 (seven) points, modify the shell so that if the last argument for an external command is "&", it will run that process "in the background" and return you to the "fish$" prompt immediately. The shell should print the following message to stderr:

   fish: background process %d started

where %d is the PID of the background process. Likewise, when the process dies, the shell should print:

   fish: background process %d died

When the process dies, you may print the death message asynchronously; you don't need to wait until the next "fish$" prompt like ksh does.

Remember that you will have to call wait() sometime to handle the zombies as your background processes die. To do this, implement a signal handler to catch SIGCHLD. All this signal handler will have to do is call wait() and print the above message.

You are not allowed to handle zombies by ignoring SIGCLD (as opposed to SIGCHILD). Additionally, you must use sigaction() to set up the handler, not signal().

Note that the "&" must be separated from the last actual argument by a space or tab. While "xterm&" would not need to work, "xterm &" would work. This can simplify your command line parsing.

Sample Usage: Here is a sample run from an implementation of the fish shell:

	$ fish
	fish$ ls
	Makefile  fish      fish.c    fish.o
	fish$ make
	make: Nothing to be done for `all'.
	fish$ xterm &  [Extra Credit!]
	fish: background process 20891 started
	fish$ ls
	Makefile  fish      fish.c    fish.o
	fish: background process 20891 died
	fish$ cd ..
	fish$ pwd
	fish$ ls
	a.out     telnettalk.c        fish
	fish$ ls -l telnettalk.c
	-rw-r--r--   1 beej     users        1538 Aug 14 14:11 telnettalk.c
	fish$ cd
	usage: cd directory
	fish$ exit 1 2
	usage: exit [n]
	fish$ exit 2
	$ echo $?

Directory structure: Please place the sources for this program in your ~/298C-02/prog2 directory.

The Makefile: Implement a Makefile for this project. It will be a bit simpler than the one for assignment 1. We should be able to simply type "make" and it will build your shell.

Late Policy: 5 (five) points per day, as the clock rolls over midnight.