How can I run an external program from C and parse its output?

CExternal Process

C Problem Overview


I've got a utility that outputs a list of files required by a game. How can I run that utility within a C program and grab its output so I can act on it within the same program?

UPDATE: Good call on the lack of information. The utility spits out a series of strings, and this is supposed to be portable across Mac/Windows/Linux. Please note, I'm looking for a programmatic way to execute the utility and retain its output (which goes to stdout).

C Solutions


Solution 1 - C

As others have pointed out, popen() is the most standard way. And since no answer provided an example using this method, here it goes:

#include <stdio.h>

#define BUFSIZE 128

int parse_output(void) {
	char *cmd = "ls -l";	
	
	char buf[BUFSIZE];
	FILE *fp;

	if ((fp = popen(cmd, "r")) == NULL)	{
		printf("Error opening pipe!\n");
		return -1;
	}

	while (fgets(buf, BUFSIZE, fp) != NULL)	{
		// Do whatever you want here...
		printf("OUTPUT: %s", buf);
	}

	if (pclose(fp)) {
		printf("Command not found or exited with error status\n");
		return -1;
	}

	return 0;
}

Sample output:

OUTPUT: total 16
OUTPUT: -rwxr-xr-x 1 14077 14077 8832 Oct 19 04:32 a.out
OUTPUT: -rw-r--r-- 1 14077 14077 1549 Oct 19 04:32 main.c

Solution 2 - C

For simple problems in Unix-ish environments try popen().

From the man page:

>The popen() function opens a process by creating a pipe, forking and invoking the shell.

If you use the read mode this is exactly what you asked for. I don't know if it is implemented in Windows.

For more complicated problems you want to look up inter-process communication.

Solution 3 - C

popen is supported on Windows, see here:

http://msdn.microsoft.com/en-us/library/96ayss4b.aspx

If you want it to be cross-platform, popen is the way to go.

Solution 4 - C

Well, assuming you're on a command line in a windows environment, you can use pipes or command line redirects. For instance,

commandThatOutputs.exe > someFileToStoreResults.txt

or

commandThatOutputs.exe | yourProgramToProcessInput.exe

Within your program, you could use the C standard input functions to read the other programs output (scanf, etc.): http://irc.essex.ac.uk/www.iota-six.co.uk/c/c1_standard_input_and_output.asp . You could also use the file example and use fscanf. This should also work in Unix/Linux.

This is a very generic question, you may want to include more details, like what type of output it is (just text, or a binary file?) and how you want to process it.

Edit: Hooray clarification!

Redirecting STDOUT looks to be troublesome, I've had to do it in .NET, and it gave me all sorts of headaches. It looks like the proper C way is to spawn a child process, get a file pointer, and all of a sudden my head hurts.

So heres a hack that uses temporary files. It's simple, but it should work. This will work well if speed isn't an issue (hitting the disk is slow), or if it's throw-away. If you're building an enterprise program, looking into the STDOUT redirection is probably best, using what other people recommended.

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

int main(int argc, char* argv[])
{
    FILE * fptr;                    // file holder
    char c;                         // char buffer

    
    system("dir >> temp.txt");      // call dir and put it's contents in a temp using redirects.
    fptr = fopen("temp.txt", "r");  // open said file for reading.
                                    // oh, and check for fptr being NULL.
    while(1){
        c = fgetc(fptr);
        if(c!= EOF)
            printf("%c", c);        // do what you need to.
        else
            break;                  // exit when you hit the end of the file.
    }
    fclose(fptr);                   // don't call this is fptr is NULL.  
    remove("temp.txt");             // clean up

    getchar();                      // stop so I can see if it worked.
}

Make sure to check your file permissions: right now this will simply throw the file in the same directory as an exe. You might want to look into using /tmp in nix, or C:\Users\username\Local Settings\Temp in Vista, or C:\Documents and Settings\username\Local Settings\Temp in 2K/XP. I think the /tmp will work in OSX, but I've never used one.

Solution 5 - C

In Linux and OS X, popen() really is your best bet, as dmckee pointed out, since both OSs support that call. In Windows, this should help: http://msdn.microsoft.com/en-us/library/ms682499.aspx

Solution 6 - C

MSDN documentation says If used in a Windows program, the _popen function returns an invalid file pointer that causes the program to stop responding indefinitely. _popen works properly in a console application. To create a Windows application that redirects input and output, see Creating a Child Process with Redirected Input and Output in the Windows SDK.

Solution 7 - C

You can use system() as in:

system("ls song > song.txt");

where ls is the command name for listing the contents of the folder song and song is a folder in the current directory. Resulting file song.txt will be created in the current directory.

Solution 8 - C

//execute external process and read exactly binary or text output
//can read image from Zip file for example
string run(const char* cmd){
    FILE* pipe = popen(cmd, "r");
    if (!pipe) return "ERROR";
    char buffer[262144];
    string data;
    string result;
    int dist=0;
    int size;
    //TIME_START
    while(!feof(pipe)) {
        size=(int)fread(buffer,1,262144, pipe); //cout<<buffer<<" size="<<size<<endl;
        data.resize(data.size()+size);
        memcpy(&data[dist],buffer,size);
        dist+=size;
    }
    //TIME_PRINT_
    pclose(pipe);
    return data;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJosh MatthewsView Question on Stackoverflow
Solution 1 - CMestreLionView Answer on Stackoverflow
Solution 2 - Cdmckee --- ex-moderator kittenView Answer on Stackoverflow
Solution 3 - CAdam PierceView Answer on Stackoverflow
Solution 4 - CDavid J. SokolView Answer on Stackoverflow
Solution 5 - CArktronicView Answer on Stackoverflow
Solution 6 - CAngus ConnellView Answer on Stackoverflow
Solution 7 - CPrabhat Kumar SinghView Answer on Stackoverflow
Solution 8 - Cdharmabook.ruView Answer on Stackoverflow