views:

1757

answers:

5

I just want to know which is the best way to execute an external command in C++ and how can I grab the output if there is any?

Edit: I Guess I had to tell that I'm a newbie here in this world, so I think I'm gonna need a working example. For example I want to execute a command like:

ls -la

how do I do that?

+10  A: 

Use the popen function.

Example (not complete, no error handling):

FILE* file = popen("ls", "r");
// use fscanf to read:
char buffer[100];
fscanf(file, "%s", buffer);
pclose(file);
Mehrdad Afshari
that also correct.. but can't accept two answers.. ty
Lipis
A: 

use system("ls -la") function

suresh
I don't know why this was downvoted...
Dan Fego
It doesn't answer the question. There's no way to get the output from a system() call.
greyfade
it works man.. i have used it several time in devc++ IDE....
suresh
+1  A: 
FILE* cmd = NULL;
char buf[256];

cmd = popen("ls -la", "r");
// fread() into buf
pclose(cmd);
greyfade
+9  A: 

An example:

#include <stdio.h>

int main() {
    FILE * f = popen( "ls -al", "r" );
    if ( f == 0 ) {
        fprintf( stderr, "Could not execute\n" );
        return 1;
    }
    const int BUFSIZE = 1000;
    char buf[ BUFSIZE ];
    while( fgets( buf, BUFSIZE,  f ) ) {
        fprintf( stdout, "%s", buf  );
    }
    pclose( f );
}
anon
forgot return 0 at the end of main. and use sizeof( buff ) instead 1000 in fgets :)
bb
C++ does not require a return at end of main.
anon
True, but it's nice to have the return, so that it's obvious what's going to come out of the program.
Michael Kohne
it worked perfectly with the ls.. but when I'm trying the command "wget -O image.jpg http://admin:[email protected]/image.jpg" it works ok too.. but even if i remove the fprintf command, I'm still getting the output on my screen..! Any help on that? (No output if I'm doing that with ls)
Lipis
wget writes its status messages to stderr - run it with the --quiet option
anon
hmm... But what if I want to catch that as well...? Without the --quite option, but letting be decide whenever I want to print it out or not..
Lipis
FILE * f = popen( "wget www.google.com 2> // this assumes a bash shell
anon
camh
@Dave Jarvis Please do not feel free to "improve" my answers by adding unnecessary code.
anon
+6  A: 

popen definitely does the job that you're looking for, but it has a few drawbacks:

  • It invokes a shell on the command you're executing (which means that you need to untaint any user provided command strings)
  • It only works in one direction, either you can provide input to the subprocess or you can read its output.

If you want invoke a subprocess and provide input and capture output then you'll have to do something like this:

int Input[2], Output[2];

pipe( Input );
pipe( Output );

if( fork() )
{
    // We're in the parent here.
    // Close the reading end of the input pipe.
    close( Input[ 0 ] );
    // Close the writing end of the output pipe
    close( Output[ 1 ] );

    // Here we can interact with the subprocess.  Write to the subprocesses stdin via Input[ 1 ], and read from the subprocesses stdout via Output[ 0 ].
    ...
}
else
{    // We're in the child here.
     close( Input[ 1 ] );
     dup2( Input[ 0 ], STDIN_FILENO );
     close( Output[ 0 ] );
     dup2( Output[ 1 ], STDOUT_FILENO );

     execlp( "ls", "-la", NULL );
}

Of course, you can replace the execlp with any of the other exec functions as appropriate.

Peter Kovacs