CS 322 Fall 2013
Project 2
The Mary Lyon Shell
Demo: Friday, October 18th at 1:15 A.M.
Code Due Friday, October 18th at 10:00 P.M.

The shell or command line interpreter is the fundamental user interface to an operating system. In effect, the very first experimental system using a mouse and multiple windows (the Cedar system at Xerox PARC), which was supposed not to need a shell because of point-and-click plus resource forks, the first tool created by a system programmer wanting to be more efficient was a shell similar to the Bourne shell. Within a few weeks everybody on the development team was using it.

In this project, you implement in C a mini shell, which is called the Mary Lyon Shell: mylysh.
mylysh is similar to familiar Unix shells such as the Bourne shell (sh) the Bourne-Again shell (bash), and C shells (csh, tcsh).

The goals of this project are:

You may work in groups of two. Collaboration within a group is, of course, unrestricted. You may discuss the program with members of other groups, but what you turn in must be your own group's work. It is a violation to the Honor Code not to acknowledge others' work fully and openly. You should cite any online resources you consulted to help you solve this project.

Groups must be formed no later than Wednesday, October 9, 2013, 5:00 P.M. Please post on Moodle's Project 2 Forum the composition of your group.


mylysh supports
  1. user commands, such as ls or grep,
  2. shell built-in commands or shell built-ins: cd and exit
  3. running a command in the background (using &)
  4. commands with I/O re-direction
  5. commands with a single pipe


Like all Unix shells, mylysh executes a loop. It
  1. prints the shell prompt,
  2. reads the command line (terminated with '\n')
  3. parses the command line
  4. creates argument lists,
  5. execs the command with its arguments, then waits until the command finishes (unless &).
  6. Repeat the loop until the exit command is entered.

In general, a shell forks a child process to execute a command. Commands have the form

	"commandname [arg1 arg2 ...]"
For example three simple commands follow.
	mylysh$ ls -la				# long listing of current directory 
	-rwxr-xr-x   1 efourque   staff   14640 Oct  6 16:57 lyon
	-rwxrwxrwx   1 efourque   staff    8293 Oct  6 16:58 lyonshell.c
	-rw-r--r--   1 efourque   staff      67 Oct  6 13:20 makefile
	mylysh$ cat makefile			# cat content of makefile
	mylysh$ pwd				# absolute path to current working directory


C has library functions for reading commands and parsing them. mylysh must be robust against two types of bad user input. Parsing a command creates the arguments for execvp
	execvp(command_name, command_argv_list);
The first argument is a string containing the command name. The second argument is a list of strings: the first one is the name of the command, followed by one string per command line argument, and followed by NULL. For example, to execute ls -l, the following is called
	execvp("ls", arg);
	arg[0] = "ls"; 
	arg[1] = "-l"; 
	arg[2] = NULL; 
It is recommended to use readline and strtok as you did for previous C exercises. Don't forget to link with the readline library.
	gcc -Wall -o lyon lyonshell.c -lreadline

Shell Built-in

A shell has also built-in commands, which are executed within the running shell's process (see man builtin).
mylysh has two built-in commands
  1. exit: exit from the shell
  2. cd: change the current working directory
Implementing cd requires two C functions: After invoking the cd command subsequent calls to pwd or ls should reflect the change in the working directory.

I/O Redirection

mylysh supports I/O redirection on stdin (standard input) and/or stdout (standard input). Specifically, Output redirection uses two redirection tokens.

An individual command may only redirect input once and output once, but those redirections may be specified in any order.

In implementing redirection notice that every process has three default file identifiers in its file descriptor table with default values:

	#   fd		default
        0   stdin	keyboard
        1   stdout	terminal display
        2   stderr	terminal display

Since each process gets a copy of its parent's file descriptor table, a shell re-directs a child process's I/O by manipulating the child's file identifiers.


mylysh supports command execution with a single pipe. For example
	mylysh$ cat makefile | wc -l
sends the output of cat makefile to be the input of wc -l: cat's output is pipe'ed to wc's input. Specifically, the shell process forks two process and waits for both to finish before printing the next shell prompt. To set up the communication between the two child processes use the pipe system call and I/O redirection.

The pipe reading process exits when it reads EOF on its input; any process blocked on a read unblocks when the file is closed. However, if several processes have the same file open, all must close it to trigger an EOF. Therefore, when you write programs that create pipes (or open files), you need to be very careful about how many processes have the files open, to ensure that EOF conditions are triggered correctly.



For fun try these once your shell is complete, correct and robust.


This project is graded out of 30 points.

Command with no arguments
Command with arguments
Builtin commands
Input/output redirection
Pipe between two processes
Background process
Documentation & README
Programming style

Please submit om royal

using a directory named with your two first names. You submission should include
  1. All the sources files needed to compile your code (use a makefile if you have .c files and .h file).
    Please de not submit object (.o) or executable files.
  2. A README file with following content.
  3. A file containing the output from your testing of mylysh. Make sure to demonstrate
    1. simple commands
    2. built-in commands
    3. background command
    4. I/O redirection
    5. pipe and
    6. some error conditions

    script is a program that captures the screen output, saving it by default to file name typescript.


Consider the pdf document available on royal

I/O Redirection

You will need to duplicate file descriptors. The dup2() system call permits to reroute things that were going to one file descriptor into another file descriptor.



Unix pipes are one way that a process send data streams to another process. An unnamed pipe can be created using the

	int pipe(int fd[]);
system call.

fd is an array of two int values. These are file descriptors, similar to the file descriptors used for file I/O (i.e. open() , read() , and write().