Lab 11

The Unix Shell II


  • Integrate some of your knowledge of systems programming. In Lab 10, you developed the basic functionality of a shell. In this lab, you will push the implementation of your shell a little further along.


This lab was developed by Prof. L. Felipe Perrone based on an assignment created by Magnus Johansson (Uppsala University). Permission to reuse this material in parts or in its entirety is granted provided that this credits note is not removed. Additional students files associated with this lab, as well as any existing solutions can be provided upon request by e-mail to perrone[at]bucknell[dot]edu

Set Up

In this lab, you will develop a bit further the work you did to create a Unix shell. First of all, you will need to team up with three other students. That is, this work will be done in teams of 4 students. Doing this work individually is not an option and you must find partners within your own lab section.

Get together with your teammates and discover which “extra” functionality they have implemented for their ishell in Lab 10. Remember that what we understand by “extra” are command line functionality that were not explicitly requested for implementation in Lab 10.

Today’s work will consist of building a new shell which includes a minimum of four different extra functions. If all the members of your team have implemented different extras, you can just combine them all into a common code base. If more than one of your teammates have implemented the same “extra,” your team will need to work together to produce additional functionalities. After all, as stated earlier, the final product of your team must offer as many different extras as there are teammates.

Additionally, in this new assignment, the “exit” function will be a standard feature of the new version of the shell. If any of your teammates implemented “exit” for their Lab 10 solution, they will have to replace it with a different extra.

Problem 1 (70 points)

The first step for your team work is to elect someone’s ishell code to be the basis of this new assignment. All additional development will be done on this single, common code base which will constitute a new file called gshell.c. The team should have a discussion to structure of this code base so that each member can add their individually contributed features with minimal hassle. Only after this restructuring is completed should the team move on.

Modify your shell’s prompt to display gshell> instead of ishell>. Next, each team member will add their “extra” feature into gshell.c. It is up to the team to determine how you will all work together on the same file. Of course, a natural option is for one of you to create a new Gitlab project that is shared with all the members of the team. This would allow each individual to pull the repository, add their individual feature to gshell.c, test and eliminate any possible bugs, and push it out for other teammates to see. Considering that people will work concurrently on the same file, you should expect that git merges will be necessary. As long as everyone is working on disjoint portions of the shared code base, you will most likely discover that git handles merges very smoothly. Feel free to use any other method for collaboration that is not based on git, if you prefer, but understand that you’re avoiding a good learning opportunity.

Once everyone has added their contributed extra features to gshell.c, the team should create a README.txt file containing:

  • The names of all members of the team.
  • For each extra function implemented: a brief description of what the function does and one or more examples of how it is used.

The team should also produce Makefile that builds the gshell executable. Work as a team to make sure that the final product works correctly and then distribute the two files to all the team members, who will add them to their individual git repositories.
Each team member should:

  • cd ~/csci315/Lab11
  • git add gshell.c
  • git add README.txt
  • git add Makefile
  • git commit -m “Lab 11.1 completed”
  • git push

Grading Rubric:

  • [10 points] README.txt with complete and clear information.
  • [10 points] gshell executes correctly all the functionality of Lab 10 without bugs or crashes.
  • [10 points] for each of the four extra features.
  • [10 points] Working Makefile.

Problem 2 (30 points)

**After** the integration of their contributions to gshell, each team member should work on this problem individually.

You now understand that every process that is started in Unix is born with three file descriptors:

  • stdin (fd = 0)
  • stdout (fd = 1)
  • stderr (fd = 2)

You can experiment with these file descriptors from the shell’s user interface to remap some of these file descriptors, so that you can redirect input and/or output in unexpected ways. For instance, if you want to throw the output of  the “ls” program into a file, in bash, you could do something like:

 $ ls -lsa > dir-contents.txt

The ‘>‘ maps the output of the first process in this command line to a new file called “dir-contents.txt“. This is an easy way to record the output of a program directly into a file, without any of that “cut and paste” silly business. It turns out that what works for output (stdout), though, works for input (stdin), too. For example:

$ wc < dir-contents.txt

The ‘<‘ maps the input of program wc(1) (read the man page for details) to file “dir-contents.txt“. These are not the only ways in which bash implements I/O redirection, though, nor the most interesting. There are many other use cases to explore and you are encouraged to pursue this on your own. (Here is one source you may want to read.)

A particularly cool use of I/O redirection is when you map the output of one program directly into the input of another. As in the following example:

$ ps -ef | grep root

This executes the program ps and then pipes its output directly into the standard input of another program, in this case grep, which filters the text it receives down to any lines containing the string “root”. The use of the ’|‘ character here is interpreted by bash as a command to create two processes to execute ps and grep and to map the stdout file descriptor of the first to the stdin file descriptor of the second.

For this problem, you will augment your gshell to include only the pipe type of I/O redirection for two processes only.

In your gshell, you will have to create one or more pipes to interconnect two programs, closing the unused end(s), as always, and use the dup2(2) system call to make the redirection work. You will need to flex your “independent learning muscles” to understand this system call and to figure out how to use it. To test whether it’s working, use commands like the one shown below:

gshell> ps -ef | grep root

When you are done:

  • cd ~/csci315/Lab11
  • git add gshell.c
  • git add Makefile
  • git commit -m “Lab 11.2 completed”
  • git push

Hand In

Before turning in your work for grading, create a text file in your Lab 11 directory called submission.txt. In this file, provide a list to indicate to the grader, problem by problem, if you completed the problem and whether it works to specification. Wrap everything up by turning in this file:

  • git add ~/csci315/Lab11/submission.txt
  • git commit -m “Lab 11 completed”
  • git push
Print Friendly