我正在尝试从我自己的程序中执行另一个程序,但我不了解一些事情。所以我写了这段代码:
void run() {
cout << "##Run" << endl;
pid_t process_id = fork();
if (process_id == 0) {
char* args[] = { "sudo", "ls", "-l" };
auto i = execvp("sudo", args);
cout << "#Result: " << i << endl;
return;
} else if (process_id < 0) {
throw std::runtime_error("fork() failed");
} else if (process_id > 0) {
wait(&process_id);
}
return;
}
void run_decorator() {
cout << "###Run decorator: " << endl;
run();
}
int main() {
run();
run_decorator();
return 0;
}
输出
##Run
total 88
-rwxr-xr-x 1 bezik bezik 77560 Nov 29 19:53 colors
-rwxr-xr-x 1 bezik bezik 63 Nov 26 21:45 compile
drwxr-xr-x 2 bezik bezik 4096 Nov 26 20:46 headers
drwxr-xr-x 2 bezik bezik 4096 Nov 23 00:48 sources
###Run decorator:
##Run
#Result: -1
有人可以向我解释,为什么execvp在从run_decorator()函数调用时失败了?
答案 0 :(得分:1)
仔细阅读 execvp(3)的文档。它说约execl
等......:
按照惯例,第一个论点应指向 与正在执行的文件关联的文件名。清单 参数必须以空指针结束,因为这些是 可变参数函数,必须转换此指针
(char *) NULL
。
关于execvp
:
指针数组必须以空指针终止。
所以你应该编码:
char* args[] = { "sudo", "ls", "-l", NULL };
execvp("sudo", args);
BTW,execvp
根本没有返回,除了失败。通话结束后无需保留结果。
但是当execvp
返回(并且这只在失败时发生)时,您需要显示一些错误消息。我建议:
perror("execvp");
exit(EXIT_FAILURE);
你可以找到有效的参数来调用,在这种精确的情况下,_exit(2)而不是exit(3)。我仍然更喜欢exit
(因为它会刷新stdio缓冲区并运行atexit(3) - 注册处理程序)。
有人可以向我解释,为什么
execvp
失败
不要忘记仔细阅读 每个使用过的功能的文档。对于系统调用(在syscalls(2)中列出)和标准C库函数(请参阅intro(3)),您通常应该处理失败案例(通常使用errno
,至少通过perror
然后exit
)
我不明白为什么sudo
需要ls
。在某些情况下,这可能很有用,因为大多数情况下working directory可列表(然后sudo
无用),在这种情况下,您甚至可以使用opendir(3),{{ 3}} readdir(3)(因此无需fork
然后execvp
/bin/ls
计划。
另请阅读stat(2)和setuid(以及execve(2))中的credentials(7)技术。请参阅setreuid(2)(您可以使用自己的setuid程序避免sudo
。)
顺便说一句,您应该编译this所有警告和调试信息(g++ -Wall -Wextra -g
与with)和GCC(可能还有use the debugger gdb
和strace(1) )。