CSC 213:  Operation Systems and Parallel Algorithms

An Expanded Unix-Style Shell

Goals

Background Materials

This lab draws upon three sources:

Much of this lab is inspired by Nutt's Lab Exercise 9.2

Main Task for this Lab

Lab Exercise 2 for this course asked you to write a simple Unix-style shell according to the following outline:

  1. Write a program that reads successive command lines from a terminal window,
  2. For each command line,
    1. break the command line into tokens - the pieces separated by spaces
    2. places the command tokens into an array of command-line strings
    3. identifies the location of the desired program by searching the user's PATH variable for the given program
    4. uses fork to spawn a child process, and using execv within the child process to actually run the desired program.

In this lab, you are to extend the allowed command lines in three ways:

  1. Allow the [first] program on the command line to redirect standard input, so reading is done from a designated file.

  2. Allow pipes to be specified to connect successive programs, running as separate processes.

  3. Allow the [last] program on the line to redirect standard output, so writing is done to a named file.

Some Details

Input Redirection

Within the Unix/Linux command-line environment, programs normally read from "standard in" and write to "standard out". By default, "standard in" is usually the keyboard, and "standard out" is usually a computer monitor at a person's workstation. For example, consider program max-min.c. This program reads an integer n, followed by n real numbers, and finds the maximum, minimum, and average of the real numbers. All reading is done from "standard in" and output is to "standard out". The program also prints out the ith real number. Thus, a typical run might be:


%gcc -o max-min max-min.c && max-min
Program to process real numbers.
Enter number of reals: 7
Enter 7 numbers: 3.0 1.0 4.0 1.0 5.0 9.0 2.0
Maximum:   9.00
Minimum:   1.00
Average:   3.57

Enter the index (1..n) of the number to be printed: 6
The 6 th number is 9.00

In running the program, Unix allows data to be read from a file, rather than from "standard in". For example, suppose that a file "data" contains the following entries, which repeat exactly what the user typed in the above session:


7
3.0 1.0 4.0 1.0 5.0 9.0 2.0
6

Unix allows information to be read from the file "data" rather than from the keyboard, with the following command:


%gcc -o max-min max-min.c && max-min < data

In this command, the less than sign (<) indicates that the name that follows (data) should be used for input rather than the keyboard. The output is exactly as above, except that the user's typing is not seen (it came from the file).

In this example, the output looks a bit strange, as the prompts for data are still printed to the screen, even though the input from the file is not echoed. When redirecting input, it is sometimes advised not to prompt the user, although that is more a matter of form than a technical requirement.

Output Redirection

Similarly, all output could be written to a file rather than to a monitor. Thus, to print output in a file called "results", we might use the following command:


%gcc -o max-min max-min.c && max-min > results

In this case, the program will wait for you to enter the relevant data, but no prompts appear on your screen. Rather, all output goes to the file "results".

Input and Output Redirection

Redirection of both input and output can be combined on a single Unix command line:


%gcc -o max-min max-min.c && max-min < data > results

In this context, nothing appears on the screen either from the user typing input or the program printing output.

Implementing I/O Redirection

Nutt discusses I/O redirection in Lab Exercise 9.2 using open and dup.

Alternatively, an implementation of input or output redirection paralleling the use of pipes may follow 3 main steps:

  1. Use open to set up the file, giving an integer file descriptor as a result. (Use the parameter O_RDONLY for reading, or the parameter O_WRONLY | O_CREAT for writing.)
  2. Use dup2 to copy the file descriptor to STDIN_FILENO or STDOUT_FILENO.
  3. Close the file variable opened in step 1, since standard in or out will handle the relevant I/O tasks.

Program io-redirection.c demonstrates how these steps might be added to the example program, max-min.c.

Piping within a Unix command line

Within a Unix command line, one can designate the output of one program as the input of another. Further, this capability can be expanded through a series of programs. For example, a listing of the directory /home/walker/c/examples yields:


%ls
core
fork-1
fork-1.c
fork-1.out
fork-2
fork-2.c
fork-2.out
fork-3
fork-3.c
fork-3.out
fork-4
fork-4.c
fork-4.out
fork-5
fork-5.c
fork-5.out
fork-6
fork-6.c
fork-6.out
intro.dvi
intro.pdf
intro.ps
intro.tex
read-write-1
read-write-1.c
read-write-1.out
read-write-1.out-a
read-write-1.out-b
read-write-2
read-write-2.c
read-write-2.out
read-write-3
read-write-3.c
read-write-3.out
read-write-4
read-write-4.c
read-write-4.out

Within this listing, we might be interested in files that end in .c. Of course, one approach to this result would be to use the command ls *.c. However, another approach would be to utilize the filter program grep, lookng for files that contain the strong .c. In this approach, we want to generate the full listing, send the output through a pipe to grep, filter the file names, and print the results:


%ls | grep .c
fork-1.c
fork-2.c
fork-3.c
fork-4.c
fork-5.c
fork-6.c
read-write-1.c
read-write-2.c
read-write-3.c
read-write-4.c

In this command, the vertical line | indicates the output of program should be sent to the next program.

As an additional step, we might want to filter out all file names containing the number 3, based on the command grep -v 3. Adding another pipe to the previous command to include this step yields


%ls | grep .c | grep -v 3
fork-1.c
fork-2.c
fork-4.c
fork-5.c
fork-6.c
read-write-1.c
read-write-2.c
read-write-4.c

Implementation of such pipes follows closely the programs fork-2.c through fork-6.c in An Introduction to Concurrency in Unix-based [GNU] C Through Annotated Examples.

Work To Be Turned In

As with all labs, you should turn in your solution utilizing the course's format for submitting assignments.


This document is available on the World Wide Web as

     http://www.cs.grinnell.edu/~walker/courses/213.fa04/lab-shell-expanded.shtml

created October 11, 2004
last revised October 11, 2004
Valid HTML 4.01! Valid CSS!
For more information, please contact Henry M. Walker at (walker@cs.grinnell.edu)