CS 322 Fall 2013
Project 2 |
The Mary Lyon Shell
|
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.
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 /Users/efourque/teaching/cs322/shell
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);where
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
mylysh$ cat < cat.c > myfile.ccauses the cat program to read from cat.c and write to the file myfile.c.
mylysh$ ls -l >> dirlistings.txtcauses the output of ls -l to be appended to the end of the existing file dirlistings.txt. 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.
mylysh$ > alines grep -i < Makefile a
should be interpreted the same as the more usual
mylysh$ grep -i a < Makefile > alines
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 displaySince 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$ cat makefile | wc -lsends 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.
#define PARSE_DEBUG 1 // debug mode : 1, remove print-out : 0 ..... ..... #ifdef PARSE_DEBUG print_args(com); #endifDouble-check the code inside the debug statments later: sometimes the code ends up running in debug mode while breaking in normal mode...
mylysh$ history # list n most previous command 1 gcc -o myproctree myproctree.c 2 ./myproctree 2 3 ./myproctree 5 4 man fork 5 cd ../../../cs211/workspace/ps/bin/ 6 java -cp ../../bailey.jar:. Interpreter < test.ps mylysh$ !4 # execute command 4 from the history
gcc -g -o myshell myshell.c -lncurses -lreadline
This project is graded out of 30 points.
Please submit om royal
/Shared/cs322/submit/proj2using a directory named with your two first names. You submission should include
script is a program that captures the screen output, saving it by default to file name typescript.
/Shared/cs322/public/UNIXSys_IO_proj2.pdf
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.
Examples
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().
Examples