$24
This programming assignment is related with writing a simple shell by considering the outline program given in the lab sessions.
The main() function of your program presents the command line prompt “myshell: ” and then invokes setup() function which waits for the user to enter a command. The setup function (given as an attachment to your project) reads the user’s next command and parses it into separate tokens that are used to fill the argument vector for the command to be executed. It can also detect background processes. This program is terminated when the user enters ^D (<CONTROL><D>); and setup function then invokes exit. The contents of the command entered by the user is loaded into the args array. You may assume that a line of input will contain no more than 128 characters or more than 32 distinct arguments.
Necessary functionalities and components of your shell is listed below:
A. It will take the command as input and will execute that in a new process. When your program gets the program name, it will create a new process using fork() system call, and the new process (child) will execute the program. The child will use the execv() function in the below to execute a new program.
Use execv() instead of execvp(), which means that you will have to read the PATH environment variable, then search each directory in the PATH for the command file name that appears on the command line.
Important Notes:
1. Using the “system()” function is not allowed for part A!
2. In the project, you need to handle foreground and background processes. When a process run in foreground, your shell should wait for the task to complete, then immediately prompt the user for another command.
myshell: gedit
A background process is indicated by placing an ampersand (’&’) character at the end of an input line. When a process run in background, your shell should not wait for the task to complete, but immediately prompt the user for another command.
myshell: gedit &
With background processes, you will need to modify your use of the wait() system call so that you check the process id that it returns.
B. It must support the following internal (built-in) commands. Note that an internal command is the one for which no new process is created but instead the functionality is built directly into the shell itself.
ps_all - display the status of each background job (process). Your shell must keep track of background job information using an appropriate data structure. Each background job should be assigned a job number to be used as an index when displaying information about the job. The job numbers should be incremented for each new background job, and when no background job exists, the job number should reset to 1. In addition to this, the PID values of the processes are also displayed. It should be noted that the status information of background jobs are displayed in two lists: list of background jobs still running, and the list of background jobs that have finished execution since the last time the status is displayed with the ps_all command. Consider the following example:
myshell> ps_all
Running:
[1] xterm (Pid=1000)
[2] emacs myfile1 (Pid=1001)
[4] netscape (Pid=1002)
Finished:
[3] myprog1 > temp_file
Note that job [3] will not be listed the second time. You should clear out the background job information from your jobs data structure after a job displayed in the finished list.
^Z - Stop the currently running foreground process, as well as any descendants of that process (e.g., any child processes that it forked). If there is no foreground process, then the signal should have no effect.
search - This command is very useful when you search a keyword or phrase in source codes. The command takes a string that is going to be searched and searches this string in all the files under the current directory and prints their line numbers, filenames and the line that the text appears. If -r option is used, the command will recursively search all the subdirectories as well. The file formats searched by the command are limited to .c, .C, .h, and H.
Example:
myshell> search "foo"
45: ./foo.c -> void foo(int a, int b);
92: ./foo.c -> foo(a,b);
myshell> search -r "foo"
45: ./foo.c -> void foo(int a, int b);
92: ./foo.c -> foo(a,b);
112: ./include/util.h -> void foo(int a, int b, int c);
254: ./lib/x86/lib64.cpp -> for (int i=0; i < N; i++) // foo is called
inside
bookmark - bookmark frequently used commands. See the following example to add a command to the bookmarks and execute it.
Example:
myshell> bookmark "ps -a"
myshell> bookmark "ls –l | wc -l"
myshell> bookmark -l
0 "ps -a"
1 "ls –l | wc -l"
myshell> bookmark -i 0
PID TTY TIME CMD
6052 pts/0 00:00:00 ps
myshell> bookmark -d 0
myshell> bookmark -l
0 "ls –l | wc -l"
In the first line, a command to print currently running processes is bookmarked at index 0 and the next command is bookmarked at index 1. Using -l (lowercase letter L) lists all the bookmarks added to myshell. bookmark -i idx executes the command bookmarked at index idx. Using -d idx deletes the command at index idx and shifts the successive commands up in the list.
exit - Terminate your shell process. If the user chooses to exit while there are background processes, notify the user that there are background processes still running and do not terminate the shell process unless the user terminates all background processes.
C. I/O Redirection
The shell must support I/O-redirection on either or both stdin and/or stdout and it can include arguments as well. For example, if you have the following commands at the command line:
myshell: myprog [args] > file.out
Writes the standard output of myprog to the file file.out. file.out is created if it does not exist and truncated if it does.
myshell: myprog [args] >> file.out
Appends the standard output of myprog to the file file.out. file.out is created if it does not exist and appended to if it does.
myshell: myprog [args] < file.in
Uses the contents of the file file.in as the standard input to program myprog.
myshell: myprog [args] 2> file.out
Writes the standard error of myprog to the file file.out.
myshell: myprog [args] < file.in > file.out
Executes the command myprog which will read input from file.in and stdout of the command is directed to the file file.out
Bonus (10%): You will get 10% extra credit if your shell supports scrolling through history using up and down arrow keys. First up arrow key press should display the most recent command at
the prompt while first down arrow key should display the oldest command in the history.
Subsequent up or down arrow key press should scroll through the history likewise.
Notes:
You should use the skeleton program provided as a starting point for your implementation. The skeleton program reads the next command line, parses and separates it into distinct arguments using blanks as delimiters. You will implement the action that needs to be taken based on the command and its arguments entered to myshell. Feel free to modify the command line parser as you wish.
You can assume that all command line arguments will be delimited from other command line arguments by white space – one or more spaces and/or tabs.
For this project, the error messages should be printed to stderr.
Take into account materials and examples covered in the lab sessions. As a starting point, you can consider the example programs given in course web site.
Consider all necessary error checking for the programs. No late homework will be accepted!
In case of any form of copying and cheating on solutions, all parties/groups will get ZERO grade. You should submit your own work.
You have to work in groups of three. Group members may get different grades.
There will be demo section for this assignment. If you cannot answer the questions about your project details in the demo section, even if you have done all the parts completely, you will not get points!
If after 3 projects, your overall grade is higher than 100, it will be considered as 100.
What to submit?
A softcopy of your source codes which are extensively commented and appropriately structured and a minimum 3-page report should be emailed to cse333.projects@gmail.com in a zip file. Make sure that your zip file name contains student IDs (Student#1_Student#2_Student#3_Project2.zip)!