首页 > 代码库 > CGI原理解析系列之三----CGI如何完整获取WEB服务器数据

CGI原理解析系列之三----CGI如何完整获取WEB服务器数据

 

//模拟了服务器端 httpd 进程启动 cgi的过程,
//完整展现了 get,post 方法支持
//gcc -g httpd_all.c -o httpd_all.ums;


#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>

#define CGI_NAME "get_post.ums"
#define REQUEST_METHOD "REQUEST_METHOD=POST"
#define REQUEST_PARAMETER "myname=huangzhihui"

int main(int argc, char *argv[])
{
 int parent[2],child[2];
 if (pipe(parent) < 0)
 {
  printf("create pipe fail.\n");
 }
 
 if (pipe(child) < 0)
 {
  close(parent[0]);
  close(parent[1]);
  printf("create pipe fail.\n");
 }

 pid_t pid;
 if ((pid = fork()) < 0)
 {
  printf("fork fail.\n");
 }
 else if (pid > 0)
 {
  /* parent */
  //关闭多余的句柄,构造单一功能读写通道
  close(parent[0]);
  close(child[1]);
  
  //模拟向 CGI 传送数据
  ssize_t length = strlen(REQUEST_PARAMETER);
  if (write(parent[1], REQUEST_PARAMETER, length) != length)
  {
   printf("write error to pipe\n");
  }
  close(parent[1]);
  
  //等待CGI子进程完全把数据读取后写入,
  //实际情况应该是使用select 或者 epoll 监听
  //usleep(1000);

  //模拟接收 CGI 应答的数据  
  char buff[256] = { 0 };
  length = read(child[0], buff, sizeof(buff));
  if (length <= 0)
  {
   printf("read error from pipe\n");
  }
  else
  {
   printf("pid %d read data=http://www.mamicode.com/%u/n%s",getpid(),length, buff);
  }
  close(child[0]);

  if (waitpid(pid, NULL, 0) < 0)
  {
   printf("waitpid error\n");
  }
  exit(0);
 }
 else
 {
  /* child */
  
  //关闭多余的句柄,构造单一功能读写通道
  close(parent[1]);
  close(child[0]);
  
  //重定向管道的输入端到标准输入
  if (parent[0] != STDIN_FILENO)
  {
   if (dup2(parent[0], STDIN_FILENO) != STDIN_FILENO)
   {
    printf("dup2 error to stdin");
   }
   close(parent[0]);
  }

  //重定向管道的输出端到标准输出
  if (child[1] != STDOUT_FILENO)
  {
   if (dup2(child[1], STDOUT_FILENO) != STDOUT_FILENO)
   {
    printf("dup2 error to stdout");
   }
   close(child[1]);
  }

  //覆盖进程空间,设置CGI环境变量
  char content_length[128] = { 0 };
  sprintf(content_length, "CONTENT_LENGTH=%u", strlen(REQUEST_PARAMETER));
  char *exec_argv[3] = { REQUEST_METHOD, content_length };
  if (execve(CGI_NAME,argv,exec_argv) < 0)
  {
   printf("execl error for %s", CGI_NAME);
  }
  exit(0);
 }
 exit(0);
}

 

CGI原理解析系列之三----CGI如何完整获取WEB服务器数据