Quash Shell
0.1
A simple yet powerfull shell program
|
EECS 678 - Project 1 - Quash Shell
In this project, you will complete the Quite a Shell (quash) program using the UNIX system calls. You may work in groups of 2. The purpose of this project is as follows:
A skeleton has been provided, but it lacks most of the core functionality one would expect from a shell program. Quash should behave similar to csh, bash or other popular shell programs.
To build Quash use:
make
To generate this documentation in HTML and LaTeX use:
make doc
To clean quash use:
make clean
To run Quash use:
./quash
or
make test
The main file you will modify is src/execute.c. You may not use or modify files in the src/parsing directory, with the notable exception of the destroy_parser() function in src/parsing/parse_interface.c if necessary. Your output should match our example result files exactly.
The following features should be implemented in Quash:
<
character is used to redirect the standard input from a file. The >
character is used to redirect the standard output to a file while truncating the file. The >>
string is used to redirect the standard output to a file while appending the output to the end of the file.|
.All built-in commands should be implemented in quash itself. They cannot be external programs of any kind. Quash should support the following built-in functions:
echo
- Print a string given as an argument. The output format should be the same as bash (a string followed by new line '\n')cd
- Change current working directory. This updates both the actual working directory and the PWD environment variable.pwd
- Print the absolute path of the current working directory. Make sure you are printing out the actual working directory and not just the PWD environment variable.quit
& exit
- Use these to terminate quash. These are already implemented for you.jobs
- Should print all of the currently running background processes in the format: "[JOBID] PID COMMAND" where JOBID is a unique positive integer quash assigns to the job to identify it, PID is the PID of the child process used for the job, and COMMAND is the command used to invoke the job.The following are some funtions outside of src/execute.c that you may want to use in your implementation:
The following is a list and brief description of some system calls and library functions you may want to use and their respective man page entries. Note that this list may not be exhaustive, but be sure what ever library functions you use will run on the lab machines:
You may NOT use the system(3) function anywhere in your project
In Quash, a job is defined as a single command or a list of commands separated by pipes. For example the following are each one job:
cat file.txt # A job with a single process running under it
find | grep *.qsh # A job with two processes running under it
A job may contain more than one process and should have a unique id for the current list of jobs in Quash, a knowledge of all of the pids for processes that run under it, and an expanded string depicting what was typed in on the command line to create that job. When passing the pid to the various print job functions you just need to give one pid associated with the job. The job id should also be assigned in a similar manner as bash assigns them. That is the job id of a new background job is one greater than the maximum job id in the background job list. Experiment with background jobs in Bash for more details on the id assignment.
The structure of the functions in src/execute.c will be explained in the following paragraphs.
The entry level function for execution in quash is run_script(). This function is responsible for calling create_process() on an array of CommandHolders. After all of the processes have been created for a job, run_script() should either wait on all processes inside a foreground job to complete or add it to the background job list without waiting if it is a background job.
The create_process() function is intended to be the place where you fork processes, handle pipe creation, and file redirection. You should not call execvp(3) from this function. Instead you should call derivatives of the example_run_command() function. Also you can determine whether you should use the boolean variables at the top of this function to determine if pipes and redirects should be setup. It may be necessary to keep a global execution state structure so that different calls to create process can view important information created in previous invocations of create_process() (i.e. the file descriptors for open pipes of previous processes).
When implementing the run_<command type> functions in src/execute.c, the command structures usually hold everything needed to pass to the corresponding function calls. For example, the GenericCommand structure contains an args field fully formatted and ready to pass into the argv argument of the execvp(3) library function. The one exception to this rule is run_cd(). In the CDCommand structure, the field dir is the path that the user typed. This needs to be expanded to an absolute path with realpath(3) before you use it.
You should not have to search for environment variables ($) in your functions. The parser uses your implementation of lookup_env() function to expand the environment variables for you.
There is an automated testing script written for this project in run_tests.bash. Using the "make test" target in the make file will run the ./run-tests.bash command present in the Makefile. If you want more control you may run this script directly from the command line with "./run_tests.bash [-cdstuv]". The various options are listed below or with "./run_tests.bash -h".
Partial credit will be given for incomplete programs. However, a program that cannot compile will get 0 points. The feature tests are placed into multiple tiers of completeness. The output to standard out from your code must match our output exactly, except for whitespace, for the next tier of grading to be accessible. This is due to reliance of previous tiers in subsequent tier tests. If we cannot run your code in one tier then it becomes far more difficult test later tiers. The point breakdown for features is below:
Description | Score |
---|---|
| 20% |
| 20% |
| 20% |
20% | |
| 20% |
| -5% from tier grade down to 0% for each tier with violations |
Each group should submit the project to your TA via Blackboard. Create a zip file of your code using "make submit". You should also check that the zipped project still builds and runs correctly after building the submit target with "make unsubmit". Your TA will be using this command to extract and build your project so make sure it works correctly. If you modify either of these targets, please ensure all file extensions are renamed to ".txt" in the submission and extract correctly with the unsubmit target.
Start early! You need to use C language to implement this project.