不能以适当的方式执行其他程序

时间:2017-11-29 19:00:25

标签: c++ execvp

我正在尝试从我自己的程序中执行另一个程序,但我不了解一些事情。所以我写了这段代码:

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()函数调用时失败了?

1 个答案:

答案 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失败

是的,errno(3)。由perror(3)使用。

不要忘记仔细阅读 每个使用过的功能的文档。对于系统调用(在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 -gwith)和GCC(可能还有use the debugger gdbstrace(1) )。