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コマンドを実行し、エラー情報を出力します.