I have a client-server application where a server listens on one machine on a particular port, and a client can connect to that machine via it’s IP address and port.
The client sends data to the server with the command it wants to execute, for instance, cat /etc/passwd
. That server uses popen
to execute the command and store the results in a buffer, like so:
/* Receive commands from client */
char command_in[256];
char command_out[2048];
char command_out_send[2048];
ssize_t recv_data = recv(client_s, command_in, sizeof(command_in), 0);
// <SNIP>
/* Execute system command and obtain output */
FILE *fp = popen(command_in, "r");
if (fp == NULL) {
close(client_s);
close(s);
return 1;
} else {
while(fgets(command_out, sizeof(command_out) - 1, fp) != NULL) {
/* Capture all output and save it to buffer */
strcat(command_out_send, command_out);
}
}
/* Send executed command to client*/
if (send(client_s, command_out_send, sizeof(command_out_send), 0) == -1) {
close(client_s);
close(s);
return 1;
}
/* Cleanup */
memset(command_out_send, 0, sizeof(char));
pclose(fp);
The issue is the fact that it creates a buffer to hold the contents.
The client is as follows.
while (1) {
char command_in[256];
char command_out[2048];
printf("~ ");
fgets(command_in, 256, stdin);
/* Send command to server */
if (send(s, command_in, sizeof(command_in), 0) == -1) {
close(s);
return 1;
}
/* Receive response from server */
ssize_t recv_data = recv(s, command_out, sizeof(command_out), 0);
if (recv_data == -1) {
close(s);
return 1;
}
/* Print out command results */
fputs(command_out, stdout);
}
Currently, the client retrieves the data and prints the output. Instead, I want to send in chunks while there is data to send on the server side, and for that client to wait until all that data is sent rather than creating a buffer to hold the entire contents of the command..
How can I do this?