Grabbing output from exec

51,997

Solution 1

You have to create a pipe from the parent process to the child, using pipe(). Then you must redirect standard ouput (STDOUT_FILENO) and error output (STDERR_FILENO) using dup or dup2 to the pipe, and in the parent process, read from the pipe. It should work.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define die(e) do { fprintf(stderr, "%s\n", e); exit(EXIT_FAILURE); } while (0);

int main() {
  int link[2];
  pid_t pid;
  char foo[4096];

  if (pipe(link)==-1)
    die("pipe");

  if ((pid = fork()) == -1)
    die("fork");

  if(pid == 0) {

    dup2 (link[1], STDOUT_FILENO);
    close(link[0]);
    close(link[1]);
    execl("/bin/ls", "ls", "-1", (char *)0);
    die("execl");

  } else {

    close(link[1]);
    int nbytes = read(link[0], foo, sizeof(foo));
    printf("Output: (%.*s)\n", nbytes, foo);
    wait(NULL);

  }
  return 0;
}

Solution 2

Open a pipe, and change stdout to match that pipe.

 #include <sys/types.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>

 int pipes[2];

 pipe(pipes); // Create the pipes

 dup2(pipes[1],1); // Set the pipe up to standard output

After that, anything which goes to stdout,(such as through printf), comes out pipe[0].

FILE *input = fdopen(pipes[0],"r");

Now you can read the output like a normal file descriptor. For more details, look at this

Solution 3

Thanks Jonathan Leffler, and i optimize the above code for it can't read all response for one time.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>

#define die(e) do { fprintf(stderr, "%s\n", e); exit(EXIT_FAILURE); } while (0);

int main() {
  int link[2];
  pid_t pid;
  char foo[4096 + 1];
  memset(foo, 0, 4096);

  if (pipe(link)==-1)
    die("pipe");

   if ((pid = fork()) == -1)
    die("fork");

  if(pid == 0) {

    dup2 (link[1], STDOUT_FILENO);
    close(link[0]);
    close(link[1]);
    execl("/bin/ls", "ls", "-1", (char *)0);
    die("execl");
  } else {
    close(link[1]);
    int nbytes = 0;
    std::string totalStr;
    while(0 != (nbytes = read(link[0], foo, sizeof(foo)))) {
        totalStr = totalStr + foo;
        printf("Output: (%.*s)\n", nbytes, foo);
        memset(foo, 0, 4096);
    }
    wait(NULL);
  }
  return 0;
}
Share:
51,997
TrewTzu
Author by

TrewTzu

Updated on July 16, 2022

Comments

  • TrewTzu
    TrewTzu almost 2 years

    I'm trying to write a C program that grabs command output and then i'll be passing that to another program.

    I'm having an issue, I cant work out how to get the command output and store it. Below is a sample of what I have

    if(fork() == 0){
       execl("/bin/ls", "ls", "-1", (char *)0);
       /* do something with the output here */
    }
    else{
        //*other stuff goes here*
    }
    

    so basically im wondering if there is any way i can get the output from the "execl" and pass it to some thing else (e.g. via storing it in some kind of buffer).

    Suggestions would be great.