参考:http://blog.chinaunix.net/uid-620765-id-2084386.html
还记得C语言main函数的完整声明吗?
int main(int argc, char **argv, char **envp);
这个就是c语言中main函数的完整声明, argc表示参数个数,argv表示参数字符串,而这个envp就表示环境变量字符串。参数和环境变量都可以不止一个,所以,用指向字符串指针的指针来表示。
比如我们用C语言写了一个程序,运行在命令行下,带有2个参数
C:> cpfile.exe c:\test.txt d:\test.txt
那么这里的
argc=3;
argv[0] = "cpfile.exe";
argv[1] = "c:\test.txt";
argv[2] = "d:\test.txt";
在c语言中的stdlib.h中有一个
extern char **environ; 或者
extern char **_environ;的声明
这个envp的参数实际上就是environ。
好,我们看看在cgi程序(其实就是一个C语言程序)里面怎么枚举这些环境变量
先写一个html页面:(当然也可以不要)
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Cache-Control" content="no-cache, must-revalidate">
<title>test</title>
<script type="text/javascript">
function post_submit()
{
document.getElementById( "mainform" ).method = "post";
document.getElementById( "mainform" ).submit();
}
function get_submit()
{
document.getElementById( "mainform" ).method = "get";
document.getElementById( "mainform" ).submit();
}
</script>
</head>
<body>
<div class="editView">
<form id="mainform" method="post" action="/printenv.cgi" enctype="multipart/form-data">
<fieldset class="">
<legend>测试页面</legend>
<dl class="nowrap">
<dd>
<span>名称</span>:
<input id="name" name="name" type="text" value="ldapserver_name">
<span>IP</span>:
<input id="ip" name="ip" type="text">
</dd>
</dl>
<dl class="nowrap">
<dd>
<span>复选框1</span>:
<input id="checkbox1" name="checkbox1" type="checkbox" checked/>
<span> 复选框1</span>:
<input id="checkbox2" name="checkbox2" type="checkbox" />
</dd>
</dl>
<dl class="nowrap">
<dd>
<label for="radiotest1">单选按钮1</label>
<input name="radiotest" id="radiotest1" type="radio" value="1"/>
<label for="radiotest2"> 单选按钮2</label>
<input name="radiotest" id="radiotest2" type="radio" value="2" checked/>
<label for="radiotest3"> 单选按钮3</label>
<input name="radiotest" id="radiotest3" type="radio" value="3"/>
</dd>
</dl>
<dl class="nowrap" id="dl_ca">
<dd>
<span>上传文件</span>
<input class="" name="uploadfile" id="uploadfile" type="file"/>
</dd>
</dl>
<dl class="nowrap">
<dd><span>下拉框</span>:
<select name="dropbox" id="dropbox">
<option value="3">3</option>
<option value="2">2</option>
</select>
</dd>
</dl>
</fieldset>
<fieldset class="btnfield">
<dl class="nowrap">
<dt> </dt>
<dd>
<a id="submit" href="javascript:;" value="Submit" οnclick="javascript: post_submit();">post提交</a>
<a id="submit" href="javascript:;" value="Submit" οnclick="javascript: get_submit();">get提交</a>
<a href="javascript:;">取消</a>
</dd>
</dl>
</fieldset>
</form>
</div>
</body>
</html>
呈现效果如下:
cgi程序源码:
/* env.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
extern char **environ;
int nlen = 0;
int i;
char *psz_content = NULL;
char **pp_env;
printf("Content-type: text/html\n\n");
for ( pp_env = environ; *pp_env; pp_env++ )
printf("%s<br>", *pp_env);
if ( strcmp("GET", getenv("REQUEST_METHOD")) == 0 )
{
printf("<p>%s</p>", getenv("QUERY_STRING"));
}
else
{
nlen = atoi(getenv("CONTENT_LENGTH"));
psz_content = ( char * )malloc( nlen + 1 );
memset( psz_content, 0, nlen + 1 );
printf("<p>char value:</p><p>");
for (i = 0; i < nlen; i++ )
{
psz_content[i] = fgetc(stdin);
printf( "%c", psz_content[i] );
}
printf("</p><p>string value: %s</p>", psz_content);
}
return 0;
}
如果是fastcgi可以用以下代码打印环境变量:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcgi_stdio.h>
int main()
{
extern char **environ;
int nlen = 0;
int i;
char *psz_content = NULL;
char **pp_env;
while(FCGI_Accept() >= 0)
{
printf("Content-type: text/html\n\n");
for ( pp_env = environ; *pp_env; pp_env++ )
printf("%s<br>", *pp_env);
if ( strcmp("GET", getenv("REQUEST_METHOD")) == 0 )
{
printf("<p>%s</p>", getenv("QUERY_STRING"));
}
else
{
nlen = atoi(getenv("CONTENT_LENGTH"));
psz_content = ( char * )malloc( nlen + 1 );
memset( psz_content, 0, nlen + 1 );
printf("<p>char value:</p><p>");
for (i = 0; i < nlen; i++ )
{
psz_content[i] = fgetc(stdin);
printf( "%c", psz_content[i] );
}
printf("</p><p>string value: %s</p>", psz_content);
}
}
return 0;
}
注意:
1、这里使用fgetc函数从标准输入读数据,不能使用gets代替
2、FCGX中,头和环境信息在FCGX_Request->envp中,不能用genenv获取,要用FCGX_GetParam获取。
在地址栏 http://localhost/testenv.htm
假设我们输入的用户名和密码分别为abcd和efgh,提交表单之后,在我的机器上显示的结果如下:
COMSPEC=C:\WINDOWS\system32\cmd.exe
CONTENT_LENGTH=31
CONTENT_TYPE=application/x-www-form-urlencoded
DOCUMENT_ROOT=d:/chateaurt4/www
HTTP_ACCEPT=text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
HTTP_ACCEPT_CHARSET=gb2312,utf-8;q=0.7,*;q=0.7
HTTP_ACCEPT_ENCODING=gzip,deflate
HTTP_ACCEPT_LANGUAGE=zh-cn,zh;q=0.5
HTTP_CONNECTION=keep-alive
HTTP_HOST=localhost
HTTP_KEEP_ALIVE=300
HTTP_REFERER=http://localhost/testenv.htm
HTTP_USER_AGENT=Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3
PATH=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;D:\MicrosoftVisual Studio\Common\Tools\WinNT;D:\Microsoft VisualStudio\Common\MSDev98\Bin;D:\Microsoft VisualStudio\Common\Tools;D:\Microsoft VisualStudio\VC98\bin;D:\AppServ\Apache2.2\bin;D:\AppServ\php5;D:\AppServ\MySQL\bin
REMOTE_ADDR=127.0.0.1
REMOTE_PORT=1644
SCRIPT_FILENAME=d:/chateaurt4/www/cgi-bin/env.cgi
SERVER_ADDR=127.0.0.1
SERVER_ADMIN=who@where.net
SERVER_NAME=localhost
SERVER_PORT=80
SERVER_SIGNATURE=
Apache/1.3.33 Server at localhost Port 80
SERVER_SOFTWARE=Apache/1.3.33 (Win32)
SystemRoot=C:\WINDOWS
WINDIR=C:\WINDOWS
GATEWAY_INTERFACE=CGI/1.1
SERVER_PROTOCOL=HTTP/1.1
REQUEST_METHOD=POST
QUERY_STRING=
REQUEST_URI=/cgi-bin/env.cgi
SCRIPT_NAME=/cgi-bin/env.cgi
usr=abcd&pwd=efgh&submit=Submit
当然不同的机器,它输出的有些结果可能不一样。如果单纯为了输出环境变量,我们可以这样做:
#include <stdio.h>
int main (int argc, char **argv, char **envp)
{
char **var = envp;
while (*var)
printf ("%s \n",*var++);
return 0;
}
这里面得到的环境变量结果和CGI程序里面的结果差别比较大,因为一个是获得与web应用程序有关的环境变量,而一个获得的是系统的环境变量。