Reputation: 1
I'm new in programming, especially in unix programming, and for my specific task I use two pipes for reading and writing from/to forked process with shell executing on it.
There is a program I need to communicate with but it hasn't got an API, so I send commands to shell and then here is a problem
When the process gets command and the command executes, I trying to get result, and there it is, but there is no EOF and fgets is never ending (not while cycle!)
while(fgets(buffer, sizeof(buffer), readPipe)) {
result += buffer;
}
When the last line printed, next what is in buffer looks like this. fgets
Because after command execution it jumps to new empty line.
Can you please help me, how to avoid kludges like && buffer[0]!='\n'
, maybe use somewhat instead fgets, or the way to understand fgets got stack, or maybe you think like all described solution is kludge...
Would appreciate an answer anyway
Class methods
CommandExecutor::CommandExecutor() {
int writePipeFd[2];
int readPipeFd[2];
if(pipe(writePipeFd) || pipe(readPipeFd)) throw std::runtime_error("create pipe: failed!");
processID = fork();
if (processID == -1) throw std::runtime_error("failed!");
else if(processID == 0) {
if (dup2(readPipeFd[1], STDOUT_FILENO) < 0) throw std::runtime_error("dup to stdout: failed!");
if (dup2(writePipeFd[0], STDIN_FILENO) < 0) throw std::runtime_error("dup to stdout: failed!");
close(writePipeFd[0]);
close(writePipeFd[1]);
close(readPipeFd[0]);
close(readPipeFd[1]);
execlp("/bin/sh", "sh", nullptr);
perror("error occured when exec!");
exit(1);
} else {
close(readPipeFd[1]);
close(writePipeFd[0]);
writePipe = fdopen(writePipeFd[1], "w");
readPipe = fdopen(readPipeFd[0], "r");
if (!writePipe || !readPipe) throw std::runtime_error("open read/write pipe: failed!");
}
}
CommandExecutor::~CommandExecutor() {
if (writePipe) fclose(writePipe);
if (readPipe) fclose(readPipe);
if (processID > 0) {
int status;
waitpid(processID, &status, 0);
if (WIFEXITED(status)) std::cerr << "child process exited whith code : " << WEXITSTATUS(status) << std::endl;
else if (WIFSIGNALED(status)) std::cerr << "child process terminated whith signal : " << WTERMSIG(status) << std::endl;
processID = 0;
}
}
std::string CommandExecutor::exec(const std::string command){
if ((fputs(command.c_str(), writePipe) == EOF) || (std::fflush(writePipe) == EOF))
throw std::runtime_error("executor: fail on command write");
std::string result;
char buffer[128];
while(fgets(buffer, sizeof(buffer), readPipe) && buffer[0]!='\n') {
result += buffer;
}
return result;
}
Upvotes: -1
Views: 78