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.\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;
    }
}

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 命令,并输出错误信息。


阅读更多
上一篇popen(3) - Linux man page
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭