我必须填写以下参数:
int execve(const char *filename, char *const argv[], char *const envp[]);
如果我执行此程序:
#include <unistd.h>
int main() {
char *args[2];
args[0] = "/bin/sh";
args[1] = NULL;
execve(args[0], args, NULL);
}
按预期正确生成shell。
我的问题是,如果我将NULL作为第二个参数传递,那么shell也会正确生成:
#include <unistd.h>
int main() {
char *args[2];
args[0] = "/bin/sh";
args[1] = NULL;
execve(args[0], NULL, NULL);
}
那么使用args向量(使用“/ bin / sh”+ NULL)作为第二个参数而不是NULL的目的是什么?
答案 0 :(得分:2)
在这一行中:execve(args[0], NULL, NULL);
您只是使用args
数组的第一个元素。你也可以使用像char* command="/bin/sh"
这样的东西。您必须传递某些内容,因为这是execve()
的定义方式。在您的情况下,您传递NULL
,因为您不需要传递任何内容。
execve()
的第二个参数的要点是将参数传递给您正在生成的命令。假设您只需要执行ls
而不是shell,则可以传递f.e.这些论点:
#include <unistd.h>
int main() {
char *args[2];
args[0] = "/bin/ls";
args[1] = "-lh";
execve(args[0], args, NULL);
}
另外,引用man execve
:
argv是传递给新程序的参数字符串数组。 按 约定,这些字符串中的第一个应该包含文件名 与正在执行的文件相关联。 envp是一个数组 通常为key = value形式的字符串,它们被传递为 新计划的环境。
答案 1 :(得分:2)
如果将空指针作为execve
的第二个或第三个参数传递,则根据POSIX,您的程序是不正确的;这两个参数都必须是非null。 (the specification of execve
中没有明确说明这一点,但它就在那里。)我目前正在一个处理空指针的操作系统上输入它,
execve("executable", 0, 0);
等同于传递空数组,例如
execve("executable", (char *[]){0}, (char *[]){0});
但要了解其他操作系统会触发分段错误或在errno
设置为EFAULT
或EINVAL
时返回-1并不会让我感到惊讶。
允许为这些参数传递空数组,但如果第二个参数是空数组,则argc
/ argv
中新执行的程序将接收零参数,和/或{ {1}} / envp
如果第三个参数是一个空数组。许多程序在这些条件下会出现故障。例如,看到像
environ
程序隐含地假设int main(int argc, char **argv)
{
if (argc != 4) {
fprintf(stderr, "usage: %s one two three\n", argv[0]);
return 2;
}
// ...
}
始终为非空。
因此,您应该始终为这两个参数提供非空数组。通常的惯例是,如果你没有别的事可做,你可以使用
argv[0]
提供程序自己的名称execve(program, (char *[]){program, 0}, environ);
,没有其他参数,以及您从父母那里得到的同一组环境变量。