C语言 了解 execve 和设置环境变量的要求
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7656549/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
understanding requirements for execve and setting environment vars
提问by james
We are having a lot of trouble interpreting our teacher. We asked for clarification and got the following back from him
我们在解释我们的老师时遇到了很多麻烦。我们要求澄清并从他那里得到以下回复
For execve, send it a environment you setup with your exported variables and create a builtin command to spawn a subshell of /bin/bash, that way you can see your exported variables using env.
(He is talking about creating our own environment vars here.)
- Yes create your own. You can start by copying environ when your shell starts and add only exported variables
对于 execve,向它发送一个使用导出变量设置的环境,并创建一个内置命令来生成 /bin/bash 的子 shell,这样您就可以使用 env 查看导出的变量。
(他在这里谈论的是创建我们自己的环境变量。)
- 是的,创建自己的。您可以从在 shell 启动时复制环境开始,并仅添加导出的变量
This is related to the following post on Stack Overflow by me (reading this other post will help you understand what I am trying to do):
这与我在 Stack Overflow 上的以下帖子有关(阅读其他帖子将帮助您了解我正在尝试做什么):
using a new path with execve to run ls command
We are just very confused about this. One more time I will explain what we are trying to do now. Similar to how your Linux shell does this, we need to write our own program that can set environment variables like PATH and USER and whatever other vars the user wants to define.
我们对此感到非常困惑。再一次,我将解释我们现在正在尝试做什么。类似于你的 Linux shell 如何做到这一点,我们需要编写我们自己的程序来设置环境变量,如 PATH 和 USER 以及用户想要定义的任何其他变量。
An example of how you would call this would be (inside your program at its prompt):
您将如何调用它的一个示例是(在您的程序中提示):
mysetenv dog spike
which would create an environment variable looking like "dog=spike"
这将创建一个看起来像“dog=spike”的环境变量
More importantly, we need to be able to set our own PATH variable and send it to an execcommand. This is the confusing part because, based on all of our questions, we don't understand what we are supposed to do.
更重要的是,我们需要能够设置我们自己的 PATH 变量并将其发送给exec命令。这是令人困惑的部分,因为基于我们所有的问题,我们不明白我们应该做什么。
回答by Jonathan Leffler
It is actually very simple. You already know that your arguments are a list of char *, terminated by a NULL pointer. Similarly, the environment is simply a list of char *, terminated by a NULL pointer. Conventionally, the values in the list take the form VARNAME=var-value, though you can pass other formats if you wish.
其实很简单。您已经知道您的参数是一个char *以 NULL 指针结尾的 列表。类似地,环境只是一个char *由 NULL 指针终止的列表。通常,列表中的值采用 形式VARNAME=var-value,但如果您愿意,也可以传递其他格式。
So, to take a simple case:
所以,举个简单的例子:
#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;
}
In this example, the program will run /bin/shwith arguments -cand env, which means that the shell will run the envprogram found on its current PATH. The environment here is set to contain 5 values in the orthodox format. If you change envto date(or env; date), you will see the effect of the TZ setting, for example. When I run that on my MacOS X machine, the output is:
在此示例中,程序将/bin/sh使用参数-cand运行env,这意味着 shell 将运行env在其当前 PATH 中找到的程序。这里的环境设置为包含 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
The shell has added environment variables SHLVL, _and PWDto the ones I set explicitly in the execve()call.
shell 添加了环境变量SHLVL,_以及PWD我在execve()调用中明确设置的变量。
You can also do fancier things, such as copy in some of the other environment variables from your genuine environment where they do not conflict with the ones you want to set explicitly. You can also play games like having two values for a single variable in the environment - which one takes effect? And you can play games with variable names that contain spaces (the shell doesn't like that much), or entries that do not match the 'varname=value' notation at all (no equals sign).
您还可以做一些更有趣的事情,例如从您的真实环境中复制一些其他环境变量,这些环境变量不会与您要明确设置的环境变量冲突。您还可以玩游戏,例如为环境中的单个变量设置两个值 - 哪个生效?并且您可以使用包含空格的变量名称(shell 不喜欢那么多)或根本不匹配“varname=value”符号(没有等号)的条目来玩游戏。
回答by Fred Frey
I'm a little late to the party here, but if you want to preserve the old environment variables as well as creating your own, use setenv, and then pass environto execve().
我在这里参加聚会有点晚了,但是如果您想保留旧的环境变量并创建自己的环境变量,请使用setenv,然后传递environ给execve().
setenv("dog", "spike", 1);
extern char** environ;
execve(argv[0], argv, environ);
environis a variable declared in unistd.h, and it keeps track of the environment variables during this running process.
environ是在 中声明的变量unistd.h,它在此运行过程中跟踪环境变量。
setenv()and putenv()modify environ, so when you pass it over execve(), the environment variables will be just as you'd expect.
setenv()和putenv()modify environ,所以当你传递它时execve(),环境变量将正如你所期望的那样。
回答by qknight
The code from Jonathan Lefflerworks great, except if you want to change the PWD(working directory) variable.
Jonathan Leffler的代码效果很好,除非您想更改PWD(工作目录)变量。
What I did, in order to change the working directory, was to put a chdir(..)before execve(..)and call:
为了更改工作目录,我所做的是chdir(..)在之前放置一个execve(..)并调用:
chdir("/foo/bar");
execve(argv[0], &argv[0], envp);

