返回顶部

收藏

popen返回子进程的成功状态及错误信息

更多

platform: linux c/c++

call: popen

function:

return the exit status and output error message if need.

#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.\\n", 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 '\\n' to make output more beautiful
        if('\\n' == result[strlen(result)-1])
        {
            result[strlen(result)-1] = '\\0';
        }

        snprintf(buffer, sizeof(buffer),
                "[%s]: %s \\r\\n", 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.\\n";
        }
        else {
            snprintf(buffer, sizeof(buffer),
                    "Close file failed. %s, with errno %d.\\n", 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.\\n");
    }
#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\\n",
            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;
    }
}
//该片段来自于http://outofmemory.cn

标签:c++,系统

收藏

0人收藏

支持

0

反对

0

发表评论