#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 fd[2];

    if (pipe(fd) < 0)

    {

        printf("create pipe fail.\n");

    }



    pid_t pid;

    if ((pid = fork()) < 0)

    {

        printf("fork fail.\n");

    }

    else if (pid > 0)

    {

        /* parent */                

        //模拟向 CGI 传送数据

        ssize_t length = strlen(REQUEST_PARAMETER);

        if (write(fd[1], REQUEST_PARAMETER, length) != length)

        {

            printf("write error to pipe\n");

        }

        close(fd[1]);

        

        //等待CGI子进程全然把数据读取后写入,

        //实际情况应该是使用select 或者 epoll 监听

        usleep(1000);



        //模拟接收 CGI 应答的数据        

        char buff[256] = { 0 };

        length = read(fd[0], buff, sizeof(buff));

        if (length <= 0)

        {

            printf("read error from pipe\n");

        }

        else

        {

            printf("pid %d read data=%u,%s\n",getpid(),length, buff);

        }

        close(fd[0]);



        if (waitpid(pid, NULL, 0) < 0)

        {

            printf("waitpid error\n");

        }

        exit(0);

    }

    else

    {

        /* child */

       //重定向管道的输入端到标准输入

        if (fd[0] != STDIN_FILENO)

        {

            if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)

            {

                printf("dup2 error to stdin");

            }

            close(fd[0]);

        }



        //重定向管道的输出端到标准输出

        if (fd[1] != STDOUT_FILENO)

        {

            if (dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO)

            {

                printf("dup2 error to stdout");

            }

            close(fd[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);

}

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHpoeHh4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

CGI原理解析之二------WEB服务和CGI交互数据的更多相关文章

  1. Web APi之过滤器执行过程原理解析【二】(十一)

    前言 上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要.这一节我们简单将讲述在Action方法上.控制器上.全局上以及授 ...

  2. CGI原理解析系列之中的一个----CGI怎样获取WEBserver数据

    //gcc get_post.c -o get_post.ums; #include <stdio.h> #include <stdlib.h> #include <un ...

  3. Spring源码:IOC原理解析(二)

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 接着上一章节的内容,我们来分析当new一个FileSystemXmlApplicationContext对象的时候,spring到底做了那 ...

  4. SpringBoot启动流程原理解析(二)

    在上一章我们分析了SpingBoot启动流程中实例化SpingApplication的过程. return new SpringApplication(primarySources).run(args ...

  5. RocketMQ架构原理解析(二):消息存储

    一.概述 由前文可知,RocketMQ有几个非常重要的概念: broker 服务端,负责存储.收发消息 producer 客户端1,负责产生消息 consumer 客服端2,负责消费消息 既然是消息队 ...

  6. kprobe原理解析(二)

    上一篇文章和大家简要说明了下kprobe到底应该怎样用,那么现在我们就揭开kprobe神秘的面纱,刨根问底,一睹kprobe的庐山真面目. kprobe的工作过程大致如下: 1)注册kprobe.注册 ...

  7. 骨骼蒙皮动画(Skinned Mesh)的原理解析(二)

    http://blog.csdn.net/jimoshuicao/article/details/9283071 2)蒙皮信息和蒙皮过程 2-1)Skin info的定义 上文曾讨论过,Skinned ...

  8. APPcrawler基础原理解析及使用

    一.背景 一年前,我们一直在用monkey进行Android 的稳定性测试 ,主要目的就是为了测试app 是否会产生Crash,是否会有ANR,页面错误等问题,在monkey测试过程中,实现了脱离Ca ...

  9. 如何测试Web服务.1

    一.什么是web服务  web服务在简单术语中可被定义为通过安装了特定设备或服务器到另一装置或客户端应用程序通过WWW彼此通信后的应用程序(万维网)提供的服务. Web服务通常在计算机网络的应用层上使 ...

随机推荐

  1. C# 中编写函数式代码

    http://www.dotnetcurry.com/csharp/1384/functional-programming-fsharp-for-csharp-developers 写给 C# 开发人 ...

  2. hysbz 2243 染色(树链剖分)

    题目链接:hysbz 2243 染色 题目大意:略. 解题思路:树链剖分+线段树的区间合并,可是区间合并比較简单,节点仅仅要记录左右端点的颜色就可以. #include <cstdio> ...

  3. 让人难过的 openssl_pkcs7_encrypt

    让人难过的 openssl_pkcs7_encrypt 用PHP.NET的范例,没有加密结果,也没有报错信息,而openssl_pkcs7_sign()函数则返回 error opening inpu ...

  4. Redis-消费模式

    一 . 两种模式简介 发布消息通常有两种模式:队列模式(queuing)和发布订阅模式(qublish-subscribe).队列模式中,consumers可以同时从服务端读取消息,每个消息纸杯其中一 ...

  5. Linux常用运维命令小结

    1. 空设备文件以及标准输入输出 /dev/null 表示空设备文件 0 表示stdin标准输入 1 表示stdout标准输出 2 表示stderr标准错误 2>&1 这里有两种解释:将 ...

  6. JS里面的indexOf()函数

    stringObject.indexOf(searchvalue,formindex); searchvalue在字符串首次出现的位置,位置是从0开始算的.

  7. Makefile的问题

    注意包含路径的变量,可能会带有空格而使得运行失败 直接定义:DEBUG  = false后面引用需要使用 $(DEBUG) 或者set  DEBUG  $(DEBUG)之后就可以直接引用了

  8. Java Web学习总结(16)——JSP的九个内置对象

    一.JSP运行原理 每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理.JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet ...

  9. 位数(digits)的处理

    主要针对:二进制表示法,以及十进制表示法: 1. 获取位数 已知该数 n 采用十进制进行表示 二进制形式的位数:⌊log2n⌋+1 十进制形式的位数:⌊log10n⌋+1 2. 截断(保留前/后 m ...

  10. StringBuilder和String的区别

      使用   StringBuilder 语言 C# String   对象是不可改变的.每次使用   System.String   类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为 ...