提前通过 execlp 确定哪个二进制文件 运行

Determine which binary will run via execlp in advance

编辑#1


到目前为止 "Possible duplicates" 不是 重复项。他们测试 $FILE$PATH 中是否存在,而不是提供第一个有效结果的完整路径;并且最佳答案使用 command line commands, not pure .

原问题


在所有 exec 系列函数中,有一些执行 $PATH 查找而不需要执行二进制文件的绝对路径。

来自man exec:

The execlp(), execvp(), and execvpe() functions duplicate the actions of the shell in searching for an executable file if the specified filename does not contain a slash (/) character. The file is sought in the colon-separated list of directory pathnames specified in the PATH environment variable. If this variable isn't defined, the path list defaults to the current directory followed by the list of directories returned by confstr(_CS_PATH). (This confstr(3) call typically returns the value "/bin:/usr/bin".)

是否有一种简单、直接的方法来测试第一个 "full path to execute" 的计算结果,而无需手动遍历 $PATH 环境变量中的所有元素,并附加二进制文件名称到路径的末尾?我想使用 "de facto standard" 方法将二进制文件估计为 运行,而不是重写过去可能已经实施过多次的任务。

我知道这不能保证,因为有人可能会通过错误的脚本、TOCTOU 攻击等使此检查无效。我只需要一个合适的近似值来进行测试。

谢谢。

Is there a simple, straightforward way, to test what the first "full path to execute" will evaluate to, without having to manually iterate through all the elements in the $PATH environment variable

不,您需要遍历 $PATH(即 C 代码中的 getenv("PATH"))。一些(非标准)库提供了一种方法来做到这一点,但它真的很简单,你不应该费心。您可以使用 strchr(3) to find the "next" occurrence of colon :, so coding that loop is really simple. As Jonathan Leffler 注释,它们是微妙的(例如权限、挂起的符号链接、一些 other 进程添加一些新的 executable 到您的 $PATH) 但大多数程序会忽略它们。

真正相关的是 运行 execvp 之前的 PATH 值。实际上,它是启动程序时 PATH 的值(因为外部进程无法更改它)。您只需要确保您的程序不会更改 PATH 这很有可能(极端情况和困难情况,将是同一 process- changing the PATH environment variable with putenv(3) or setenv(3) 的其他线程)。

实践中,PATH不会改变(除非有一些代码明确改变它)。即使您使用专有库并且没有时间检查它们的源代码,您也可以期望 PATH 在执行过程中在实践中保持不变。

如果你需要一些更精确的东西,假设你在程序名称上使用 execp 函数,这些函数是编译时常量,或者至少在你的程序初始化读取一些配置文件后是常量,你可以做很多shells 正在做: "caching" 将 PATH 搜索到一些散列 table 中并在其上使用 execve 的结果。不过,您仍然无法避免某些 other 进程将文件添加或删除到 PATH 中提到的目录中的问题;但是大多数程序并不关心(并且在编写时隐含假设这不会发生,或者会通知您的程序:以 zshrehash 内置为例)。 =34=]

但是你总是需要针对exec(包括execlp(3) & execve(2))和fork函数的失败进行测试。它们可能因多种原因而失败,即使 PATH 没有更改并且其中提到的目录和文件也没有更改。