This part of code is for the client. It need to receive first the file size and then the size:

Code:
void do_retr_cmd(int f_sockd){
  int fd;
  ssize_t nread = 0;
  uint32_t fsize, fsize_tmp, total_bytes_read, size_to_receive;
  char *filename = NULL, *conferma = NULL, *filebuffer = NULL;
  char buf[256], dirp[256], t_buf[256];


  memset(dirp, 0, sizeof(dirp));
  memset(buf, 0, sizeof(buf));
  memset(t_buf, 0, sizeof(t_buf));
  printf("Write the name of file to download: ");
  fgets(dirp, BUFFGETS, stdin)
  filename = NULL;
  filename = strtok(dirp, "\n");
  sprintf(buf, "RETR %s", dirp);
  if(send(f_sockd, buf, strlen(buf), 0) < 0){
    perror("Errore durante l'invio del nome del file");
    onexit(f_sockd, 0, 0, 1);
  }
  fsize = 0;
  recv(f_sockd, t_buf, sizeof(t_buf), 0)
  fsize = atoi(t_buf);
  fd = open(filename, O_CREAT | O_WRONLY, 0644);
  fsize_tmp = fsize;
  filebuffer = (char *)malloc(fsize);
  total_bytes_read = 0;
  nread = 0;
  for(size_to_receive = fsize; size_to_receive > 0;){
    nread = read(f_sockd, filebuffer, size_to_receive);
    if(nread < 0){
      perror("read error on retr");
      onexit(f_sockd, 0, 0, 1);
    }
    if(write(fd, filebuffer, nread) != nread){
      perror("write error on retr");
      onexit(f_sockd, 0, 0, 1);
    }
    size_to_receive -= nread;
  }
  close(fd);
  fflush(stdout);
  fflush(stdin);
  memset(buf, 0, sizeof(buf));
  recv(f_sockd, buf, 21, 0)
  printf("%s", buf);
  memset(buf, 0, sizeof(buf));
  memset(t_buf, 0, sizeof(t_buf));
  memset(dirp, 0, sizeof(dirp));
  free(filebuffer);
}
Here's the code of the server which first send the file size and then the file:

Code:
void do_server_retr_cmd(f_sockd, m_sockd){
  int fd, rc;
  uint32_t fsize, size_to_send;
  char *filename = NULL, *other = NULL;
  char buf[512], t_buf[256];
  off_t offset;
  struct stat fileStat;


  memset(buf, 0, sizeof(buf));
  memset(t_buf, 0, sizeof(t_buf));
  recv(f_sockd, buf, sizeof(buf), 0)
  other = NULL;
  filename = NULL;
  other = strtok(buf, " ");
  filename = strtok(NULL, "\n");


  if(strcmp(other, "RETR") == 0){
    printf("Ricevuta richiesta RETR\n");
  } else /* do something */


  fd = open(filename, O_RDONLY);


  memset(&fileStat, 0, sizeof(fileStat));
  fileStat.st_size = 0;
  fstat(fd, &fileStat)
  fsize = fileStat.st_size;
  snprintf(t_buf, 255, "%" PRIu32, fsize);
  send(f_sockd, t_buf, sizeof(t_buf), 0)
  offset = 0;
  for (size_to_send = fsize; size_to_send > 0; ){
    rc = sendfile(f_sockd, fd, &offset, size_to_send);
    if (rc <= 0){
      perror("sendfile");
      onexit(f_sockd, m_sockd, fd, 3);
    }
    size_to_send -= rc;
  }
  close(fd);
  fflush(stdout);
  fflush(stdin);
  memset(buf, 0, sizeof(buf));
  strcpy(buf, "226 File transfered\n");
  send(f_sockd, buf, strlen(buf), 0)
  memset(buf, 0, sizeof(buf));
  memset(t_buf, 0, sizeof(t_buf));
}
--> Errors checking have been omitted <--
I have a big problem with these 2 pieces of code. When i start the main program i have to do:
1. write retr and then press enter
2. Write the filename to download and - again - press enter.
The problem is that sometimes the file is downloaded correctly and sometimes it is not downloaded but a part of it is displayed on stdout (on the client's terminal).
I don't understand why i got this strange behavior.
PS: i know my code is ugly but i a C-newbie!


I'm developing on Ubuntu amd64 and using GCC-4.6.3 (C language).