Programming Assignment #3

Due: Friday 11/9/01

Overview

This assignment asks you to write your own shell, using the fork, exec, and wait system calls.  The purpose is to get you familiar with Linux/Unix processes, creating them, passing arguments, inheriting open files, waiting for them to terminate, getting their exit status, background processes, and so on.  You will write your shell in C.

 

In this assignment you will write your own shell, called minish.  This will work like the bash shell you likely use when using Linux, prompting for a command line and running commands, but it will not have many of the special features of the bash shell.  Your shell will allow for the redirection of standard input and standard output and it will support both foreground and background processes.  Your shell will support three built in commands: exit, cd, and status.  It will also support comments, lines beginning with the # character.

 

Command Line

The general syntax of a command line is

 

                [bg:] [in: input_file] [out: output_file] command [arg1 arg2 …]

 

where items in square brackets are optional.  You can assume that a command is made up of words separated by spaces. 

 

If the command is to be executed in the background, the first word must be bg:.  If standard input or output is to be redirected, the in: or out: words followed by a filename word must appear after the bg:, if it is present, and before the command itself.  Input and output redirection can appear in either order.

 

Your shell does not need to support any quoting; so arguments with spaces inside them are not possible.  Your shell should support command lines of at least 2048 characters, with at least 500 arguments.  You do not need to do any error checking on the syntax of the command line, you can assume it follows the rules given here.

 

The prompt for each command line should be your last name followed by the ‘>’ character.

 

To help you out with the parsing of the command line (which is not the point of this

assignment) some simple parsing code has been given in the “code” section of this handout.

 

Command Execution

You will use fork, exec, and wait to execute commands.  The shell will wait for completion of foreground commands (commands without the bg:) before prompting for the next command.  The shell will not wait for background commands to complete.

 

The shell will allow the user to get the exit status of the previous foreground command with the status command.  If a command is terminated by a signal, a message indicating which signal terminated the process will be printed. When a background process is started your shell will print out its process id; when it finishes, the shell will print out its process id and exit status. You should print the exit status or terminating signal of any completed background processes just before you prompt for a new command.  You will need to use waitpid to check for completed background processes.

 

If a command fails because the shell could not open a file for redirection or because it could not find the command to run, then the shell will report an exit status of -1.  (Note, this will be implemented in SEVERAL places.  Think through the termination of any attempt you make).

 

Be sure that a control-C interrupt from the keyboard does not terminate your shell, but only the foreground command it is running.  Background commands should not be terminated by a control-C signal.  To accomplish this you will need the line

 

    signal( SIGINT, SIG_IGN );

 

at the beginning of your shell.  After forking a foreground process (but not a background process) you will need the line

 

    signal( SIGINT, SIG_DFL );

 

to indicate that the foreground process should take the default action for a control-C, which is to terminate the process.  You will need to have #include <signal.h> in any files that make these signal calls.

 

Built in Commands

Your shell will support three built in commands: exit, cd, and status. 

Finally, your shell should allow blank lines and comments; any line that begins with the # character is a comment line and should be ignored.

 

Grading  and Submission of the Project

Your final version of this assignment is due no later than Friday, November 9th at the beginning of class.  You should turn in your C source code on a floppy disk, in a file labeled minish.c, and a printout of your final code in the manila envelope you were provided during PA#2.  You may turn in the project as many times as you like in the next three weeks.  Each time you turn it in I will test it and notify you of problems or errors which will cost you points during final grading.  While I do not make any guarantees, I will make every effort to have turn around time be no more than 24 hours.  Only the version submitted on 11/9 will be considered for grading purposes.

 

Helpful Code/References/Hints

const char *delim = " ";

 

fgets(BUFF,MAX_CHARS,stdin);

 

            BUFF[strlen(BUFF)-1]=’\0’;

            arg_count=0;

args[arg_count] = strtok(BUFF,delim);

while (args[arg_count] != NULL) {

arg_count++;

args[arg_count]=strtok(NULL,delim);

}

You will configure this in two ways for use in this lab.  If PID>0 then the method waits until that specific process is complete.  If PID = -1 then it waits until ANY process completes.  If FLAG=0 then the method blocks and waits until there is a complete process.  If FLAG=WNOHANG then the method just CHECKS to see if the process (or multiple processes) has completed.  The PID2 returned is the PID of the finishing process or 0 if no process has completed (obviously, this is only a possibility with the WNOHANG flag).