Try Firefox!

Lab 7: A mini shell


Lab setup
  1. Create a directory lab07 for this lab
  2. Copy this compressed archive file to the above directory:
                  ~wcbrown/courses/IC221/labs/L07/lab07.tar.gz
    	    
  3. Unzip and untar the archive.

Background
In this lab you will be creating your own mini-shell --- i.e. your program will read in command-lines, distinguish between program name, command-line arguments and < for redirection, and launch new processes matching the command. It will require you to use fork and exec (hopefully that's obvious) and it will also require you to change standard input when you receive commands like "mmame < foo.txt". This we'll do at the file descriptor level (though there's a handy function called freopen you could use instead). So ask yourself: Which file descriptor is "standard in"? How do I change that file descriptor so that it refers to a connection to some other file?

mmame: a better mma
The tar archive contains code for an "enhanced" version of the mma (min-max-average) utility called mmame --- the last m is for median, and the e is for enhanced. This version acts like mma when reading from stdin, i.e. reading until end-of-file (^D, CONTROL-D) is encountered, then printing the results:
$ mmame                                   mmame reads from stdin
1 2 3                                     the user enters data
^D                                        the user indicates end-of-input
1.000 3.000 2.000 2.000                   results are printed
$                                         back to the shell prompt
The enhanced version will also read from a file named on the command line, but after the file has been processed, the program continues reading from standard input! $ mmame test_data.dat mmame reads data from test_data.dat ^D the user indicates end-of-input 55.000 32767.000 16650.824 16633.000 results are printed $ back to the shell prompt Note that results are not printed until the user enters ^D. This allows the user to continue entering data from stdin after mmame first reads data from the named file:
$ mmame test_data.dat                    mmame reads data from test_data.dat
1 2 3                                    the user continues to enter values
^D                                       the user then indicates end-of-input
1.000 32767.000 16601.027 16617.000      results are printed
$                                        back to the shell prompt
mmame behaves differently when the shell redirects stdin to read from a file, as follows:
$ mmame < test_data.dat                  mmame reads from stdin (redirected from test_data.dat)
55.000 32767.000 16650.824 16633.000     results are printed
$                                        back to the shell prompt
	
Notice that ^D is not entered by the user when IO redirection is handled by the shell.

The command make mmame will compile-and-link the program. Do that, and experiment with it a little bit.

Part 1: Minimal minishell (70 Points)
For Part 1 of the project you are to create a program named minishell. You are given skeleton code for minishell in a file named minishell.c. This is your starting point. If you give the make command, it'll be compiled-and-linked ... although the version your given doesn't do anything. Read the source code and follow the numbered comments! (Note: comments are the the red pieces of text between the /* and */ ... just in case some of you are unfamiliar with them.) minishell works as follows:
  1. The minishell prompt is "IC221> "
  2. minishell reads "minishell commands" from stdin, but it is a very simple shell: it "understands" only how to run the program named on its command line. We're testing the minishell with the mmame program, but you may NOT assume the user won't try to run a program other than mmame.
  3. Your minishell should read user input, then fork/exec as appropriate to execute mmame.
Here are some examples of the minishell in action for a correct Part 1 solution:

Part 2: Reading direct from file (10 Points)
Add to a correctly functioning Part 1 the ability to execute mmame reading directly from a file. Do not attempt Part 2 unless Part 1 works completely and correctly. Here's are two example of the minishell in action for a correct Part 2:
$ minishell
IC221> mmame test_data.dat
^D 
	55.000 32767.000 16650.824 16633.000
IC221> mmame test_data.dat
1 2 3
^D
1.000 32767.000 16601.027 16617.000
IC221>

Part 3: Input Redirection (10 Points)
Add to a correctly functioning Part 2 the ability to execute mmame using input redirection. Do not attempt Part 3 unless Part 2 works completely and correctly. Here's an example of the minishell in action for a correct Part 3:
    IC221> mmame < test_data.dat
    55.000 32767.000 16650.824 16633.000
	
You may assume that only well formed commands are entered on your minishell command line. A well formed command looks like this:
    mmame < filename
	
You DO NOT have to worry about handling lines like these:
    mmame Test_Data.Dat < 	(< In The Wrong Location)
    mmame <Test_Data.Dat  	(Missing Space After <)
    mmame <               	(Missing Filename After <)
    < mmame Test_data.dat 	(mmame not first)
	
You also do NOT need to deal with background jobs: you can assume the '&' character will never appear on your minishell command line. Of course, a shell like bash does have to deal with these things, but for this project, we're interested in you showing how the shell prepares for and does an exec, not in you showing how to parse the command line.

Part 4: Questions (10 Points)
Answer the following questions regarding the skeleton code we gave you. Put your answers in a file named answer.txt:
1) Do a man on fgets and answer the following questions:

   a) Briefly explain what fgets does.

   b) Why is it recommended that fgets is used instead of gets?

   c) Will '\n'  appear in the string fgets returns?

   d) What does fgets return if end-of-file is reached and no bytes
      have been read?

2) Explain what the function strrchr does.

3) Explain the difference between sscanf and fscanf?

4) Explain how sscanf and strstr are used together to extract tokens
   (or words) from the command line string.

5) If your minishell was going to support "&" with the same
   meaning as bash, what (briefly) would change in your implementation.


	  

Submission instructions
Follow the usual submission rules and submit your lab07 directory. It must include your answers to the above questions in answers.txt, and a file README that includes your name, alpha and whether the file minishell.c in your submission is a Part 1, Part 2 or Part 3 solution. As usual, your submission should be the last one that you got functioning properly!


Christopher W Brown
Last modified: Wed Feb 25 16:08:58 EST 2009