How do I execute a command and get the output of the command within C++ using POSIX?

前端 未结 11 1130
我在风中等你
我在风中等你 2020-11-21 05:39

I am looking for a way to get the output of a command when it is run from within a C++ program. I have looked at using the system() function, but that will jus

11条回答
  •  迷失自我
    2020-11-21 05:59

    I'd use popen() (++waqas).

    But sometimes you need reading and writing...

    It seems like nobody does things the hard way any more.

    (Assuming a Unix/Linux/Mac environment, or perhaps Windows with a POSIX compatibility layer...)

    enum PIPE_FILE_DESCRIPTERS
    {
      READ_FD  = 0,
      WRITE_FD = 1
    };
    
    enum CONSTANTS
    {
      BUFFER_SIZE = 100
    };
    
    int
    main()
    {
      int       parentToChild[2];
      int       childToParent[2];
      pid_t     pid;
      string    dataReadFromChild;
      char      buffer[BUFFER_SIZE + 1];
      ssize_t   readResult;
      int       status;
    
      ASSERT_IS(0, pipe(parentToChild));
      ASSERT_IS(0, pipe(childToParent));
    
      switch (pid = fork())
      {
        case -1:
          FAIL("Fork failed");
          exit(-1);
    
        case 0: /* Child */
          ASSERT_NOT(-1, dup2(parentToChild[READ_FD], STDIN_FILENO));
          ASSERT_NOT(-1, dup2(childToParent[WRITE_FD], STDOUT_FILENO));
          ASSERT_NOT(-1, dup2(childToParent[WRITE_FD], STDERR_FILENO));
          ASSERT_IS(0, close(parentToChild [WRITE_FD]));
          ASSERT_IS(0, close(childToParent [READ_FD]));
    
          /*     file, arg0, arg1,  arg2 */
          execlp("ls", "ls", "-al", "--color");
    
          FAIL("This line should never be reached!!!");
          exit(-1);
    
        default: /* Parent */
          cout << "Child " << pid << " process running..." << endl;
    
          ASSERT_IS(0, close(parentToChild [READ_FD]));
          ASSERT_IS(0, close(childToParent [WRITE_FD]));
    
          while (true)
          {
            switch (readResult = read(childToParent[READ_FD],
                                      buffer, BUFFER_SIZE))
            {
              case 0: /* End-of-File, or non-blocking read. */
                cout << "End of file reached..."         << endl
                     << "Data received was ("
                     << dataReadFromChild.size() << "): " << endl
                     << dataReadFromChild                << endl;
    
                ASSERT_IS(pid, waitpid(pid, & status, 0));
    
                cout << endl
                     << "Child exit staus is:  " << WEXITSTATUS(status) << endl
                     << endl;
    
                exit(0);
    
    
              case -1:
                if ((errno == EINTR) || (errno == EAGAIN))
                {
                  errno = 0;
                  break;
                }
                else
                {
                  FAIL("read() failed");
                  exit(-1);
                }
    
              default:
                dataReadFromChild . append(buffer, readResult);
                break;
            }
          } /* while (true) */
      } /* switch (pid = fork())*/
    }
    

    You also might want to play around with select() and non-blocking reads.

    fd_set          readfds;
    struct timeval  timeout;
    
    timeout.tv_sec  = 0;    /* Seconds */
    timeout.tv_usec = 1000; /* Microseconds */
    
    FD_ZERO(&readfds);
    FD_SET(childToParent[READ_FD], &readfds);
    
    switch (select (1 + childToParent[READ_FD], &readfds, (fd_set*)NULL, (fd_set*)NULL, & timeout))
    {
      case 0: /* Timeout expired */
        break;
    
      case -1:
        if ((errno == EINTR) || (errno == EAGAIN))
        {
          errno = 0;
          break;
        }
        else
        {
          FAIL("Select() Failed");
          exit(-1);
        }
    
      case 1:  /* We have input */
        readResult = read(childToParent[READ_FD], buffer, BUFFER_SIZE);
        // However you want to handle it...
        break;
    
      default:
        FAIL("How did we see input on more than one file descriptor?");
        exit(-1);
    }
    

提交回复
热议问题