【问题标题】:Using '__progname' instead of argv[0]使用 '__progname' 而不是 argv[0]
【发布时间】:2010-09-21 09:10:32
【问题描述】:

在我工作的 C / Unix 环境中,我看到一些开发人员使用 __progname 而不是 argv[0] 来获取使用消息。这有什么好处吗? __prognameargv[0] 有什么区别。便携吗?

【问题讨论】:

    标签: c unix


    【解决方案1】:

    __progname 不是标准的,因此不可移植,更喜欢argv[0]。我想__progname 可以查找字符串资源以获取不依赖于您运行它的文件名的名称。但是argv[0] 会给你他们实际上运行它的名字,我会发现它更有用。

    【讨论】:

    • 考虑:execl("/bin/sh", "hot potato", "-c", "echo $0 - Hi", (char *)0);工作正常; argv[0] 是“烫手山芋”;呼应“热土豆-嗨”。这与运行的可执行文件的名称无关。
    • 尽管前面有评论 - 我同意 argv[0] 更便携。只有少数程序会像这样与 argv[0] 混淆——但任何攻击者都可以这样做。谨慎基于 argv[0] 做出关键决策。
    【解决方案2】:

    使用__progname 允许您更改argv[] 数组的内容,同时仍保留程序名称。 getopt() 等一些常用工具在处理参数时会修改 argv[]

    为了可移植性,您可以在程序启动时将strcopy argv[0] 放入您自己的progname 缓冲区。

    【讨论】:

    • GNU getopt() 与 argv 混淆;非 GNU 版本通常不会这样做。
    • @Jonathan:是的,感谢您的澄清。我是 GNU 我一直坚持使用一个平台太久了。 (对不起。)
    【解决方案3】:

    我发现 argv[0] 至少有两个潜在问题。

    首先,如果 execve() 调用者邪恶或粗心,则 argv[0] 或 argv 本身可能为 NULL。调用 execve("foobar", NULL, NULL) 通常是一种简单而有趣的方式来证明一个过于自信的程序员他的代码不是 sig11-proof。

    还必须注意,argv 不会在 main() 之外定义,而 __progname 通常被定义为全局变量,您可以在您的 usage() 函数中甚至在调用 main() 之前使用(如非标准GCC 构造函数)。

    【讨论】:

    【解决方案4】:

    为此还有一个 GNU 扩展,因此可以从 main() 外部访问程序调用名称,而无需手动保存。但是,手动操作可能会更好。从而使其可移植,而不是依赖于 GNU 扩展。不过,我在这里提供了可用文档的摘录。

    来自the on-line GNU C Library manual(今天访问):

    “许多不从终端读取输入的程序被设计为在任何系统调用失败时退出。按照惯例,此类程序的错误消息应以程序名称开头,无目录。您可以找到该名称在变量program_invocation_short_name中;完整的文件名存储在变量program_invocation_name中。

    • 变量:char * program_invocation_name 该变量的值是用于调用在当前进程中运行的程序的名称。与argv[0] 相同。请注意,这不一定是有用的文件名;通常它不包含目录名称。

    • 变量:char * program_invocation_short_name 此变量的值是用于调用在当前进程中运行的程序的名称,删除了目录名称。 (也就是说,它等于program_invocation_name 减去最后一个斜线之前的所有内容,如果有的话。)

    库初始化代码在调用 main 之前设置这两个变量。

    可移植性说明:这两个变量是 GNU 扩展。如果您希望您的程序使用非 GNU 库,则必须将 argv[0] 的值保存在 main 中,然后自己删除目录名称。我们添加了这些扩展,以便编写独立的错误报告子例程,这些子例程不需要主程序的明确合作。”

    【讨论】:

      【解决方案5】:

      这是一种 BSD 主义,绝对不能移植。

      【讨论】:

        【解决方案6】:

        __progname 只是 argv[0],此处其他回复中的示例显示了使用它的弱点。虽然也不是可移植的,但我在 /proc/self/exe(Linux、Android)上使用 readlink,并读取 /proc/self/exefile (QNX) 的内容。

        【讨论】:

        • /proc 既然能找到正确的可执行路径,那肯定是有系统功能的。
        【解决方案7】:

        如果您的程序是使用例如符号链接运行的,则 argv[0] 将包含该链接的名称。

        我猜 __progname 将包含实际程序文件的名称。

        无论如何,argv[0] 是由 C 标准定义的。 __progname 不是。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-09-11
          • 2016-06-03
          • 2020-01-15
          • 2014-09-22
          • 1970-01-01
          • 2011-01-02
          • 2021-09-18
          相关资源
          最近更新 更多