问题
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?
回答1:
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.
回答2:
If you pass a null pointer as the second, or the third, argument of execve
, your program is incorrect according to POSIX; both of these arguments are required to be non-null. (This is not all that clearly stated in the specification of execve, but it's in there.) I am currently typing this on an operating system that treats passing null pointers,
execve("executable", 0, 0);
as equivalent to passing empty arrays, e.g.
execve("executable", (char *[]){0}, (char *[]){0});
but it would not surprise me to learn that other operating systems would fire a segmentation fault or return -1 with errno
set to EFAULT
or EINVAL
.
Passing empty arrays for these arguments is allowed, but the newly executed program will receive zero arguments in argc
/argv
if the second argument is an empty array, and/or zero environment variables in envp
/environ
if the third argument is an empty array. Many programs will malfunction under these conditions. For instance, it is very common to see things like
int main(int argc, char **argv)
{
if (argc != 4) {
fprintf(stderr, "usage: %s one two three\n", argv[0]);
return 2;
}
// ...
}
where the program implicitly assumes that argv[0]
will always be non-null.
So, you should always provide non-empty arrays for both arguments. The usual convention is that if you don't have anything else to do, you use
execve(program, (char *[]){program, 0}, environ);
which supplies the program's own name as argv[0]
and no further arguments, and the same set of environment variables you got from your own parent.
来源:https://stackoverflow.com/questions/30149779/c-execve-parameters-spawn-a-shell-example