Homework 2
Due Monday, October 20.

Directions for submission: Use tar to combine README, your *.c files and a Makefile. Then gzip and uuencode, and e-mail the result to the Reader.

In this problem, you will write a program similar to ftp. You will actually write a pair of programs, named dtp and dtpd, corresponding to ftp and ftpd.

The program dtp will fetch an entire directory tree which is rooted at the directory specified on the user's command line. (Note: The full path must be specified in that command-line argument, not just a relative path.) The program dtp will copy all files and directories in the entire directory tree, i.e. including subdirectories, subsubdirectories, and so on, and will set up the same tree, rooted in the directory from which dtp is invoked. (The action in terms of directory trees will be similar to `tar' and `cp -r'.)

The form of the command line is

        dtp  
For example, if dtpd is running on sgi8, then on my machine, heather.cs.ucdavis.edu, I might type
        dtp sgi8.cs.ucdavis.edu /home/matloff/Pub/Architecture
to copy the given directory tree from sgi8 to heather.

The program dtpd is intended to run constantly on machines which offer dtp access; in your testing, of course, you will run it on one machine and invoke dtp from another. Be sure that it is another machine, especially a different architecture (but NOT the DECs, which do not handle this correctly).

The dtpd program does not need to handle more than one request at a time. Do not worry about the file permissions in the files created on the client side.

The dtpd program must also keep a record, in a file named Vistors, of all machines from which it receives dtp "calls". So, in the example above, one of the entries in the Visitor file will be

heather.cs.ucdavis.edu
To implement this feature, use the getpeerbyname() and gethostbyaddr() functions, as follows. (Please add this information to your printed lecture notes, and consider it part of them.) Declare a variable, say s, of type sockaddr_in and initialize its sin_family field to AF_INET. Also, declare a variable, say i, of type int and initialize it to sizeof(sockaddr_in). Then the call to getpeername will have as its arguments the client socket descriptor, &s and &i. If you wish to get the address as a character string in ``Internet dot'' form, call the function inet_ntoa() on s.sin_addr. Define a variable, say hp, of type ``struct hostent *''. Then call gethostbyaddr() with the arguments &s.sin_addr, 4 and ``AF_INET'', assigning the return value to hp. The alphabetic host name will then be available as a character string in hp->h_name.

You may find it helpful to write your code in such a way that each time dtpd writes to the socket to dtp, dtpd prefaces the message with an integer indicating the length of the message. That way you can write code for dtp which easily distinguishes where one message ends and another begins.

I recommend that you start with the simpler case first, in which only one level of directory depth is allowed. Once you get that working, then add the recursive feature to implement the general case.

As in all assignments, you must follow specified requirements EXACTLY. In particular, the following are REQUIRED:

In this and all other homework assignments, "must" means "must"; "required" means "required". So for example, you cannot use the "tar" command to package a directory; that would be inconsistent with the requirements given above. HOMEWORK THAT DOES NOT COMPLY WITH THE REQUIREMENTS WILL NOT RECEIVE CREDIT.

You may find that your programs dtp and dtpd work on "smaller" problems but not on larger ones, say directory trees with a large number of levels, in which case you may exceed your limit of file descriptors. If this happens, don't worry about it. Also, if you wish to limit your program to files containing at most, say, 1000 bytes, that is fine.

To save typing or editing on your part, I have placed the source files for the wps/svr example from the printed lecture notes in the printed lecture notes package for this unit.