Search code examples
c++terminaltermios

how to redirect terminal command output via execve to std::string in c++


I want to redirect the output from executing a command in the terminal to a string in c++. I dont want the command output to appear at all in the terminal because i am using an ncurses display. is there any way i can do this?

i am using a Linux terminal.

I have considered redirecting to a temp file then reading the contents of a file. But i would much prefer not to introduce tmp files. to clarify, i want to be able to do the following:

  1. echo "hello world" via execve
  2. redirect the output from the terminal to an std::string, so that it does not in fact show in the terminal at this stage.
  3. use printw function in ncurses to print the command output to an ncurses window

i am currently looking for possible implementations using features from termios.h and possibly dup2

my code looks like this:

std::string containerForOutput;


// some method which redicects execve into containerForOutput here

char cmd[100];
strcpy(cmd, "/usr/bin/");
strcat(cmd, argv[0]);

// execute the command using execve, but
// will not output to terminal after command is given
// and will instead store it in the string containerForOutput
int result = execve(cmd, argv, environ);
perror("Fallback Shell");

Using a stringstream did not work.


Solution

  • A good alternative is to use the pstream header file instead of execve, which creates a child process.

    thanks to this post:

    https://stackoverflow.com/a/10702464/5133238

    Instead of using exec i capture the output and print it using the ncurses printw method:

      // run a process and create a streambuf that reads its stdout and stderr
      redi::ipstream proc("echo hello", redi::pstreams::pstdout | redi::pstreams::pstderr);
      std::string line;
      // read child's stdout
      while (std::getline(proc.out(), line)) {
       // the output is captured line by line here
       // so that i can do what i want with it
        printw(line.c_str());
        printw("\n");
      }
    
      // if reading stdout stopped at EOF then reset the state:
      if (proc.eof() && proc.fail()) {
        proc.clear();
      }
      // read child's stderr
      while (std::getline(proc.err(), line)) {
       // error message is captured line by line here
       // so that i can do what i want with it.
        printw(line.c_str());
        printw("\n");
      }
    

    pstreams here: http://pstreams.sourceforge.net/