ftp/ftpc.c
author Madhusudan.C.S <madhusudancs@gmail.com>
Mon, 18 Jan 2010 14:10:13 +0530
changeset 0 30d751ac6d49
child 1 47438813ede2
permissions -rw-r--r--
Solution to first assignment. First assignment was to implement a FTP Server and Client using SUN RPC. This is in C. Doesn't support binary file formats yet. Both binary file format transfer support and Python equivalent of the code is to be added yet.

#include <rpc/rpc.h>
#include <stdio.h>
#include <string.h>
#include "ftp.h"

extern __thread int errno;

/*
 * Gets the requested file from the server by calling the
 * remote procedure in a loop
 */
int get_file(char *host, char *name)
{
    CLIENT *clnt;
	int total_bytes = 0, write_bytes;
    readfile_res *result;
	request req;
	FILE *file;

    /*
	 * Initialize the request with the file name 
	 */
	req.name = name;

    /*
     * Create client handle used for calling FTPPROG on
     * the server designated on the command line. Use
     * the tcp protocol when contacting the server.
     */
    clnt = clnt_create(host, FTPPROG, FTPVER, "tcp");
    if (clnt == NULL) {
        /*
         * Couldn't establish connection with server.
         * Print error message and stop.
         */
         clnt_pcreateerror(host);
         exit(1);
    }

	/*
	 * Open the file for writing on the client machine
	 */
    file = fopen(name, "w");

    /*
     * Call the remote procedure retrieve_file on the server.
	 * During each iteration of the loop remote procedure is
	 * called and only 1024 bytes of data is read and returned
	 * by the server. The loop terminates when the data returned
	 * from the server is less than 1024 bytes
     */
	while (1) {
		/*
		 * Specifies the byte position where the next read should be
		 * started in the server.
		 */
		req.start = total_bytes;

        result = retrieve_file_1(&req, clnt);
        if (result == NULL) {
            /*
             * An RPC error occurred while calling the server.
             * Print error message and stop.
             */
            clnt_perror(clnt, host);
            exit(1);
        }

        /*
         * We successfully called the remote procedure.
         */
        if (result->errno != 0) {
            /*
             * A remote system error occurred.
             * Print error message and stop.
             */
            errno = result->errno;
            perror(name);
            exit(1);
        }

        /*
         * Successfully got a chunk of the file.
         * Write into our local file and update the
		 * total bytes of data read till now.
         */
		write_bytes = fwrite(result->readfile_res_u.chunk.data, 1, result->readfile_res_u.chunk.bytes, file);
		total_bytes += result->readfile_res_u.chunk.bytes;
		if (result->readfile_res_u.chunk.bytes < MAXLEN) 
		    break;
	}

	fclose(file);

	return 0;
}

/*
 * Stores the file on the server by calling the remote
 * procedure in a loop
 */
int put_file(char *host, char *name)
{
    CLIENT *clnt;
    char data[1024];
	int read_bytes;
    int *result;
	chunksend chunk;
	FILE *file;

    /*
     * Create client handle used for calling FTPPROG on
     * the server designated on the command line. Use
     * the tcp protocol when contacting the server.
     */
    clnt = clnt_create(host, FTPPROG, FTPVER, "tcp");
    if (clnt == NULL) {
        /*
         * Couldn't establish connection with server.
         * Print error message and stop.
         */
         clnt_pcreateerror(host);
         exit(1);
    }

    /*
	 * Open the file that should be stored on the server
	 */
    file = fopen(name, "r");

    /*
	 * Initialize the chunk to be sent with the name
	 * of the file
	 */ 
	chunk.name = name;

    /*
     * Call the remote procedure readdir on the server
	 * in a loop sending only 1024 bytes of data in each
	 * iteration. The loop terminates once the data less
	 * than 1024 bytes is sent.
     */
	while (1) {
		read_bytes = fread(data, 1, MAXLEN, file);

        chunk.data = data;
		chunk.bytes = read_bytes;
        result = send_file_1(&chunk, clnt);

        if (result == NULL) {
            /*
             * An RPC error occurred while calling the server.
             * Print error message and stop.
             */
            clnt_perror(clnt, host);
            exit(1);
        }

        /*
         * Okay, we successfully called the remote procedure.
         */
        if (*result != 0) {
            /*
             * A remote system error occurred.
             * Print error message and stop.
             */
            errno = *result;
            perror(name);
            exit(1);
        }

        /*
         * Successfully got a chunk of the file.
         * Write into our local file.
         */
		if (read_bytes < MAXLEN) 
		    break;
	}

	fclose(file);

	return 0;
}

/*
 * Handles commands read on the command line and calls
 * the appropriate function to handle the command
 */
int read_command(char *host)
{
	char command[MAXLEN];

	printf("> ");
	fflush(stdin);
	gets(command);

    if (strncmp(command, "get", 3) == 0) {
		return get_file(host, command+4);
	} else if(strncmp(command, "put", 3) == 0){
		return put_file(host, command+4);
	} else if(strncmp(command, "exit", 4) == 0){
		exit(0);
    } else {
		return -1;
	}
}

int main(int argc, char *argv[])
{
   int result;

   if (argc != 2) {
        fprintf(stderr, "usage: %s host\n", argv[0]);
        exit(1);
   }

   /*
    * Command handling loop
	*/
   while(TRUE) {
	   result = read_command(argv[1]);
   }

   return 0;
}