16

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

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

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

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

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

使用带有 execve 的新路径来运行 ls 命令

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

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

mysetenv dog spike

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

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

4

3 回答 3

42

其实很简单。您已经知道您的参数是一个char *由 NULL 指针终止的列表。同样,环境只是一个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使用参数-c和运行env,这意味着 shell 将运行env在其当前 PATH 中找到的程序。这里的环境设置为包含 5 个正统格式的值。例如,如果您更改envdate(或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”表示法的条目(没有等号)来玩游戏。

于 2011-10-05T05:48:13.067 回答
8

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

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

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

setenv()putenv()modify environ,因此当您将其传递过来时execve(),环境变量将与您期望的一样。

于 2016-08-22T20:15:42.557 回答
1

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

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

chdir("/foo/bar"); 
execve(argv[0], &argv[0], envp);
于 2012-08-28T11:25:16.633 回答