In a TCP
client-server
implementation, I set the client to send a shell command to be ran by server and then server send back the response of the OS to the client.
using namespace std;
string run_shell()
{
// return buffer
char buffer[1024];
memset(buffer, 0, 1024);
//fork child
int pid = fork();
//Child
if(!pid)
{
char* args[] = {"ls", "-l", NULL};
int status = execvp("ls", args);
if(status < 0)
{
cout << "Error: executing shell command failed!" << endl;
return "";
}
int out_pipe[2];
// save stdout
int saved_stdout = dup(STDOUT_FILENO);
pipe(out_pipe);
// redirect stdout to the pipe
dup2(out_pipe[1], STDOUT_FILENO);
close(out_pipe[1]);
// read from pipe into buffer
read(out_pipe[0], buffer, 1024);
}
//Parent
else
{
}
return buffer;
}
output:
in server's terminal:
Server received a message
ls -l
-rw-r--r-- 1 XXXX XXXX 4865 Jul 15 12:27 Client.cpp
-rw-r--r-- 1 XXXX XXXX 281 Jul 15 16:40 client_main.cpp
-rw-r--r-- 1 XXXX XXXX 12008 Jul 15 17:06 client_main.o
Server sent a message
in client's terminal:
Client sent a message
ServerMessage: -> `�7��
I would want to get the STDOUT of the executed command by server available as a string
to the client. From what I have done, I always get garbage in client side.
Can someone help me address that? There should be some part of redirection in parent branch, but i cannot code it properly.
Solution:
string run_shell()
{
// create pipe lines between parent and child processes
int pipe_lines[2];
// create the return buffer
vector<char> return_buffer;
// define the pipes
if(pipe(pipe_lines) == -1)
{
cout << "Error: creating pipe_line in server failed!" << endl;
return "";
}
//fork child
int pid = fork();
//Child
if(!pid)
{
// command
char* args[] = {"ls", "-l", NULL};
// copy STDOUT and STDERR of child process to be copied into write pipe
dup2 (pipe_lines[1], STDOUT_FILENO);
dup2 (pipe_lines[1], STDERR_FILENO);
// chile does not read
close(pipe_lines[0]);
// child does not write
close(pipe_lines[1]);
int status = execvp("ls", args);
if(!status)
{
cout << "Error: executing shell command failed!" << endl;
return "";
}
// send the 'exec' output into the pipe
fprintf(stderr, "%s\n", execvp);
// exit child process
exit(EXIT_FAILURE);
}
//Parent
else
{
// parent does not write
close(pipe_lines[1]);
// how many bytes have been read
int read_bytes;
// a temp char buffer
char tmp_ch = 0;
// read until there is no more character left in read pipe
while((read_bytes = read(pipe_lines[0], &tmp_ch, 1)) == 1)
{
return_buffer.push_back(tmp_ch);
tmp_ch = 0;
}
// block the parent process until any of its children has finished
wait(NULL);
}
return string(return_buffer.data());
}