Computer Science 322 Operating Systems

Mount Holyoke College Spring 2010

Lab 2: The Lyon ShellDue: 2:40 PM, Monday, February 22, 2010

For this lab, you are to write a C program called the Lyon Shell
(lysh), a mini command shell interpreter. lysh is similar
to familiar Unix shells such as the Bourne shell (sh) the
Bourne-Again shell (bash), and C shell (csh, tcsh). You
will learn about process creation, pipes, input/output redirection,
background process management, signals, and interrupt handling, and
gain extensive experience with C.

You may work in groups of size 2 or 3. Collaboration within a group
is, of course, unrestricted. You may discuss the program with members
of other groups, but what you turn in must be your own group's work.
Groups must be formed no later than 2:40 PM, Wednesday, February 10, 2010, and be confirmed by
all group members by electronic mail to jteresco AT mtholyoke.edu. All group
members will be assigned the same grade for the lab. There are many
subtasks that can be carved off and assigned to group members, so
everyone is encouraged to join a group.

Requirements

Like the Unix shells you use every day, lysh should issue a prompt
(below, it is "shell#"), at which it reads commands from the user
and executes them.

Your shell should interpret the following commands and provide the
following functionality:

exit: exit from the shell

help: display a message listing usage of all commands

Execute a command (program on disk). As in the shells you use,
the command should be located according to the PATH environment
variable Appropriate choice of exec function will help here.
The arguments following the command should be passed to the command.

For example,

shell# cat cat.c

should execute cat with one argument, cat.c

Input and output redirection should be implemented.

For example,

shell# cat < cat.c > myfile.c

should cause the cat program to read from cat.c and write
to the file myfile.c.

shell# ls -l >> dirlistings.txt

should cause the output of ls -l to be appended to the end of the
existing file dirlistings.txt.

An individual command may only redirect input once and output once,
but those redirections may be specified in any order.

shell# > alines grep -i < Makefile a

should be interpreted the same as the more usual

shell# grep -i a < Makefile > alines

Pipes should be implemented.

For example,

shell# cat cat.c | wc > count.txt

should cause the output of cat cat.c to be the input of wc >
count.txt.

You should allow a sequence of pipes to be specified:

shell# ls -l *.c | grep "Oct 31" | wc -l

The program should be able to handle a sequence of pipes of any
length.

Only the first command in a pipeline may have input redirection.
Only the last command in a pipeline may have output redirection.
Redirection of other commands should be reported as an ambiguous
command line.

Typing <ctrl-c> should abort a command being run, but not
cause lysh to terminate.

A list of commands separated by semicolons should be executed in
sequence.

As with the familiar Unix shells, appending an & to the
end of your command line will execute the command in the background.

An & may be anywhere in a command line, but it is treated
like a ; in that anything on the command line following an
& should be treated as a new command.

For example,

shell# sleep 5 & sleep 5

should launch one instance of sleep 5 in the background, then a
second in the foreground.

Typing <ctrl-c> should not kill the shell or any commands
running in the background.

All backgrounded processes should be maintained in a process
table by lysh, so that the program name is displayed when
it terminates, and for use in the jobs and kill commands.

jobs: Displays all the active background programs that
have been started from this shell, along with their ids. (This
id need not be that same as the actual process id. For example, it
could be the index into your process table).

The system calls that you should use are fork(2), a variant
of exec(3), signal(3), kill(2), open(2),
dup2(2), close(2), pipe(2), and chdir(2).

You may find the readline(3) and the strsep(3)
functions to be useful. readline(3) is part of the GNU
Readline Library and strsep(3) is in the Standard C Library.

You may assume the builtin commands (exit, help,
jobs, kill) stand alone on a command line (no pipes, I/O
redirection).

Use lysh scripts to test your shell.

A shell may run for a long time. Be careful about memory management.

gcc's -Wall flag will report additional compiler
warnings. This can help you find some of the more subtle bugs that
are so common in C code before they have a chance to cause their
subtle problems. If you aren't absolutely certain that a given
warning is harmless, fix it!

A verbose/debugging mode is essential for, well, debugging.

Keep your code under source code control. You may wish to use
subversion to track your changes and to allow you to go back to
previously working code. If you're working in a group, this is even
more useful, allowing easier concurrent development. Group members
should request a Unix group for safe sharing of files.

The following might be a good order to tackle the required functionality.

exit and help commands

run a command (with no argument passing, no redirection, no pipes)

run a command with argument passing

run a command with input and output redirection

run a command in the background

jobs command

kill command

<ctrl-c> trapping

trapping termination of background processes

pipes

;- or &-separated commands

cd command

extra functionality

/home/jteresco/shared/cs322/labs/shell/lysh
contains my version of lysh, compiled to run on FreeBSD (mogul).

Submission and Evaluation

All necessary files should be submitted in a single tar file
shell.tar. Include a Makefile to allow easy compilation of
the Lyon Shell program. Send this tar file as an attachment to
jteresco AT mtholyoke.edu by 2:40 PM, Monday, February 22, 2010.

I will compile and test your shell programs on the FreeBSD system,
mogul.

Your program will be graded based on a total of 50 points.

6 points for documentation. Your code should
be commented appropriately throughout. Please also include a longer
comment at the top of your program describing your implementation.
This documentation should list your important design decisions, the
assumptions that you made (if any), the additional functionality
implemented, and any other relevant information.