$24
Collaboration Policy. Homeworks will be done individually: each student must hand in their own answers. It is acceptable for students to collaborate in understanding the material but not in solving the problems or programming. Use of the Internet is allowed, but should not include searching for existing solutions.
Under absolutely no circumstances code can be exchanged between students. If some code was shown in class, it can be used, but it must be obtained from Canvas, the instructor or the TA.
Assignments from previous offerings of the course must not be re-used. Violations will be penalized appropriately.
Late Policy. No late submissions will be allowed without consent from the instructor. If urgent or unusual circumstances prohibit you from submitting a homework assignment in time, please e-mail me.
Problem 1. Shell-Within-Shell (100 points) Create a simple shell that allows you to launch programs using fork() and the exec() family of functions. Your shell should create a prompt (see below) and accept a string from the keyboard. Your program should process the string and decide if it is (i) a built-in command, (ii) a process that should be launched in the foreground, or (iii) a process that should be launched in the background. You do not need to check the correctness of the inputs to your shell. The user’s commands should be launched and the OS will handle any errors.
Your program should be called msh and should take no arguments. When your program runs, the commands you provide could look like the following:
SWS:student:/home/student/sharedls .. SWS:student:/home/student/sharedsudo find / -name stdio.h & SWS:student:/home/student/sharedwget http://norvig.com/big.txt
Requirements.
The prompt should have the form SWS:username:directory. SWS is a fixed identi-fier to distinguish your shell from the bash shell. You should retrieve username from the password file using the user’s uid. (You can use getpwuid() for this. See the 3rd set of notes.) Also, see the 3rd set of notes for how to retrieve the current working directory. The last character of the prompt should be . For example, your prompt should look like:
SWS:student:/home/student/shared
Use strtok() to tokenize the input string. Assume that commands, options and arguments are separated by spaces.
Your program should recognize two built-in commands: cd and exit. They should be executed without forking a new process.
1
If the user adds a & at the end of an input string for a non-built-in command, the process should be executed in the background. Make sure that there are no zombies. Before a process starts in the background, print the process ID number and the string, as in the following example:
pid: 1366 cmd: ls ..
After the child process is reaped, print its pid again, in a message like: pid 1366 done
If the user command is to be executed in the foreground, a child process should be forked and the parent process should wait for it. No printouts like the above should appear.
Install signal handlers for SIGINT and SIGCHLD using signal(). SIGINT should be disabled in the parent process; a newline character should be printed when it is received, but the shell should not be terminated. SIGINT handling is restored after exec() is called, so you only need to worry about the parent process. SIGCHLD should be handled as shown in the 10th part of the notes.
Hints.
You can think of the example in the 9th set of notes as pseudo-code for parts of this assign-ment, but it will not work directly.
You should include unistd.h, singal.h and sys/signal.h.
If you are having trouble retrieving the username, using uid instead will earn half of the relevant points.
Remember to remove the & from the arguments passed to command that will be launched.
Use waitpid() to wait for children running in the foreground.
Use waitpid() with WNOHANG to reap child processes running in the background.
Start with either the foreground or background option and make sure that it works before moving on.
Keep in mind that you can use exit to exit the shell, not CTRL-C.
Deliverables. A zip/tar/gz file containing:
Source files, including at least one header file.
The makefile.
Everything must work on the virtual machine we have provided.
In a pdf file, please answer the following questions.
2
Why are exit and cd handled as built-in commands and no child processes are forked? What would happen if you forked children for these commands?
Why should you use killpg(getpid(), SIGTERM); before main() exits?
Homework 03 questions
Why are exit and cd handled as built-in commands and no child processes are forked? What
would happen if you forked children for these commands?
a. These commands are handled without forking because they are actions that should be
happening to the parent instead of to a child. For example, typing “exit” and having it
fork would just cause the parent to fork and the child instantly exits which does nothing.
Likewise, “cd” would change the directory of the child, but the user wants to change the
directory of the parent.
b) Why should you use killpg(getpid(), SIGTERM); before main() exits?
a. This line is necessary in the event the parent wants to exit before the children are done.
If this line was not present, the children would have never been fetched and would
become zombies. This line kills any children still running so the parent process can safely
exit.
3