502 Project 1

Mini Shell

Due date: Thursday, June 2nd by 11:59pm



This assignment is intended to introduce you to some system calls and process manipulation facilities from an Operating System. You are to implement the program described below on any machines you wish. However, specific examples are provided for Unix systems. For other systems, you are (mostly) on your own if you have specific implementation questions.

You are to write a program that simulates a simple command line shell. Your program will allow a user to enter commands one at a time until s/he types "exit".

Not all commands will be executed externally. Your shell will also have several "built-in" commands. These commands will be handled internally by your tiny-shell and will not be executed. The built-in commands are:

After running the command, your program should print out some statistics for the command it ran:

  1. The amount of CPU time used (both user and system time) as reported by the getrusage() system call (in milliseconds) (see below for more information)
  2. To get the elapsed wall-clock time (in milliseconds) (use a time function such as the system call gettimeofday() (see below for more information)
  3. The number of page faults (minor and major).
  4. The number of times the process was preempted involuntarily (e.g. time slice expired, preemption by higher priority process)
  5. The number of times the process gave up the CPU voluntarily (e.g. waiting for a resource)

Note, the last two are not kept in your typical Linux OS.

The emphasis of this program is working with processes. If you have trouble with the command line parameters, you make a simplifying assumption, that only single-word commands are allowed. See Hand In for details on how this version would be graded.

Your program should have error checking. You must check the return values from system calls and print appropriate error messages to the user, when required.

To make things a bit easier, you can assume:


The following system calls might be useful:

Check out samples fork.c and execl.c showing simple use of fork() and execl(), respectively.

To get help information about these routines, use the Unix "man" command. For instance, entering "man fork" will display the manual page entry for fork on the terminal. The manual pages are organized into sections. Section 1 is for Unix commands, section 2 is for Unix system calls and section 3 is for Unix library routines. Some entries are contained in more than one section. For example to obtain information about the system call wait() (rather than the command wait) use "man 2 wait" where the section is explicitly given.

A few recommendations if you find yourself struggling (in order):

  1. Build a simple program that does nothing but an execvp() with a one word command (ie - ls).
  2. Add the built-in exit command.
  3. Work on a simple program that does nothing but fork() a child. Have the parent and child both print out a different message and quit.
  4. Combine the execvp() with the fork().
  5. Add a loop for the parent and the wait() call.
  6. Add the cd code.
  7. Add the nice code.
  8. Add statistics via the getrusage() and gettimeofday() calls.
  9. Allow more complicated commands. Again, think simple (ie- only one argument at first). You might like to use the strtok() function here. Do a man strtok().
  10. Add the built-in cd command.
  11. Polish, clean-up, debug thoroughly ...
  12. Turn it in.
  13. Relax!

Remember, do each step thoroughly. Make sure the step you are on works well and you understand it before going to the next step.


Script started on Sat Aug 29 13:51:18 1998
Welcome to Mark's tiny-shell!
count	       tiny-shell    index.html
count.c        tiny-shell.c  typescript
              wallclock time:   85.174 msec
              getrusage time:   80.222 msec
            context switches: 7
involuntary context switches: 0
==>>ls -l
total 229
-rwxr-xr-x   1 claypool 500        105908 Aug 28 22:14 count
-rw-rw----   1 claypool 500           238 Aug 28 22:14 count.c
-rwxrwx---   1 claypool 500        109908 Aug 29 13:49 tiny-shell
-rw-------   1 claypool 500          3187 Aug 29 13:50 tiny-shell.c
-rw-rw----   1 claypool 500          9653 Aug 29 13:46 index.html
-rw-rw----   1 claypool 500             0 Aug 29 13:51 typescript
              wallclock time:   545.359 msec
              getrusage time:   540.412 msec
  voluntary context switches: 5
involuntary context switches: 0
==>>ls -l -a -r -t
total 231
drwxrwx---   4 claypool 500          1024 Aug 28 21:45 ..
-rw-rw----   1 claypool 500           238 Aug 28 22:14 count.c
-rwxr-xr-x   1 claypool 500        105908 Aug 28 22:14 count
-rw-rw----   1 claypool 500          9653 Aug 29 13:46 index.html
-rwxrwx---   1 claypool 500        109908 Aug 29 13:49 tiny-shell
-rw-------   1 claypool 500          3187 Aug 29 13:50 tiny-shell.c
drwxrwx---   2 claypool 500          1024 Aug 29 13:51 .
-rw-rw----   1 claypool 500             0 Aug 29 13:51 typescript
              wallclock time:   54.140 msec
              getrusage time:   40.513 msec
  voluntary context switches: 7
involuntary context switches: 0
              wallclock time:   991.045 msec
              getrusage time:   1120.448 msec
  voluntary context switches: 0
involuntary context switches: 2

==>>cd /
bin	    etc		lost+found  root	usr
boot	    home	mnt	    sbin	var
dev	    lib		proc	    tmp
              wallclock time:   219.142 msec
              getrusage time:   20.231 msec
  voluntary context switches: 0
involuntary context switches: 0
==>>cd blah
Unable to change directory: No such file or directory
==>>blah blah
Unable to execute "blah".  No such command found.

Test Cases

Make a program called "count" that does nothing but increment an integer in a loop from 1 to 70000000 (or some other large number). Then run your program with the following commands:

   ls -l
   ls -l -a -r -t
   nice count (use top to see if it is workign)
   cd ..
   cd /

You may run it with more commands, too, if you wish to be sure it works properly.


You should observe how your tiny-shell works compared to a full-fledged Unix shell, such as tcsh or bash. Give brief answers to the following questions:

  1. What are some of the process features the Unix shell has that your tiny-shell does not?
  2. What are some of the other features you might like to know about the commands you run (either included or not included in the getrusage() call)?
  3. Are there ever discrepancies between the getrusage() time reported and the gettimeofday() (wall clock) time reported? If so, why?
  4. Shells typically allow processes to be run in "background" mode using the '&' character. In background mode, the shell does not wait for the current process to complete but instead prompts the user for the next command. Briefly describe changes you would make to your code to support the '&' character.

You should include your answers as either comments in your program header or in a separate text file.

Hand In

A completely working program will function as described above. There are several levels of less sophisticated programs that can be achieve to receive lesser grades. Here is a rough summary of the grades that will be assigned:

Note, one letter grade is worth approximately 10% of the Project points.

Please include a README file giving some project information. The main information I'd like you to have from the documentation standard is: author(s), date, project id, language, OS dependencies, description and building information. Do note, however, that this information does not take the place of normal comments in your code! These comments are to make it easier for me to assess a grade if there are difficulties in the program.

Here is a sample of the information you should have:

Author:                         Mark Claypool
Date:                           06/01/05
Project ID:                     Project 1
CS Class:                       CS 3013/502
Programming Language:           C
OS/Hardware dependencies:       Unix, gcc

Problem Description:            This program implements a small shell
                                that does blah, blah, blah

How to build the program:       gcc tiny-shell.c

To hand in project 1:

  1. Be sure the answers to the Questions are in a file called "questions.txt" in the directory with your project code.

  2. Then, make a tar-ball to submit your files:

       cd my-dir-with-proj1
       rm all-files-not-to-be-turned-in
       cd ..
       tar cvf proj1.tar my-dir-with-proj1

  3. Attach them to an email them to me with the subject "cs3013/502 project 1"

Return to the cs3013/502 Home Page

Send all questions to claypool at cs.wpi.edu.