popen関数および出力エラー情報
#include <cstdio> // popen, printf, snprintf
#include <sys/wait.h> // WIFEXITED() WEXITSTATUS()
#include <errno.h> // extern int errno;
#include <string>
#include <cstring>
#include <cstdlib>
#include <cassert>
#define MAX_SIZE (1024)
bool exec_cmd(const char* command, std::string& errmsg)
{
assert(command);
char buffer[MAX_SIZE] = {'\0'};
std::string final_msg;
// the exit status of the command.
int rc = 0;
// I/O redirection.
char cmd[MAX_SIZE] = {'\0'};
snprintf(cmd, sizeof(cmd), "%s 2>&1", command);
FILE *fp = popen(cmd, "r");
if(NULL == fp)
{ // if fork(2) or pipe(2) calls fail, or cannot callocate memory.
// it does not set errno if memory allocation fails.
// if the underlying fork(2) or pipe(2) fails, errno is set
// appropriately.
// if the type arguments is invalid, and this condition is detected,
// errno is set to EINVAL.
snprintf(buffer, sizeof(buffer),
"popen failed. %s, with errno %d.
", strerror(errno), errno);
final_msg = buffer;
errmsg = final_msg.c_str();
return false;
}
char result[MAX_SIZE] = {'\0'};
std::string child_result;
while(fgets(result, sizeof(result), fp) != NULL)
{
// remove the '
' to make output more beautiful
if('
' == result[strlen(result)-1])
{
result[strlen(result)-1] = '\0';
}
snprintf(buffer, sizeof(buffer),
"[%s]: %s \r
", command, result);
child_result += buffer;
}
// waits for the associated process to terminate and returns
// the exit status of the command as returned by wait4(2).
rc = pclose(fp);
if(-1 == rc)
{ // return -1 if wait4(2) returns an error, or some other error is detected.
// if pclose cannot obtain the child status, errno is set to ECHILD.
final_msg += child_result;
if(ECHILD==errno) {
final_msg += "pclose cannot obtain the child status.
";
}
else {
snprintf(buffer, sizeof(buffer),
"Close file failed. %s, with errno %d.
", strerror(errno), errno);
final_msg += buffer;
}
errmsg = final_msg.c_str();
return false;
}
// TODO: warning 'file descriptor leaked
#if 0
if(WIFEXITED(rc)!=0) {
printf("maybe cause file descriptor leaked.
");
}
#endif
// child process exit status.
int status_child = WEXITSTATUS(rc);
// the success message is here.
final_msg += child_result;
snprintf(buffer, sizeof(buffer),
"[%s]: command exit status [%d] and child process exit status [%d].\r
",
command, rc, status_child);
final_msg += buffer;
errmsg = final_msg.c_str();
if(status_child==0) {
// child process exits SUCCESS.
return true;
}
else {
// child process exits FAILED.
return false;
}
}
bool getCmdPath(const char* cmd, String& path)
{
if (cmd == NULL || strlen(cmd) == 0)
return false;
string command = "which ";
command += cmd;
FILE* pf = popen(command.c_str(), "r");
if (pf) {
char buf[100];
memset(buf, '\0', sizeof(buf));
fgets(buf, sizeof(buf), pf);
pclose(pf);
//return the path
path = buf;
return true;
} else {
return false;
}
}
popen関数を呼び出し、shellコマンドを実行し、エラー情報を出力します.