环境变量
我们在第2章讨论了环境变量。这些变量可以用来控制shell脚本和其他程序的形为。我们也可以使用他们来配置用户环境。例如,每一个用户都有一个环境变量,HOME,定义了其用户主目录,作为其会话的起始位置。正如我们所知的,我们由shell提示来测试环境变量:
$ echo $HOME
/home/neil
我们也可以使用shell的set命令来列出所有的环境变量。
Unix描述定义了许多标准的环境变量用于各种目的,包括终端类型,默认编辑器,时区,等等。一个C程序可以使用putenv与getenv函数来访问环境变量。
#include <stdlib.h>
char *getenv(const char *name);
int putenv(const char *string);
环 境由name=value形式的字符串组成。getenv函数会查找由name所指定的环境,并且返回与其相关的值。如果所请求的变量不存,则会返回 null。如果变量存在但是却没有值,getenv函数会成功返回一个字符串,其第一个字节为null。由getenv函数所返回的变量存储在由 getenv所提供的表态存储区中,他不可被程序覆盖,因为他会由getenv的序列调用覆盖。
putenv函数的参数为一个name=value格式的字符串,并且将其添加到当前环境中。如果因为缺少可用内存不能扩展环境时,函数调用失败并且返回-1。如果发生这种情况,错误变量errno会被设置为ENOMEM。
下面让我们来编写一个程序打印出我们选择的任何环境变量的值。如果我们程序指定了第二个参数,我们还可以设置其值。
试验--getenv与putenv
1 main函数声明之后的几行确保程序environ.c被正确的调用:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *var, *value;
if(argc == 1 || argc > 3) {
fprintf(stderr,”usage: environ var [value]/n”);
exit(1);
}
2 做完这些工作以后,我们使用getenv函数由环境中取得变量的值:
var = argv[1];
value = getenv(var);
if(value)
printf(“Variable %s has value %s/n”, var, value);
else
printf(“Variable %s has no value/n”, var);
3 接下来我们要检测程序调用是否指定了第二个参数。如果指定了第二个参数,我们将变量设置为通过组合成的name=value格式的参数值,然后调用putenv:
if(argc == 3) {
char *string;
value = argv[2];
string = malloc(strlen(var)+strlen(value)+2);
if(!string) {
fprintf(stderr,”out of memory/n”);
exit(1);
}
strcpy(string,var);
strcat(string,”=”);
strcat(string,value);
printf(“Calling putenv with: %s/n”,string);
if(putenv(string) != 0) {
fprintf(stderr,”putenv failed/n”);
free(string);
exit(1);
}
4 最后,我们通过再次调用getenv函数来测试新的变量值:
value = getenv(var);
if(value)
printf(“New value of %s is %s/n”, var, value);
else
printf(“New value of %s is null??/n”, var);
}
exit(0);
}
如果我们运行这个程序,我们可以得到下面的程序输出:
$ ./environ HOME
Variable HOME has value /home/neil
$ ./environ FRED
Variable FRED has no value
$ ./environ FRED hello
Variable FRED has no value
Calling putenv with: FRED=hello
New value of FRED is hello
$ ./environ FRED
Variable FRED has no value
注意,环境只对我们的程序局部可见。我们在程序内部所做的改变并不会反映到程序外部,因为变量值并不会由子进程(我们的程序)传递到父进程(shell)。
使用环境变量
程序通常使用环境变量来改变其工作的方式。用户可以用各种方式改变环境变量,或者是在其默认环境中,修改我们的登陆shell所读取的.profile文件,或者是使用一个shell特定的启动文件(rc),或者是在shell命令行指定变量。例如:
$ ./environ FRED
Variable FRED has no value
$ FRED=hello ./environ FRED
Variable FRED has value hello
shell将初始的变量赋值作为环境变量的临时改变。在我们上面的第二个例子中,程序environ运行在一个变量FRED有值的环境中。
例如,在我们的CD数据库程序的将来版本中,我们会改变一个环境变量CDDB,来指定要使用的数据库。每个用户都可以指定他们自己的默认值或是使用一个shell命令来进行设置:
$ CDDB=mycds; export CDDB
$ cdapp
或者
$ CDDB=mycds cdapp
environ变量
正如我们所看到的,程序环境是由name=value格式的字符串组成的。这个字符串数组是直接通过environ变量使其可以为程序可用的,其声明为:
#include <stdlib.h>
extern char **environ;
试验--environ
这里有一个showenv.c程序,使用environ变量来打印出环境变量:
#include <stdlib.h>
#include <stdio.h>
extern char **environ;
int main()
{
char **env = environ;
while(*env) {
printf(“%s/n”,*env);
env++;
}
exit(0);
}
在当我们在一个Linux系统上运行这个程序时,我们会得到类似于下面的输出,在这里进行大量的简写。这些变量的数量,出现的顺序,及其值依赖于操作系统版本,所使用的命令shell,以及程序运行时的用户设置:
$ ./showenv
HOSTNAME=tilde.provider.com
LOGNAME=neil
MAIL=/var/spool/mail/neil
TERM=console
HOSTTYPE=i386
PATH=/usr/local/bin:/bin:/usr/bin:
HOME=/usr/neil
LS_OPTIONS=—8bit—color=tty -F -T 0
SHELL=/bin/bash
PS1=/h:/w/$
PS2=>
OSTYPE=Linux
工作原理
这个程序在environ变量中遍历来打印出整个环境。