$30
CS 392: Homework Assignment 3
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.
1. The prompt should have the form SWS:username:directory. SWS is a fixed identifier 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
2. Use strtok() to tokenize the input string. Assume that commands, options and arguments
are separated by spaces.
3. Your program should recognize two built-in commands: cd and exit. They should be
executed without forking a new process.
1
4. 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
5. 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.
6. 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.
1. You can think of the example in the 9th set of notes as pseudo-code for parts of this assignment, but it will not work directly.
2. You should include unistd.h, singal.h and sys/signal.h.
3. If you are having trouble retrieving the username, using uid instead will earn half of the
relevant points.
4. Remember to remove the & from the arguments passed to command that will be launched.
5. Use waitpid() to wait for children running in the foreground.
6. Use waitpid() with WNOHANG to reap child processes running in the background.
7. Start with either the foreground or background option and make sure that it works before
moving on.
8. Keep in mind that you can use exit to exit the shell, not CTRL-C.
Deliverables. A zip/tar/gz file containing:
1. Source files, including at least one header file.
2. The makefile.
3. Everything must work on the virtual machine we have provided.
4. In a pdf file, please answer the following questions.
2
(a) 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?
(b) Why should you use killpg(getpid(), SIGTERM); before main() exits?
3