0

编辑#1


到目前为止,“可能的重复”不是重复的。他们测试$FILEin的存在$PATH,而不是提供第一个有效结果的完整路径;最佳答案使用命令行命令,而不是纯

原始问题


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

来自man exec

如果指定的文件名不包含斜杠 (/) 字符,则 execlp()、execvp() 和 execvpe() 函数会复制 shell 在搜索可执行文件时的操作。在 PATH 环境变量中指定的以冒号分隔的目录路径名列表中查找该文件。如果未定义此变量,则路径列表默认为当前目录,后跟 confstr(_CS_PATH) 返回的目录列表。(此 confstr(3) 调用通常返回值“/bin:/usr/bin”。)

是否有一种简单直接的方法来测试第一个“执行的完整路径”将评估为什么,而不必手动遍历$PATH环境变量中的所有元素,并将二进制名称附加到路径的末尾?我想使用“事实上的标准”方法来估计要运行的二进制文件,而不是重写过去可能已经实施过多次的任务。

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

谢谢你。

4

1 回答 1

3

是否有一种简单直接的方法来测试第一个“执行的完整路径”将评估为什么,而无需手动遍历 $PATH 环境变量中的所有元素

不,您需要遍历$PATH(即getenv("PATH")在 C 代码中)。一些(非标准)库提供了一种方法来做到这一点,但它真的很简单,你不应该打扰。您可以使用strchr(3)来查找冒号的“下一个”出现:,因此对该循环进行编码非常简单。正如Jonathan Leffler评论的那样,它们是微妙的(例如权限、挂起的符号链接、一些其他进程将一些新的可执行文件添加到您提到的目录中$PATH),但大多数程序都会忽略它们。

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

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

如果您需要一些更精确的东西,并假设您execp在程序名称上使用函数,这些函数是编译时常量,或者至少在程序初始化读取一些配置文件后是常量,您可以做许多 shell 正在做的事情:“缓存”结果搜索PATH一些哈希表,并execve在上面使用。尽管如此,您仍无法避免其他PATH一些进程将文件添加或删除到您的;中提到的目录中的问题。但是大多数程序并不关心(并且在编写时隐含假设这不会发生,或者会通知您的程序:以rehash内置zsh的为例)。

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

于 2017-01-27T06:16:18.103 回答