Home > front end >  Reading file descriptor size from popen command for socket programming in C
Reading file descriptor size from popen command for socket programming in C

Time:09-09

I have seen similar questions asked but I seek a more specific way of how to correctly do it. I am creating a client and a server UDP FTP service where the client has options of

  • get [file_name]
  • put [file_name]
  • delete [file_name]
  • ls
  • exit

Currently, all implementations work except for my ls as I am trying to ensure the contents of "ls" are less than my buffer size so I know whether to receive/send continually. From what I have learned with research, I am getting an error because you cannot do ftell on a popen file descriptor given it is a pipe rather than the full contents of the popen command. Looking for help on how my implementation should be changed (mainly with doing ls -l on the server and sending the contents of it to the client).

My current code is as follows

FILE *fp=popen("ls -l","r");  
      fseek(fp, 0L, SEEK_END);
      long numbytes = ftell(fp);
      fseek(fp, 0L, SEEK_SET);    
      char tmp[SO_SNDBUF];
      sprintf(tmp, "%d", numbytes); 
      n = sendto(sockfd, tmp, strlen(tmp), 0, (struct sockaddr *) &clientaddr, clientlen); //send ls file size
      if (n < 0) 
        error("ERROR in sendto");  
      if(numbytes<SO_SNDBUF)
      {
        bzero(buf, SO_SNDBUF);
        fread(buf, sizeof(char), numbytes, fp);
        printf("BYTES-----%ld\nBUFFER-%s\n",numbytes,buf);
        n = sendto(sockfd, buf, numbytes, 0, (struct sockaddr *) &clientaddr, clientlen);
        if (n < 0) 
          error("ERROR in sendto");
      }
      else
      {
        //outgoing file is larger than buffer size
        long totalSent = 0;
        while(totalSent<numbytes)
        {
          bzero(buf, SO_SNDBUF);
          if((numbytes-totalSent)<SO_SNDBUF)
          {
            fread(buf, sizeof(char), numbytes-totalSent, fp);
            n = sendto(sockfd, buf, numbytes-totalSent, 0, (struct sockaddr *) &clientaddr, clientlen); //send ls contents
            if (n < 0) 
              error("ERROR in sendto");
          }
          else
          {
            fread(buf, sizeof(char), SO_SNDBUF, fp);
            n = sendto(sockfd, buf, SO_SNDBUF, 0, (struct sockaddr *) &clientaddr, clientlen); //send ls contents
            if (n < 0) 
              error("ERROR in sendto");
          }
          totalSent =n;
        }
      }
      pclose(fp);   

The main portion of code that would need modifying is: To correctly get how many bytes ls -l is returning

FILE *fp=popen("ls -l","r");  
      fseek(fp, 0L, SEEK_END);
      long numbytes = ftell(fp);
      fseek(fp, 0L, SEEK_SET);    
      char tmp[SO_SNDBUF];
      sprintf(tmp, "%d", numbytes); 

CodePudding user response:

How about:

system("ls -l > ls.txt");
FILE *fp = fopen("ls.txt", "r");
//...

If it is not too much to create a temporary file. The advantage is, that you have your content ready (mainly the size).

The other solution would be (as suggested) to read from popen line by line into an array of strings and calculating the total amount of bytes while doing so. The disadvantage here is memory allocation (but we read it into memory anyway).

  • Related