66

I want to execute another program within C code. For example, I want to execute a command

./foo 1 2 3

foo is the program which exists in the same folder, and 1 2 3 are arguments. foo program creates a file which will be used in my code.

How do I do this?

2
  • 1
    Why does this question ask for C code and is tagged with C++? Commented Mar 9, 2011 at 16:19
  • 1
    Because any solution would work in C++ Commented Oct 30, 2019 at 1:27

7 Answers 7

68

For a simple way, use system():

#include <stdlib.h>
...
int status = system("./foo 1 2 3");

system() will wait for foo to complete execution, then return a status variable which you can use to check e.g. exitcode (the command's exitcode gets multiplied by 256, so divide system()'s return value by that to get the actual exitcode: int exitcode = status / 256).

The manpage for wait() (in section 2, man 2 wait on your Linux system) lists the various macros you can use to examine the status, the most interesting ones would be WIFEXITED and WEXITSTATUS.

Alternatively, if you need to read foo's standard output, use popen(3), which returns a file pointer (FILE *); interacting with the command's standard input/output is then the same as reading from or writing to a file.

Sign up to request clarification or add additional context in comments.

7 Comments

system() is declared where?
stdlib.h, found in another answer.
See securecoding.cert.org/confluence/pages/… and alternative answer posted by this author.
@Erik : What I can do if there is no available shell?
This solution is not the right way to go, you can introduce a lot of security bugs in your application. Check you this: securecoding.cert.org/confluence/pages/… A better solution is to use popen, or execve or related functions.
|
44

The system function invokes a shell to run the command. While this is convenient, it has well known security implications. If you can fully specify the path to the program or script that you want to execute, and you can afford losing the platform independence that system provides, then you can use an execve wrapper as illustrated in the exec_prog function below to more securely execute your program.

Here's how you specify the arguments in the caller:

const char    *my_argv[64] = {"/foo/bar/baz" , "-foo" , "-bar" , NULL};

Then call the exec_prog function like this:

int rc = exec_prog(my_argv);

Here's the exec_prog function:

static int exec_prog(const char **argv)
{
    pid_t   my_pid;
    int     status, timeout /* unused ifdef WAIT_FOR_COMPLETION */;

    if (0 == (my_pid = fork())) {
            if (-1 == execve(argv[0], (char **)argv , NULL)) {
                    perror("child process execve failed [%m]");
                    return -1;
            }
    }

#ifdef WAIT_FOR_COMPLETION
    timeout = 1000;

    while (0 == waitpid(my_pid , &status , WNOHANG)) {
            if ( --timeout < 0 ) {
                    perror("timeout");
                    return -1;
            }
            sleep(1);
    }

    printf("%s WEXITSTATUS %d WIFEXITED %d [status %d]\n",
            argv[0], WEXITSTATUS(status), WIFEXITED(status), status);

    if (1 != WIFEXITED(status) || 0 != WEXITSTATUS(status)) {
            perror("%s failed, halt system");
            return -1;
    }

#endif
    return 0;
}

Remember the includes:

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

See related SE post for situations that require communication with the executed program via file descriptors such as stdin and stdout.

1 Comment

What does %s and %m do in perror call(s) ? Is it not a mistake ?
21

You can use fork() and system() so that your program doesn't have to wait until system() returns.

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

int main(int argc,char* argv[]){

    int status;

    // By calling fork(), a child process will be created as a exact duplicate of the calling process.
    // Search for fork() (maybe "man fork" on Linux) for more information.
    if(fork() == 0){ 
        // Child process will return 0 from fork()
        printf("I'm the child process.\n");
        status = system("my_app");
        exit(0);
    }else{
        // Parent process will return a non-zero value from fork()
        printf("I'm the parent.\n");
    }

    printf("This is my main program and it will continue running and doing anything i want to...\n");

    return 0;
}

1 Comment

It would be far more efficient to just use execl or execv from the child process because it won't use a shell, it won't fork a new thread, and you're exiting right after you called system, anyway. Also, the process will become a zombie if you don't call wait().
12

system() executes a shell which is then responsible for parsing the arguments and executing the desired program. To execute the program directly, use fork() and exec() (which is what system() uses to execute the shell as well as what the shell itself uses to execute commands).

#include <unistd.h>

int main() {
     if (fork() == 0) {
          /*
           * fork() returns 0 to the child process
           * and the child's PID to the parent.
           */
          execl("/path/to/foo", "foo", "arg1", "arg2", "arg3", 0);
          /*
           * We wouldn't still be here if execl() was successful,
           * so a non-zero exit value is appropriate.
           */
          return 1;
     }

     return 0;
}

5 Comments

What to put in the path if the executable exists in the same directory?
@y_159 Just remove everything up to and including the last slash. If you're trying to execute a file named foo in the current directory, the code would be: execl("foo", "foo", "arg1", "arg2", "arg3", 0);
thanks. just one doubt instead of foo in the second argument shouldn't it be ./foo?
@y_159 You can add ./, but it isn't required.
This is the correct answer. All the others rely on flawed calls and poorly secured functions.
5

In C

#include <stdlib.h>

system("./foo 1 2 3");

In C++

#include <cstdlib>

std::system("./foo 1 2 3");

Then open and read the file as usual.

1 Comment

I'm trying to do this, but instead of using the value directly, i need to pass a c variable, how can i do this?
2

How about like this:

char* cmd = "./foo 1 2 3";
system(cmd);

3 Comments

While assigning a string literal to a char *, it is deprecated in C++ and a bad idea in C.
I meant: while it is valid, not just "while". :)
@FredFoo Why is it a bad idea?
1

Here's the way to extend to variable args when you don't have the args hard coded (although they are still technically hard coded in this example, but should be easy to figure out how to extend...):

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

int argcount = 3;
const char* args[] = {"1", "2", "3"};
const char* binary_name = "mybinaryname";
char myoutput_array[5000];

sprintf(myoutput_array, "%s", binary_name);
for(int i = 0; i < argcount; ++i)
{
    strcat(myoutput_array, " ");
    strcat(myoutput_array, args[i]);
}
system(myoutput_array);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.