Programming Assignment #2
Project 2: Write a simple shell
Relevant material: UNIX man pages. You may need to read the following man pages:
fork,
wait,mkdir, strtok, pipe, dup2, execv (execl)
HINT Programs: parser.c
simple
child.c
STDIN/OUT
example
Programming Language: C -- NO EXCEPTIONS.
A properly commented/documented
program is expected.
Note, your name, date, and purpose of
program must be
part of the comments. You must error check the system calls. Failure
to document or error check will result in a lower score.
Requirements: Write a program which performs rudimentary shell actions.
Details: The goal of this project is to familiarize
you with some of the system programs
used in running an interactive environment, known as
a "shell". Whenever you log
into a UNIX computer, the system runs a program for you
called a shell. You know this
by the "%" prompt. When you type in unix commands
like "ls", the shell runs the
program for you.
The shell can be quite complex. This assignment
is to have you write a bare bones
shell; a small set of shell features will be required.
I have given you some links to programs that you may find
helpful in your project.
You should note that a shell program is in an infinite
loop, reading in commands, executing
them, and then giving you a prompt. Something like:
while (1)
{
read in a line
parse the input line
execute the line (if possible)
print out prompt
}
Your job is to write a shell which takes in commands from
standard input, executes
the commands.
There are several shell "features" that I encourage you
to make work (I do this by
making them worth some points). The one that is
part of the 100 points is
I/O redirection. You may have done this with the command:
% a.out < input > output
This says that the input file will be used as a.out reads
data, and that
output file is where the output will be placed (instead
of the terminal).
You will need "dup2" to accomplish this task (and I have
given you
an example on how that works).
Your most difficult task is that you will have to use
"fork" to create new processes.
The new processes will use one of the "execv" family
subroutines to run the
new image. Again, you have example on how this
is done.
You may want to consider the following as sub-goals for
the projects:
1) write a program which reads in lines
and uses the "system" call to
execute the line
2) use the parser program I gave you
along with the child program to create
processes,
use an "execl" type subroutine to run the program
2a) enhance the code to consider
input like "cd", "pwd", "echo", "mkdir", and "exit"
echo -- prints the arguments to it with "printf()"
cd /
-- should use the system call "chdir()"
pwd
-- should use the system call "getwd()"
mkdir DIR
-- should use the system call "mkdir()"
3) enhance the parser to recognize
the "<" and ">" symbols and if they
exist,
tie STDIN_FILENO and STDOUT_FILENO to the respective
file
descriptors.
You can assume that each token in the input
will be separated by at least one space.
You should take into account bad input to
the shell like:
a.out < foo bar
In this case, there are two files on
the right side of the redirect command, when there
should only be one.
START EARLY -- This assignment can be extremely time consuming
if you start late. There
is a lot of thinking in this project.
Grading:
A solution which reads in a command line and uses "system" to call the program will be graded on 65 points.
A solution which reads in a command line and executes the program without arguments will be graded on 73 points.
A solution which read in a command line and executes the program with all arguments will be graded on 82 points.
A solution which reads in commands, performs chdir, pwd, echo, and exit will be graded on 88 points.
A solution which does the above as well as IO redirection will be graded on 94 points.
A solution which does the above as well as a single PIPE will be graded on 100 points.
A solution which does the above and also
performs at least 3 pipes will be graded on 110 points.
Testing: I will run various shell commands to your solution.
Examples include: /bin/date
cd /usr
pwd
/bin/ls -F
/bin/cat - < /etc/passwd
/bin/cat - < /etc/passwd > /tmp/out
/bin/ls -F /
/bin/sort /etc/passwd | /bin/sort | /bin/uniq | /bin/wc
-l > /tmp/out