The lab questions below are optional. If you solve them I would be happy to check them out and give you feedback. If you choose not to bother with them no worries, similar concepts will appear in the assignments.
There exists a Unix command called file which tests each of its
arguments (which must be file names) in an attempt to classify them.
It then prints a short description of all the arguments. For
instance, the command file applied to a C++ source file
foo.cc will print:
foo.cc: ASCII C program text
The following asks you to write a wrapper for the Unix command
file, as follows: Your program reads from the standard input a
number of file names, one per line. For each input, the program
invokes the command file and prints to the standard output the
result. The program terminates when it reads an empty string.
Create two versions of the program, one what waits for a file
command to complete before issuing the next command, and another that
does not wait (instead, the command file will be called on the
file name given by the just read line before processing the remainder
of the input). No matter the version there must be no input prompt.
Suppose that you have a program called foo that reads/writes
from/to the standard input/output (i.e., by using cin and
cout). Then, you could type the following command:
./foo < some_file
The effect is that foo receives the content of
some_file as input (including newlines), just as if someone
would have typed this content while foo runs.
The output can also be redirected to a file. The following command
puts the output of foo into the file results instead
of printing it to the terminal:
./foo > results
Of course, the two redirections can be combined, e.g.,
./foo < some_file > results
Finally, the output of one program can be fed as input to another
program. For example, in the following command the input of
foo is the output of the command ls:
ls | foo
In terms of your program, I recommend to test it by redirecting the
input (and possibly the output). For instance, you could perform
the following tests (I assume that the executable is called
files):
ls -a | ./files
This will (hopefully) call file on all the files contained
in the current directory. Then,
input) and do
./files < input
ls -a | ./files > results1
./files < input > results2
file
invocations in a file whose name is given as command line argment.
Use for this purpose POSIX file I/O calls.
file to a more verbose call such as
cat. Test both variants of your program under suitable input
re-direction. Do you note any difference in the output of these two
variants? Why (not)?
In answering this question you may want to try various well known services such as SMTP (port 25) and HTTP (port 80). You will need to find the application protocols for these services by yourself.
<--, and
j118-1.ubihsops.ca:Thu Jan 25 13:36:44 2007:503 5.0.0 Polite people say HELO firstThe answer given by the server could be on more than one line, and there is no character that signals the end of the answer. You should thus read the answer until no data is available (within a reasonable time).
Writing to file f should not destroy anything that is already there. If f does not exists, it should be created anew. Any error condition encountered during the processing must generate a suitable error message.
Welcome to the wonderful world of servers. We shall now build sort of
a remote shell server that will accept commands from clients and will
execute them locally. All the incoming requests (except for the
particular request CPRINT, detailed below) are considered
normal shell commands. The server then attempts to run the given
command locally, and replies upon completion with one ``status line''
that has the form
statuscodemessage
where
OK (signifying that the command
completed successfully), FAIL (meaning that the command could
not be executed), and ERR (meaning that the command
terminated prematurely because of an error condition).
| Response | Meaning of code |
OK |
always 0 (zero) |
ERR |
the (non-null) exit status of the executed command |
FAIL |
the server-side error code (errno)
that describes the cause of the failure |
FAIL message it would be nice for this
field to contain the readable description of the error code.
Commands may print things to the standard error and output streams when running. Such an output is not sent back to the client by default. Instead, the stuff printed by the most recently executed command is remembered by the server and is sent to the client only upon request. A client can ask for the output of the most recent command by issuing the following request:
CPRINT
Upon receipt of such a request, the server sends to the client the
(possibly empty) output of the most recently executed shell command,
followed by a ``status line'' as described before. A FAIL such
a line is emitted when an internal server error prevented the output
to be produced, and an ERR line is sent only when no command
has been issued in the current session (and thus there is nothing to
print); in the latter case, the error code shall be set to EIO
(input/output error).
Your server must be concurent. You are further required to use single-threaded processes for this assignment.