thttpd中cgi使用的注意事项
1、cgi运行环境
在thttpd代码中,cgi是通过execve函数调用的
int execve(const char *filename, char *const argv[], char *const envp[]);
**execve()**执行程序由 filename决定。
filename必须是一个二进制的可执行文件,或者是一个脚本以#!格式开头的解释器参数参数。如果是后者,这个解释器必须是一个可执行的有效的路径名,但是不是脚本本身,它将调用解释器作为文件名。
argv是要调用的程序执行的参数序列,也就是我们要调用的程序需要传入的参数。
envp 同样也是参数序列,一般来说他是一种键值对的形式 key=value. 作为我们是新程序的环境。
所以,在调用cgi时如果运行了动态库,需要将动态库的环境包含在envp中,thttpd代码添加如下
//CGI_LD_LIBRARY_PATH即是运行的动态库环境,如果不定义该宏则是默认的动态路径
//(/opt/app/lib3rd:/opt/app/libsdk是我添加的动态库路径,并需要把#ifdef notdef屏蔽)
#ifdef notdef
#define CGI_LD_LIBRARY_PATH "/usr/local/lib:/usr/lib:/opt/app/lib3rd:/opt/app/libsdk"
#endif
2、cgi全局变量
如果cgi调用的函数中,包含了其他函数中的全局变量,那这个全局变量不生效,因为execve已经是一个独立的进程,和原本的进程没有关系了,所以全局变量也不会共用,即在a进程中全局变量的值,和execve进程中全局变量的值不相等
3、cgi设置http响应头信息(如cookie)
设置Cookie时,需在 printf(“Content-type:text/html\n\n”); 前设置,否则会当成response body
4、cgic获取post数据
简单的cgi获取post数据可以通过stdin来获取,参考
https://blog.csdn.net/shallnet/article/details/50896985
然而,cgic库中,stdin的数据已经被处理过了,因此程序内再次读取sdin时并不能读到数据
可以用cgic中的 cgiFormEntries 或者 cgiFormString
当知道表单的名称时,可以使用cgiFormString,不知道时可以使用cgiFormEntries
//cgiFormString获取数据
int cgiMain() {
char name[241];
char number[241];
cgiHeaderContentType("text/html");
fprintf(cgiOut, "<HTML><HEAD>\n");
fprintf(cgiOut, "<TITLE>My CGI</TITLE></HEAD>\n");
fprintf(cgiOut, "<BODY>");
cgiFormString("name", name, 241);
cgiFormString("number", number, 241);
fprintf(cgiOut, "<H1>%s</H1>",name);
fprintf(cgiOut, "<H1>%s</H1>",number);
fprintf(cgiOut, "</BODY>\n");
fprintf(cgiOut, "</HTML>\n");
return 0;
}
//cgiFormEntries 获取数据
char **form;
cgiFormEntries(&form);
5、thttpd中cgi代码解析
cgi_child( httpd_conn* hc )
{
int r;
char** argp;
char*