mspoerr
mspoerr

Reputation: 2710

C++ system() function — How to collect the output of the issued command?

I'm running some commands with the C++ system() function:

int system ( const char * command );

How can I collect the standard output from the issued commands?

To be specific, I want to collect the output of the issued command (for example, the directory listing output from issuing the dir command).

Upvotes: 7

Views: 29584

Answers (8)

Employed Russian
Employed Russian

Reputation: 213476

Are you looking for returned value (as in "exit status") of the executed command, or for its output (as in "what did it print")?

If the latter, use popen() and pclose() instead.

If the former, look at the return value from system() (and use the documentation for waitpid() to interpret it).

Upvotes: 16

larryy
larryy

Reputation: 678

Inspired by bmorin's attempt, but working and tested, this snippet will take a char* command and return a char* containing the results of executing that command...

// Calling function must free the returned result.
char* exec(const char* command) {
  FILE* fp;
  char* line = NULL;
  // Following initialization is equivalent to char* result = ""; and just
  // initializes result to an empty string, only it works with
  // -Werror=write-strings and is so much less clear.
  char* result = (char*) calloc(1, 1);
  size_t len = 0;

  fflush(NULL);
  fp = popen(command, "r");
  if (fp == NULL) {
    printf("Cannot execute command:\n%s\n", command);
    return NULL;
  }

  while(getline(&line, &len, fp) != -1) {
    // +1 below to allow room for null terminator.
    result = (char*) realloc(result, strlen(result) + strlen(line) + 1);
    // +1 below so we copy the final null terminator.
    strncpy(result + strlen(result), line, strlen(line) + 1);
    free(line);
    line = NULL;
  }

  fflush(fp);
  if (pclose(fp) != 0) {
    perror("Cannot close stream.\n");
  }
  return result;
}

I looked into just editing bmorin's code, but would have had to change most lines, so a separate answer seemed more appropriate. Apologies if not. (Amongst other problems, bmorin's code didn't actually accumulate the lines; it printed them to stdout, where I presume they would not be wanted, since system() would have done that; and it returned void in one error path, when the function must return a char*, so the code wouldn't compile. Perhaps most egregious, it freed the result just before returning it.)

Upvotes: 4

bmorin
bmorin

Reputation: 645

Here is a code snippet (in plain C) executing a command with popen and returning its output:

char* exec(const char* command) {
    FILE* fp;
    char* result = NULL;
    size_t len = 0;

    fflush(NULL);
    fp = popen(command, "r");
    if (fp == NULL) {
        printf("Cannot execute command:\n%s\n", command);
        return;
    }

    while(getline(&result, &len, fp) != -1) {
        fputs(result, stdout);
    }

    free(result);
    fflush(fp);
    if (pclose(fp) != 0) {
        perror("Cannot close stream.\n");
    }
    return result;
}

Upvotes: 0

I suggest the popen() functions, as said by other people as well, but this problem is platform specific. the popen() function is available on operating systems that use the POSIX API. I am not sure if this command would work on other APIs like WIN32

Upvotes: 0

Alex Martelli
Alex Martelli

Reputation: 881595

The return value of system is (ironically) system-dependent, but in POSIX systems (including Linux, etc), it's the same as for wait -- low 8 or 16 bits are the exit status of the child (probably what you mean by "value returned by"), higher bits indicating what kind of signal terminated the child, if any. The URL to the manpage I've given supplies the preprocessor macros you can use to pry apart that return value!

There is no such thing as a "return string" of a program, as you've now clarified in a comment is what you desire; as another answer already mentioned, if you want the text which gets output by the other program, you should use popen instead of system.

Upvotes: 3

Martin v. Löwis
Martin v. Löwis

Reputation: 127447

There are typically two ways for a system program to "return" a value: by writing to stdout, and by returning a status integer at the end of the program. (there are often more ways to return results, eg. by writing to a file or into a database, but I assume those are out of scope here).

For receiving the status code, just check the return value of the system function.

For receiving the output, either redirect it into a file, and read the file afterwards, or use popen.

Upvotes: 3

Jonathan Feinberg
Jonathan Feinberg

Reputation: 45324

system() is declared and defined in libc. You can either read the first link I provided, or do man system at a command prompt in your shell.

Upvotes: 0

phoebus
phoebus

Reputation: 14931

system() returns an int, so just grab it: int rvalue = system(command);

I believe the exact details of what system() will return are system-specific, though.

Upvotes: 8

Related Questions