C execve() parameters [spawn a shell example]

rh0x picture rh0x · May 10, 2015 · Viewed 18.4k times · Source

I have to fill the parameters for:

int execve(const char *filename, char *const argv[], char *const envp[]);

If I execute this program:

#include <unistd.h>
int main() {
        char *args[2];
        args[0] = "/bin/sh";
        args[1] = NULL;
        execve(args[0], args, NULL);
}

the shell is spawned correctly as expected.

My problem is that the shell is spawned correctly also if I pass a NULL as second parameter like that:

#include <unistd.h>

int main() {
        char *args[2];
        args[0] = "/bin/sh";
        args[1] = NULL;
        execve(args[0], NULL, NULL);
}

So what's the purpose to use the args vector (with the "/bin/sh" + NULL) as second parameter instead of a NULL?

Answer

syntagma picture syntagma · May 10, 2015

In this line: execve(args[0], NULL, NULL); you are simply using the first element of args array. You could also use something like char* command="/bin/sh". You have to pass something, because that's how execve() was defined. In your case you pass NULL because you don't need to pass anything.

The point of the second argument of execve() is to pass arguments to the command you are spawning. Suppose that instead of shell you simply want to execute ls, you could then pass f.e. these arguments:

#include <unistd.h>
int main() {
        char *args[2];
        args[0] = "/bin/ls";
        args[1] = "-lh";
        execve(args[0], args, NULL);
}

Also, quoting man execve:

argv is an array of argument strings passed to the new program. By convention, the first of these strings should contain the filename associated with the file being executed. envp is an array of strings, conventionally of the form key=value, which are passed as environment to the new program.