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).