[an error occurred while processing this directive]
Project 1: Implementing a Simple Shell (c) 1997, Howard E. Motteler; Modified by Gary L. Burt, 1998 Assigned: 2 March; Due:18 March Project Goals The goals of this project are to learn the basics of how a "shell" or command interpreter works, and to gain experience programming with UNIX processes and system calls. The Project You are to design and implement a simple shell, "mysh". A prototype is on page 24 of your text. You should start with this and expand it to implement the features specified below. Specifications Your shell should be able to parse and execute command lines of the following form
cmd where "file" is any valid UNIX filename, and "cmd" is a program name followed by zero or more arguments, with no wildcards, no in-line command evaluation, no macro substitutions, and which does not include the symbols ">", "<", or "|". For the special case when "cmd" is "exit", you shell should terminate.
Your shell should also be able to parse and execute command lines
as above ending with an "&" that puts the specified process or
processes into the background.
cmd & You can assume that all command lines are of the form described here, and you do not have to check for any other sorts of input. In particular, you do not have to expand filename wildcards, do multi-step pipes or do both input and output redirection on one line. Use fork() and either execve() or execvp() to execute the commands. In Minix and Linux execve() is a systems call and execvp a library routine; on the SGIs, both seem to be systems calls. The man difference is that execvp() will search your PATH for the specified executable, and doesn't have an explicit environment argument. Your shell should prompt the user for each command line with the string "mysh>". The final version you submit should not print any test messages or other extraneous jabber. You should print errors returned by execvp() or execve(); you can use strerror(errno) to make your error reporting more informative; errno is an external variable set to the most recent error, and strerror() translates this to a human-readable string. You may find the UNIX string manipulation library routines convenient for parsing the command line; do a "man string" to learn more about these functions. To redirect input from a file to a program, so the file appears as "standard input" to the program (e.g., as in the command " wc < test.dat"), you will have to manipulate file descriptors. To connect a file to the UNIX "standard input" (by convention file descriptor 0), you can use the dup2()system call, as in the following example. If we wanted to execute the command "ls -l", "cmd" in the above example would be the string "ls", and the string array "args" would have its first element pointing to "ls", its second element pointing to "-l", and its third element the null pointer 0, indicating the end of the arg array. The "&" function is easy to implement--without the "&", the shell waits for the child process; with the "&" it does not wait. The pipe function "|" is a little more difficult, and can be implemented with either a temporary file, or preferably with a real UNIX pipe. Grading Make sure you have read the general information on programming projects. Approximately 20% of your grade is for documentation, and the remainder is based on how well your project works. You should describe your design and implementation at the beginning of the project; this initial description is worth 15% of your grade. Describe any non-trivial data structures you have used, and briefly say how each relevant routine acts on those data structures. The description should be about a half-page long. Do not ramble incoherently, and do not simply echo the specifications given here. Do not use the system() sys call or invoke the UNIX shell to implement your shell! You must do the project described here. Doing some other similar or dissimilar project, matter how difficult or clever, may be worth 0 points. This is not a group project; please do your own work, and be careful about sharing your code. It is OK to discuss design issues, but in your documentation, you should give credit to your sources. What to turn in Mail the file mysh.c to the TA for grading. All of your code should be
in this one file.
Hints and Tips
cmd > file
cmd < file
cmd | cmd
cmd > file &
cmd < file &
cmd | cmd &
{
fprintf( stderr, "mysh error: can't open %s\n", fname);
exit(1);
}
dup2(fd, 0);
close(fd);
if(execvp(cmd, args == -1 )
fprintf(stderr, "mysh error: %s\n", strerror(errno) );
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
1. write and test a parser to read the command lines;
2. get the simple commands to work;
3. get "&" to work;
4. get I/O redirection to work;
5. get pipes to work.