title: File transfer using RPC(any type of file)
body: <p>I want to construct a RPC Program to transfer any type of files. But I am getting segmentation fault after running the client:such as</p>
  
  <pre><code>./file_client localhost
  &gt;get /home/ab/1.txt
  &gt;put /home/1.txt
  Segmentation Fault
  </code></pre>
  
  <p>For your convenience I am pasting my client and server and .x code:</p>
  
  <p><strong>file.x</strong></p>
  
  <pre><code>const MAXLEN = 1024;
  
  /*
   * Type for storing path
   */
  typedef string filename&lt;MAXLEN&gt;;
  
  /*
   * Structure for sending request. Expects the path of the file
   * and the byte number at which to start reading the file from
   */
  struct request {
      filename name;
      int start;
  };
  
  /*
   * Type that represents the structute for request
   */
  typedef struct request request;
  
  /*
   * Type for storing a chunk of the file that is being
   * sent from the server to the client in the current
   * remote procedure call
   */
  typedef opaque filechunk[MAXLEN];
  
  /*
   * Response sent by the server to the client as a response
   * to remote procedure call, containing the filechunk for
   * the current call and number of bytes actually read
   */
  struct chunkreceive {
      filechunk data;
      int bytes;
  };
  
  /*
   * Type that represents the structure for file's chunks
   * to be received from the server
   */
  typedef struct chunkreceive chunkreceive;
  
  /*
   * File data sent by the server from client to store
   * it on the server along with the filename and the
   * number of bytes in the data
   */
  struct chunksend {
      filename name;
      filechunk data;
      int bytes;
  };
  
  /*
   * Type that represents the structure for file's chunks
   * to be sent to the server 
   */
  typedef struct chunksend chunksend;
  
  /*
   * union for returning from remote procedure call, returns
   * the proper chunkdata response if everything worked fine
   * or will return the error number if an error occured
   */
  union readfile_res switch (int errno) {
      case 0:
          chunkreceive chunk;
      default:
          void;
  };
  
  /*
   * Remote procedure defined in the Interface Definition Language
   * of SUN RPC, contains PROGRAM and VERSION name definitions and
   * the remote procedure signature
   */
  program FTPPROG {
      version FTPVER {
          readfile_res retrieve_file(request *) = 1;
          int send_file(chunksend *) = 2;
      } = 1;
  } = 0x20000011;
  </code></pre>
  
  <p><strong>My server code is:</strong></p>
  
  <pre><code>#include &lt;rpc/rpc.h&gt;
  #include &lt;stdio.h&gt;
  #include "file.h"
  
  extern __thread int errno;
  
  readfile_res* retrieve_file_1_svc(request *req, struct svc_req *rqstp)
  {
      FILE *file;
      char data[1024];
      int bytes;
      static readfile_res res;
  
      file = fopen(req-&gt;name, "rb");
      if (file == NULL) {
          res.errno = errno;
          return (&amp;res);
      }
  
      fseek (file, req-&gt;start, SEEK_SET);
      bytes = fread(res.readfile_res_u.chunk.data, 1, 1024, file);
  
      //res.readfile_res_u.chunk.data = data;
      res.readfile_res_u.chunk.bytes = bytes;
  
      /*
       * Return the result
       */
      res.errno = 0;
      fclose(file);
      return (&amp;res);
  }
  
  int* send_file_1_svc(chunksend *rec, struct svc_req *rqstp)
  {
      FILE *file;
      int write_bytes;
      static int result;
  
      file = fopen(rec-&gt;name, "a");
      if (file == NULL) {
          result = errno;
          return &amp;result;
      }
  
      write_bytes = fwrite(rec-&gt;data, 1, rec-&gt;bytes, file);
      fclose(file);
  
      result = 0;
      return &amp;result;
  }
  </code></pre>
  
  <p><strong>My client code is:</strong></p>
  
  <pre><code>#include &lt;rpc/rpc.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;string.h&gt;
  #include "file.h"
  
  extern __thread int errno;
  
  int get_file(char *host, char *name)
  {
      CLIENT *clnt;
      int total_bytes = 0, write_bytes;
      readfile_res *result;
      request req;
      FILE *file;
  
      req.name = name;
      req.start = 0;
  
      /*
       * 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);
      }
  
      file = fopen(name, "wb");
  
      /*
       * Call the remote procedure readdir on the server
       */
      while (1) {
          req.start = total_bytes;
          result = retrieve_file_1(&amp;req, 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-&gt;errno != 0) {
              /*
               * A remote system error occurred.
               * Print error message and stop.
               */
              errno = result-&gt;errno;
              perror(name);
              exit(1);
          }
  
          /*
           * Successfully got a chunk of the file.
           * Write into our local file.
           */
          write_bytes = fwrite(result-&gt;readfile_res_u.chunk.data, 1, result-&gt;readfile_res_u.chunk.bytes, file);
          total_bytes += result-&gt;readfile_res_u.chunk.bytes;
          if (result-&gt;readfile_res_u.chunk.bytes &lt; MAXLEN) 
              break;
      }
  
      fclose(file);
  
      return 0;
  }
  
  int put_file(char *host, char *name)
  {
      CLIENT *clnt;
      char data[1024];
      int total_bytes = 0, 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);
      }
  
      file = fopen(name, "r");
  
      chunk.name = name;
  
      /*
       * Call the remote procedure readdir on the server
       */
      while (1) {
          read_bytes = fread(data, 1, MAXLEN, file);
          total_bytes += read_bytes;
  
          read_bytes = fread(chunk.data, 1, MAXLEN, file);
          chunk.bytes = read_bytes;
          result = send_file_1(&amp;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 &lt; MAXLEN) 
              break;
      }
  
      fclose(file);
  
      return 0;
  }
  
  int read_command(char *host)
  {
      char command[MAXLEN], filepath[MAXLEN];
  
      printf("&gt; ");
      fflush(stdin);
      scanf("%s %s", command, filepath);
  
      if (strcmp(command, "get") == 0) {
          return get_file(host, filepath);
      } else if(strcmp(command, "put") == 0){
          return put_file(host, filepath);
      } else if(strcmp(command, "exit") == 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);
     }
  
     while(TRUE) {
         result = read_command(argv[1]);
     }
  
     return 0;
  }
  </code></pre>
  
  <p>Can any one advice me what are the modifications I need to follow here.</p>
  
  <p>Thanx in advance.</p>