CPR E 308 Project 1: UNIX Shell: Department of Electrical and Computer Engineering Iowa State University
CPR E 308 Project 1: UNIX Shell: Department of Electrical and Computer Engineering Iowa State University
CPR E 308 Project 1: UNIX Shell: Department of Electrical and Computer Engineering Iowa State University
Submission
Introduction
In this project you will be creating your own version of a UNIX shell. It will not be as
sophisticated as bash, the shell you have been using in lab, but it will perform a similar
function.
A UNIX shell is simply an interactive interface between the OS and the user. It
repeatedly accepts input from the user and initiates processes on the OS based on that
input.
Description
• Your shell should accept a '-p <prompt>' option on the command line when it is
initiated. The <prompt> option should become the user prompt. If this option is
not specified, the default prompt of ‘308sh>’ should be used. Read the appendix
on command line options at the end of this document for more information.
• Your shell must run an infinite loop accepting input from the user and running
commands until the user requests to exit.
• The shell should notify the user if the requested command is not found and cannot
be run. HINT: read about the libc call, perror.
• For each spawned child, print the process ID (PID) before executing the specified
command. It should only be printed once and it should be printed before the
output from the command.
• By default, the shell should block (wait for the child to exit) for each command.
Thus the prompt will not be available for additional user input until the command
has completed. Your shell should only wakeup when the most recently executed
child process completes. See waitpid.
• The shell should evaluate the exit status of the child process and print the
conditions under which it exited (identify which process exited by its PID). Read
the man page for wait to see a list of macros that provide this information (man 2
wait). Two examples of exit status are normal exit and killed (signaled).
• If the last character in the user input was the ampersand (&), the child should be
run in the background (the shell will not wait for the child to exit before
prompting the user for further input). Remove the & when passing the parameters
to exec. When your background process does exit, you must print its status like
you do for foreground processes.
An example is, if the user entered “/usr/bin/emacs” then the shell would wait for
the process to complete before returning to the prompt. However, if the user
entered “/usr/bin/emacs &” then the prompt would return as soon as the process
was initiated. HINT: to evaluate and print the exit status of a background child
process call waitpid with -1 for the pid and WNOHANG set in the options. This
checks all children and doesn’t block – see the man page. To do this periodically,
a check can be done every time the user enters a command.
• The following commands are special commands (also called built-in commands)
that are not to be treated as programs to be launched. No child process should be
spawned.
1. exit – the shell should terminate and accept no further input from the user
2. pid – the shell should print it’s own process ID
3. ppid – the shell should print the process ID of it’s parent
4. cd – used to change or display the current working directory
“cd” – with no parameters displays the current working directory
“cd blah” – changes the directory to “blah”
Note: to make sure programs still run correctly after you have issued a ‘cd
somedir’ you should update the environment variablePWD.
EXTRA CREDIT
• Keep track of the names of your child processes and output them with their PIDs
(i.e. “… process pid (procnam) …”). For this, you need a data structure which can
maintain a list of currently executing background tasks – we suggest using a list.
Also, now that you are maintaining a list of background tasks, add another built-in
command ‘jobs’ that outputs the name of each task running in the background.
• Sometimes it’s nice to have your program dump its output to a file rather than the
console. In bash (and most shells) if you do ‘cmd arg1 … argN > filename’ then
the output from cmd will go the file filename. If the file doesn’t exist, it is created.
If it does exist, it is truncated (removes all its data, allowing you to effectively
overwrite it). Add this feature to your shell.
Other comments
• Don’t forget that all command line parameters (e.g. in `ls –al /home/user` ls has
two command line parameters) need to be passed on to the executed command via
“exec”. These parameters become argv to the new process. See Appendix A for
more information on command line parameters.
• You may want to prefix all your output messages with some sort of identifier,
such as “>>>”, to more easily determine which lines are yours and which came
from the executed program.
Grading Criteria
Summary – 15%
Well written and specific.
Extra Credit
Each extra credit option listed is worth an additional 5%.
Command line options are options that are passed to a program when it is initiated. For
example, to get ls to display the size of files as well as their names the –l option is passed
to it. (e.g. ls –l /home/me) In this example /home/me is also a command line option which
specifies the desired directory for which the contents should be listed.
From within a C program, command line options are handled using the parameters argc
and argv which are passed into main.
The parameter argc is a value that contains the number of command line arguments. This
value is always at least 1, as the name of the executable is always the first parameter.
The parameter argv is an array of string values that contain the command line options.
The first option, as mentioned above, is the name of the executed program. The program
below simply prints each command line option passed in on its own line.
int main(int argc, char **argv)
{
int i;
for(i=0; i<argc; i++)
printf(“Option %d is :%s\n”, i, argv[i]);
return 0;
}
If you are unfamiliar with how command line options work, enter the above program and
try it with different values. (e.g. ./myprog I guess these are options)
Appendix B – Useful System and Library Calls
The following system calls will be useful in this project. Read the corresponding man
pages for those you are unfamiliar with.
The syscalls necessary for the extra credit aren’t listed above, but look into what’s
available for “file descriptors” such as dup2.