经验分享: command执行示例

示例,不保证可用性

#include <iostream>
#include <sstream>
#include <cstdarg>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/poll.h>


#define CREATE_PIPE(name) \
FDHolder fdI##name; \
FDHolder fdO##name; \
do { \
    int tmp__pipeFd##name[2] = { -1, -1 }; \
    status = pipe(tmp__pipeFd##name); \
    if (status) \
    { \
        THROW_TEXCEPTIONERRNO("pipe"); \
    } \
    fdI##name = tmp__pipeFd##name[0]; \
    fdO##name = tmp__pipeFd##name[1]; \
} while (false)


#define THROW_TEXCEPTION(exceptionTitle, userData)                  \
    do { throw (TaskMgmt::TException(SUBSYSTEM_NAME,                \
                                     COMPONENT_NAME,                \
                                     (exceptionTitle),              \
                                     __FILE__,                      \
                                     __LINE__,                      \
                                     (userData))); } while (false)

#define THROW_TEXCEPTIONERRNO(functionName)                             \
    do { throw (TaskMgmt::TExceptionErrno(SUBSYSTEM_NAME,               \
                                          COMPONENT_NAME,               \
                                          (functionName),               \
                                          __FILE__,                     \
                                          __LINE__)); } while (false)


void TaskMgmt::ForkAndExecIO(const std::string              &in,
                             std::string                    &out,
                             std::string                    &err,
                             const std::vector<std::string> &cmdargs)
{
    /* There has to be atleast the command */
    assert(cmdargs.size() >= 1);

    const char *command = cmdargs.front().c_str();
    std::vector<const char *> args;
    std::vector<std::string>::const_iterator i =  cmdargs.begin();
    for (++i; i != cmdargs.end(); ++i)
    {
        args.push_back(i->c_str());
    }
    ForkAndExecIO(in,
                  out,
                  err,
                  command,
                  args);
}



void TaskMgmt::ForkAndExecIO(const std::string                  &in,
                             std::string                        &out,
                             std::string                        &err,
                             const char                         *command,
                             const std::vector<const char *>    &args)
{
    assert_pointer(command);

    /* Build argv */
    std::vector<const char *> argv;
    argv.push_back(command);
    for (std::vector<const char *>::const_iterator i = args.begin();
         i != args.end();
         ++i)
    {
        argv.push_back(*i);
    }
    argv.push_back(NULL);

    int status;
    CREATE_PIPE(In);
    CREATE_PIPE(Out);
    CREATE_PIPE(Err);

    /* Fork a new child to execute the command. */
    pid_t pid;
    pid = fork();
    if (pid == 0)
    {
        /* Child */
        close(fdOIn);
        fdOIn = -1;
        close(fdIOut);
        fdIOut = -1;
        close(fdIErr);
        fdIErr = -1;

        /* Map in, out and err */
        dup2(fdIIn,
             STDIN_FILENO);
        close(fdIIn);
        dup2(fdOOut,
             STDOUT_FILENO);
        close(fdOOut);
        dup2(fdOErr,
             STDERR_FILENO);
        close(fdOErr);

        /* Clear signal mask */
        clearSignalMask();

        /* Exec */
        execvp(argv.front(),
               (char* const*)&argv[0]);
        /* Reaching this point indicates an error with execvp */
        std::cerr << "Error with execvp(" << command << "): " <<
                     strerror(errno) << std::endl;
        _exit(EXIT_FAILURE);
    }
    else if (pid > 0)
    {
        /* Parent */
        close(fdIIn);
        fdIIn = -1;
        close(fdOOut);
        fdOOut = -1;
        close(fdOErr);
        fdOErr = -1;

        /* Read out and err and write in until they are closed */
        std::string::const_iterator iIn = in.begin();
        while ((fdOIn >= 0) ||
               (fdIOut >= 0) ||
               (fdIErr >= 0))
        {
            struct pollfd pollfd[3] = { };
            unsigned int nfds = 0;
            if (fdOIn >= 0)
            {
                pollfd[nfds].fd = fdOIn;
                pollfd[nfds].events = POLLOUT;
                pollfd[nfds].revents = 0;
                ++nfds;
            }
            if (fdIOut >= 0)
            {
                pollfd[nfds].fd = fdIOut;
                pollfd[nfds].events = POLLIN;
                pollfd[nfds].revents = 0;
                ++nfds;
            }
            if (fdIErr >= 0)
            {
                pollfd[nfds].fd = fdIErr;
                pollfd[nfds].events = POLLIN;
                pollfd[nfds].revents = 0;
                ++nfds;
            }
            assert(nfds > 0);
            do
            {
                status = poll(pollfd,
                              nfds,
                              -1);
            }
            while ((status < 0) &&
                   (errno == EINTR));
            if (status < 0)
            {
                /* Something went wrong */
                THROW_TEXCEPTIONERRNO("poll");
            }
            nfds = 0;
            if (fdOIn >= 0)
            {
                assert(pollfd[nfds].fd == fdOIn);
                if (pollfd[nfds].revents & POLLOUT)
                {
                    ssize_t size;
                    size_t toWrite = in.end() - iIn;
                    do
                    {
                        size = write(fdOIn,
                                     &(*iIn),
                                     toWrite);
                    }
                    while ((size < 0) &&
                           (errno == EINTR));
                    if (size < 0)
                    {
                        /* Something went wrong */
                        THROW_TEXCEPTIONERRNO("read");
                    }
                    else if (static_cast<size_t>(size) < toWrite)
                    {
                        iIn += static_cast<size_t>(size);
                    }
                    else
                    {
                        /* All done */
                        close(fdOIn);
                        fdOIn = -1;
                    }
                }
                else if (pollfd[nfds].revents & (POLLERR | POLLHUP))
                {
                    close(fdOIn);
                    fdOIn = -1;
                }
                ++nfds;
            }
            if (fdIOut >= 0)
            {
                assert(pollfd[nfds].fd == fdIOut);
                if (pollfd[nfds].revents & POLLIN)
                {
                    ReadInto(fdIOut,
                             out);
                }
                else if (pollfd[nfds].revents & (POLLERR | POLLHUP))
                {
                    close(fdIOut);
                    fdIOut = -1;
                }
                ++nfds;
            }
            if (fdIErr >= 0)
            {
                assert(pollfd[nfds].fd == fdIErr);
                if (pollfd[nfds].revents & POLLIN)
                {
                    ReadInto(fdIErr,
                             err);
                }
                else if (pollfd[nfds].revents & (POLLERR | POLLHUP))
                {
                    close(fdIErr);
                    fdIErr = -1;
                }
                ++nfds;
            }
        }

        /* Wait for the child to die */
        do
        {
            pid = waitpid(pid,
                          &status,
                          0);
        }
        while ((pid < 0) &&
               (errno == EINTR));
        if (pid < 0)
        {
            /* Something went wrong */
            THROW_TEXCEPTIONERRNO("waitpid");
        }

        /* Check how the child died */
        if (WIFEXITED(status))
        {
            if (WEXITSTATUS(status) != EXIT_SUCCESS)
            {
                /* Abnormal exit */
                THROW_TEXCEPTION(command,
                                 err.c_str());
            }
        }
        else if (WIFSIGNALED(status))
        {
            /* Terminated with signal */
            std::ostringstream s;
            s << command << " was killed with signal " <<
                 WTERMSIG(status);
            THROW_TEXCEPTION(command,
                             s.str().c_str());
        }
        else
        {
            /* Unknown reason */
            THROW_TEXCEPTION(command,
                             "unknown termination");
        }
    }
    else
    {
        /* Something went wrong */
        THROW_TEXCEPTIONERRNO("fork");
    }
}

void TaskMgmt::clearSignalMask()
{
    int status;
    sigset_t sigSet;
    sigemptyset(&sigSet);
    status = pthread_sigmask(SIG_SETMASK,
                             &sigSet,
                             NULL);
    if (status)
    {
        THROW_TEXCEPTIONERRNO("pthread_sigmask");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值