The goal of this assignment is to get everyone up to speed on system programming and to become familiar with the system call interface. A secondary goal is to use some of the programming tools provided in the Unix/Linux environment. In this assignment you are to implement a Unix/Linux shell program. A shell is simply a program that conveniently allows you to run other programs. Read up on your favorite shell to see what it does. You may work by yourself or with one partner.
Your shell must support the following:
1. The internal shell command "exit" which terminates the shell.
Concepts: shell commands, exiting the shell
System calls: exit()
2. A command with no arguments
Example: ls
Details: Your shell must block until the command completes and, if the return code is abnormal, print out a message to that effect.
Concepts: Forking a child process, waiting for it to complete, synchronous execution
System calls: fork(), execvp(), exit(), wait()
Your solution must also support the following:
1. A command with arguments
Example: ls -l
Details: Argument 0 is the name of the command
Concepts: Command-line parameters
2. A command, with or without arguments, executed in the background using &.
For simplicity, assume that if present the & is always the last thing on the line.
Example: xemacs &
Details: In this case, your shell must execute the command and return immediately, not blocking until the command finishes.
Concepts: Background execution, signals, signal handlers, processes, asynchronous execution
System calls: sigset()
3. A command, with or without arguments, whose output is redirected to a file
Example: ls -l > foo
Details: This takes the output of the command and put it in the named file
Concepts: File operations, output redirection
System calls: freopen()
4. A command, with or without arguments, whose input is redirected from a file
Example: sort < testfile
Details: This takes the named file as input to the command
Concepts: Input redirection, more file operations
System calls: freopen()
5. A command, with or without arguments, whose output is piped to the input of another command.
Example: ls -l | more
Details: This takes the output of the first command and makes it the input to the second command
Concepts: Pipes, synchronous operation
System calls: pipe()
Note: You must check and correctly handle all return values. This means that you need to read the man pages for each function to figure out what the possible return values are, what errors they indicate, and what you must do when you get that error.
1. You will need to make use of system calls such as execvp(), fork(), pipe(), wait() and dup2().
2. Assume the user enters "ls -lt | sort | more". Your shell would create a process for each command. A pipe must be created (using the pipe command) between the first and second process and the second and third process. Creating a pipeline between two processes is relatively simple (you have sample code for this), but the building of a multiple command pipeline is more difficult.
3. You may use any of the system calls found in the exec() family. If you use execvp, remember that the first argument in the array is the name of the command itself, and the last argument must be a null pointer.
4. A shell needs a command-line parser. The parser breaks down the string representing the command into constituent parts. These parts are referred to as tokens. To read a line from the user, you may use gets(). The parser you implement may use scanf(), strtok() or any other suitable C library functions. Parsing requires these steps:
5. Develop your code in incremental stages. One order of stages is the following:
6. Add support for pipes