我正在尝试运行一个简单的 C 程序。
#include <stdio.h>
#include <unistd.h>
extern char** environ;
int main(){
// execl("/bin/sh","sh","-c","/bin/ls -l",(char *) NULL);
char* argv[] = {"/bin/sh","sh","-c","/bin/ls", (char*) NULL};
execve(argv[0], argv, environ);
return 0;
}
注释掉的 execl 运行良好。但是当我尝试对 execve 执行相同操作时,编译器会调用以下错误:
/bin/sh: 0: Can't open sh
我在这里做错了什么?
答案1
char* argv[] = {"/bin/sh","sh","-c","/bin/ls", (char*) NULL};
execve(argv[0], argv, environ);
请注意,您使用argv[0]
( /bin/sh
) 两次,一次作为 的第一个参数execve()
,另一次作为作为第二个参数传递给它的数组的一部分。这不是您的execl()
调用中发生的情况,您只有/bin/sh
第一个参数(程序文件)。
因此,您execve()
执行文件/bin/sh
,为其指定程序名称(第零个参数)/bin/sh
和常规参数sh
, -c
, /bin/ls
。这与调用几乎相同execl("/bin/sh", "/bin/sh", "sh", "-c", "/bin/ls", (char*) NULL)
。或者在 shell 命令行中:
$ /bin/sh sh -c /bin/ls
/bin/sh: 0: Can't open sh
这告诉 shell 尝试运行sh
当前目录中调用的脚本,如果该脚本不存在,则 Dash 会给出错误消息。零可能是命令行参数的行号。 (Bash 给出了类似但不同的错误消息,并且似乎也在寻找脚本PATH
。我不确定标准是否说明了有关PATH
在这里使用的任何内容。)
你可以这样做
char *program = "/bin/sh";
char *argv[] = {"sh", "-c", "/bin/ls", NULL};
execve(program, argv, environ);
或者可能
char *argv[] = {"/bin/sh", "sh", "-c", "/bin/ls", NULL};
execve(argv[0], argv + 1, environ);