【问题标题】:What corner cases must we consider when parsing $PATH on Linux?在 Linux 上解析 $PATH 时我们必须考虑哪些极端情况?
【发布时间】:2011-10-30 14:35:48
【问题描述】:

我正在开发一个 C 应用程序,该应用程序必须通过 $PATH 来查找二进制文件的完整路径名,并且唯一允许的依赖项是 glibc(即不能调用类似的外部程序)。在正常情况下,这只需要用冒号拆分 getenv("PATH") 并逐个检查每个目录,但我想确保我涵盖了所有可能的极端情况。我应该注意什么问题?特别是,相对路径、以 ~ 开头的路径意味着扩展为 $HOME 或包含 : 字符的路径是否允许?

【问题讨论】:

    标签: c linux posix environment-variables glibc


    【解决方案1】:

    曾经让我吃惊的一件事是PATH 中的空字符串表示当前目录。 PATH 的两个相邻冒号或末尾或开头的冒号表示包含当前目录。例如,这记录在 man bash 中。

    它也在POSIX specification

    所以

    PATH=:/bin
    PATH=/bin:
    PATH=/bin::/usr/bin
    

    都表示当前目录在PATH

    【讨论】:

    • +1 在检查which 的源代码后,似乎这是唯一的极端情况。 which 首先检查是否给出了完整路径并且文件是否可执行。然后它将在路径的每个组件之前添加并再次检查,用当前目录替换一个空的路径组件。
    • 遵循规范,which 的实现和一些常见的标准 shell 应该可以提供一个很好的视角。
    【解决方案2】:

    我不确定这是否是一般 Linux 的问题,但如果PATH 有一些时髦的(如 UTF-8)编码来处理带有花哨字母的目录,请确保您的代码可以正常工作。我怀疑这可能取决于文件系统编码。

    我记得我正在处理某个俄罗斯人的错误报告,该人的用户名中有花哨的字母(因此,他的主目录名称出现在 PATH 中)。

    【讨论】:

    • 不,编码与PATH 无关。如果一个程序考虑它,它就是错误的。
    • @R.:有趣;你有一些规格来支持这种说法吗?我的理解是,为了解析PATH,您需要将其视为一个字符序列(而不是bytes 序列),因此您需要了解编码。
    • PATH 中唯一特殊的字符是 :,因此您的声明唯一有效的情况是使用面向 Windows 的传统 CJK 编码,但这些通常被认为在 Unix 上不可用.
    • @R.:冒号确实是专门用于拆分PATH 值的。然而,这还不够。想象一下,您想对路径实际一些事情,例如将它们打印到屏幕上(使用本地 8 位编码)或通过线路将它们作为 UTF-8 编码字符串发送,以便另一台计算机可以使用在您的主目录名称中添加精美的俄语字符。在这些情况下,您必须执行字符串转换,这要求您知道字符串当前编码的内容。
    • 不,你没有。在任何正确配置的系统上,区域设置的编码和文件系统编码匹配。您所做的就是打印它。如果它们不匹配,则没有标准方法可以知道编码是什么,您也无能为力。当然,任何现代系统无论如何都将是全 UTF-8... 最后,使用 PATHdo 的正常操作不是打印它,而是搜索文件(程序)运行,在这种情况下编码总是无关紧要的。
    【解决方案3】:

    这是次要的,但我会添加它,因为它尚未被提及。 $PATH 可以包括绝对路径和相对路径。如果您通过 chdir(2) 抓取每个目录的路径列表,则需要在每次抓取迭代时跟踪原始工作目录 (getcwd(3)) 和 chdir(2)。

    【讨论】:

      【解决方案4】:

      现有答案涵盖了大部分内容,但值得涵盖尚未回答的部分问题:

      1. $ 和 ~ 在 $PATH 的值中并不特殊。
      2. 如果根本没有设置 $PATH,execvp() 将使用默认值。

      【讨论】:

        猜你喜欢
        • 2011-01-01
        • 2020-11-09
        • 2017-02-21
        • 2021-04-26
        • 1970-01-01
        • 2011-06-21
        • 1970-01-01
        • 1970-01-01
        • 2012-06-20
        相关资源
        最近更新 更多