【问题标题】:understanding requirements for execve and setting environment vars了解 execve 和设置环境变量的要求
【发布时间】:2011-10-05 03:56:16
【问题描述】:

我们在解释我们的老师时遇到了很多麻烦。我们要求澄清并从他那里得到以下回复

  1. 对于 execve,将您使用导出的变量设置的环境发送给它,并创建一个内置命令来生成 /bin/bash 的子 shell,这样您就可以使用 env 查看导出的变量。

    (他在这里谈论创建我们自己的环境变量。)

  2. 是的,创建您自己的。您可以在 shell 启动时复制 environ 并仅添加导出的变量

这与我在 Stack Overflow 上的以下帖子有关(阅读其他帖子将帮助您了解我想要做什么):

using a new path with execve to run ls command

我们对此感到非常困惑。再一次,我将解释我们现在正在尝试做的事情。与您的 Linux shell 执行此操作的方式类似,我们需要编写自己的程序来设置环境变量,如 PATH 和 USER 以及用户想要定义的任何其他变量。

你如何调用它的一个例子是(在你的程序的提示符下):

mysetenv dog spike

这将创建一个看起来像“dog=spike”的环境变量

更重要的是,我们需要能够设置自己的 PATH 变量并将其发送到exec 命令。这是令人困惑的部分,因为根据我们所有的问题,我们不明白我们应该做什么。

【问题讨论】:

    标签: c path exec execve


    【解决方案1】:

    其实很简单。您已经知道您的参数是char * 的列表,以空指针终止。同样,环境只是一个char * 的列表,由一个NULL 指针终止。按照惯例,列表中的值采用VARNAME=var-value 的形式,但您可以根据需要传递其他格式。

    所以,举个简单的例子:

    #include <unistd.h>
    #include <stdio.h>
    
    int main(void)
    {
        char *argv[] = { "/bin/sh", "-c", "env", 0 };
        char *envp[] =
        {
            "HOME=/",
            "PATH=/bin:/usr/bin",
            "TZ=UTC0",
            "USER=beelzebub",
            "LOGNAME=tarzan",
            0
        };
        execve(argv[0], &argv[0], envp);
        fprintf(stderr, "Oops!\n");
        return -1;
    }
    

    在本例中,程序将运行/bin/sh,参数为-cenv,这意味着shell 将运行在其当前路径上找到的env 程序。这里的环境设置为包含 5 个正统格式的值。例如,如果您将env 更改为date(或env; date),您将看到TZ 设置的效果。当我在我的 MacOS X 机器上运行它时,输出是:

    USER=beelzebub
    PATH=/bin:/usr/bin
    PWD=/Users/jleffler/tmp/soq
    TZ=UTC0
    SHLVL=1
    HOME=/
    LOGNAME=tarzan
    _=/usr/bin/env
    

    Shell 已将环境变量 SHLVL_PWD 添加到我在 execve() 调用中明确设置的变量中。

    您还可以做一些更有趣的事情,例如从您的真实环境中复制一些其他环境变量,它们不会与您要显式设置的变量冲突。您还可以玩游戏,例如在环境中为单个变量设置两个值 - 哪个生效?您可以使用包含空格的变量名(shell 不太喜欢)或根本不匹配 'varname=value' 表示法的条目(没有等号)玩游戏。

    【讨论】:

    • 你真的为我清除了这一切。我已经把所有东西都上交了,但是谢谢!我现在明白了。
    【解决方案2】:

    我在这里聚会有点晚了,但是如果您想保留旧环境变量以及创建自己的环境变量,请使用setenv,然后将environ 传递给execve()

        setenv("dog", "spike", 1);
        extern char** environ;
        execve(argv[0], argv, environ);
    

    environunistd.h中声明的变量,它在这个运行过程中跟踪环境变量。

    setenv()putenv() 修改environ,这样当你把它传递给execve() 时,环境变量就会和你期望的一样。

    【讨论】:

    • 您不能在使用setenv 扩展环境后直接调用execv(argv[0], argv); 吗?
    • @ErichKitzmueller 据我了解,环境变量本身不会保留在 execve 上,如果您在不传递环境的情况下调用 execve,它将默认为 shell 的环境变量。不过,我可能是错的。我建议你试试看。
    • 在我的理解中,如果你调用execve,你必须提供一个环境(Linux允许NULL,它的含义就像一个包含单个NULL指针的列表;虽然这是不可移植的)。但是,您可以调用execv(不带e)而不是调用execve,这样也可以调用environ,包括调用setenv所做的更改。
    【解决方案3】:

    Jonathan Leffler 的代码效果很好,除非您想更改 PWD(工作目录)变量。

    为了更改工作目录,我所做的是将chdir(..) 放在execve(..) 之前并调用:

    chdir("/foo/bar"); 
    execve(argv[0], &argv[0], envp);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-14
      • 1970-01-01
      • 2013-05-16
      • 2018-07-13
      • 2014-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多