In this assignment you will implement a small part of a shell program. You will write a program that implements the "pipe" and "I/O redirection" features of a shell. This assignment makes use of files contained in this zip file. The ideas and code used in this assignment are covered in Inter-Process_Communication.zip This assignment is due Monday, March 28.
A "pipe" is an operating system feature that lets one process communicate with another process. Pipes are created by calling the Windows operating system function CreatePipe(), but users of Windows can have the shell program cmd.exe create a pipe for them between two processes. In this assignment you will write a "baby shell" program that calls CreatePipe() and CreateProcess() to build a pipeline between two processes chosen by the user of your shell program.
In the zip file there is a program called bsh_demo.exe
that is a demonstration version of the baby shell that you need to write. This program takes a "command-line" as its command-line arguments. That is, you run the bsh_demo.exe
program with a command-line like this one.
hw2> bsh_demo.exe find \"pipe\" ^< hw2.html ^| sort /r ^> result.txt
This command-line has nine command-line arguments for the bsh_demo.exe
program. These command-line argument simulate a shell command-line. These arguments tell bsh_demo.exe
to create a pipeline between the find.exe
program and the sort.exe
program. The find.exe
program has a parameter, the string "pipe"
, and the program should have its stdin
redirected to the file hw2.html
. The sort.exe
program should have its stdout
redirected to the file result.txt
. The sort.exe
program also has a singe command-line argument of its own, /r
. So the shell command that is being simulated above would be.
hw2> find "pipe" < hw2.html | sort /r > result.txt
You can type this command directly in to the cmd.exe
shell. The result should be the same as the above execution of bsh_demo.exe
.
The "command-line" passed to bsh_demo.exe
looks kind of strange because it has several special characters in it. We are using command-line arguments to simulate a command-line. The problem is that we want command-line special characters, like <
or >
, to be command-line arguments to bsh_demo.exe
. In order to have the cmd.exe
shell ignore what would otherwise be special characters for it, we put an "escape character", the ^
, in front of the special characters like <
and >
. Similarly, we put the escape character in front of the pipe character, |
, so that cmd.exe
will not treat it as the pipe symbol. We also need to escape the quotes around the string "pipe"
but, for whatever weird reason, we use a different escape character here. We escape the quotes using \
.
In general, here is the syntax for the command-line arguments to bsh_demo.exe
.
bsh_demo program1 [arg_list] [^< in_file] ^| program2 [arg_list] [^> out_file]
The program1
and program2
arguments are both required. The argument lists for program1
and program2
are optional and they can be arbitrarily long. The in_file
and out_file
arguments are also optional (but must be accompanied by the escaped redirection symbols). The escaped pipe symbol, ^|
, is required. If you need any quotes in either of the two arg_lists, then the quotes must be escaped.
The semantics (meaning) of the above syntax is as follows. The bsh_demo
process shall:
program1.exe
program and give it whatever command-line arguments are present in the first optional arg_list
,program2.exe
program and give it whatever command-line arguments are present in the second optional arg_list
,program1
process and the standard input of the program2
process,in_file
option is present, redirect the standard input of the program1
process to the given input file, otherwise, let the program1
process inherit the standard input of the bsh_demo
process,out_file
option is present, redirect the standard output of the program2
process to the given output file, otherwise, let the program2
process inherit the standard output of the bsh_demo
process,program2
process to terminate.Here are some examples to think about (and try).
This example
hw2> bsh_demo doubleN ^| remove_vowels
means that bsh_demo.exe
should create a pipe between the doubleN.exe
and remove_vowels.exe
processes. The doubleN.exe
process should inherit standard input from bsh_demo.exe
. The remove_vowels.exe
process should inherit standard output from bsh_demo.exe
.
This example
hw2> bsh_demo doubleN ^< hw2.html ^| remove_vowels
means that bsh_demo.exe
should create a pipe between the doubleN.exe
and remove_vowels.exe
processes. The doubleN.exe
process should have its standard input redirected to the file hw2.html
. The remove_vowels.exe
process should inherit standard output from bsh_demo.exe
.
This example
hw2> bsh_demo doubleN 5 ^< hw2.html ^| remove_vowels
is similar to the previous one but here the doubleN.exe
process should be passed a single command-line argument, 5, when bsh_demo.exe
calls CreateProcess().
In this example
hw2> bsh_demo doubleN 5 ^< hw2.html ^| remove_vowels ^> result.txt
the only change is that now the remove_vowels.exe
process should have its standard output redirected to the file result.txt
(which should be created automatically if it doesn't already exist).
Here is a tricky example. The two commands
hw2> bsh_demo doubleN 5 ^< hw2.html ^| remove_vowels ^> result.txt hw2> bsh_demo doubleN 5 ^| remove_vowels < hw2.html > result.txt
should do essentially the same thing. Why? In each case, who is doing what I/O redirection? (Draw pictures! Your pictures should include the four processes cmd.exe
, bsh_demo.exe
, doubleN.exe
, and remove_vowels.exe
, a pipe, and the two files hw2.html
and result.txt
.)
Write a program bsh.c
that acts like bsh_demo.exe
. Your program will need to:
You're main source of code for this program is the file Pipeline.c
from the "9. Child to Child Pipeline" sub-folder of Inter-Process_Communication.zip. You should also look at the file CreateChildRedirectStdinStdout.c
from the "7. Redirect Child's Standard Streams" sub-folder.
In the zip file there are a number of filter programs that you can use when experimenting with the demo program or testing your program. There is also a file example_command_lines.cmd
that shows you a number of good examples for testing your program. I will use a file similar to this when grading your assignment.
In the zip file there is one example program, list_arguments.c
, that can be used both to test your program and also to experiment with command-line arguments and see exactly how the cmd.exe
shell treats special characters and their escape characters. See the notes inside list_arguments.c
for some good examples.
A few things to watch out for.
You must make the handles to the input and output files inheritable, otherwise the child processes will not see the files. But make sure that only program1
inherits the handle to the input file and only program2
inherits the handle to the output file. Similarly for the two pipe handles. On the other hand, the handles to the parent's stdin, stdout, and stderr are always inheritable.
Be sure to error check all your Windows operating system function calls. If one of those function calls fails silently, you will have a very hard time figuring out what went wrong. Error check all of them, even the CloseHandle()
calls.
You do not need to check the syntax of the command-line arguments in your version of bsh.c
. Your program can assume that every simulated "command-line" is correct and your program is allowed to fail spectacularly if there is a syntax error. The bsh_demo.exe
program does do some syntax checking, to make it easier to experiment with the program and learn how it should work. You do not need to emulate the demo program's error messages (though you are welcome to try; it's not really all that hard).
Turn in a zip file called CS302Hw2Surname.zip
(where Surname
is your last name) containing your C program bsh.c
.
This assignment is due Monday, March 28.
Here are references to relevant functions in the C Library and the Windows API.