popen:拦截用户的输入

时间:2016-08-01 16:13:09

标签: c popen

我有一个运行bcpopen()的代码。我可以拦截计算器的输出并在其前面添加"输出="文本。但是,如何拦截用户写入bc的内容?

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    FILE *in;
    char buff[512];
    if(!(in = popen("bc", "r"))){
        exit(1);
    }
    while(fgets(buff, sizeof(buff), in)!=NULL){
        printf("Output = %s", buff);
    }
    pclose(in);
    return 0;
}

3 个答案:

答案 0 :(得分:0)

您可以将bcecho与管道合并:echo '12*4' | bc

输入12*4的示例:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void) {
    FILE *in;
    char buff[512];
    char cmd[512];

    while (fgets(buff, sizeof(buff), stdin)!=NULL){
        strcpy(cmd, "echo '");
        strcat(cmd, buff);
        strcat(cmd, "' | bc");
        if(!(in = popen(cmd, "r"))){
            exit(1);
        }
        fgets(buff, sizeof(buff), in);
        printf("output:%s", buff);
    }
    pclose(in);
    return 0;
}

输出:

david@debian:~$ ./demo
12*4
output:48

答案 1 :(得分:0)

您需要使用pipe()fork/exec()。但是,手动管道非常复杂:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void) {
    int write_pipe[2], read_pipe[2];
    pipe(read_pipe); pipe(write_pipe);

    #define PARENT_READ read_pipe[0]
    #define CHILD_WRITE read_pipe[1]
    #define CHILD_READ  write_pipe[0]
    #define PARENT_WRITE    write_pipe[1]

    int child = fork();
    if (child == 0) { /* in child */
        close(PARENT_WRITE);
        close(PARENT_READ);

        dup2(CHILD_READ, 0); close(CHILD_READ);
        dup2(CHILD_WRITE, 1); close(CHILD_WRITE);

        execl("/usr/bin/bc", "/usr/bin/bc");
    } else { /* in parent */
        close(CHILD_READ);
        close(CHILD_WRITE);

        write(PARENT_WRITE, "2+3\n", 4);

        char buff[512];
        int output_len=read(PARENT_READ, buff, sizeof(buff));
        write(1, buff, output_len);
        close(PARENT_READ);
    }
    return 0;
}

答案 2 :(得分:0)

您要做的是启动子流程,然后同时启动:

  • 当标准输入上发生活动时,在将该输入传递给子进程之前对该输入执行一些函数。
  • 当子进程输出发生活动时,在将该输出传递给标准输出之前,对该输出执行一些函数。

允许您等待两个句柄上的活动的系统调用称为poll,但在我们这样做之前,我们需要创建句柄并启动子进程:

int a[2], b[2];
if(pipe(a)==-1)abort(); // for communicating with subprocess input
if(pipe(b)==-1)abort(); // for communicating with subprocess output
switch(fork()) {
case -1: abort();
case 0: dup2(a[0],0), dup2(b[1],1), execlp("/usr/bin/bc", "bc", 0); exit(1);
};

注意pipe的工作原理:写入fildes [1]的数据出现在(即可以读取)fildes [0]上。这意味着我们想从标准中读取输出我们的子进程b[0]并写入子进程a[1]的标准输入。

在我们这样做之前,我们可以使用poll指令等待标准输入(fd#0)或子进程输出(b [0])上的活动:

for(;;) {
  struct pollfd p[2]={0};
  p[0].fd = 0; p[1].fd = b[0];
  p[0].events = p[1].events = POLLIN;
  while (poll(p,2,-1) <= 0);

此时,至少有一个文件描述符存在活动。您可以通过检查.revents成员来查看哪一个。

  if(p[0].revents & POLLIN) {
    r = read(0, buffer, sizeof(buffer));
    write(a[1], buffer, r); // check for errors, or perhaps modify buffer
  }
  if(p[1].revents & POLLIN) {
    r = read(b[0], buffer, sizeof(buffer));
    write(1, buffer, r); // check for errors, or perhaps modify buffer
  }

特别注意我们使用成员a[1]b[0]中的成员} read()到子进程标准输入(0)和标准输出(1)。

此时你可以循环回来再次轮询:

0

断开连接(如EOF,程序崩溃等)将显示为break;返回<!-- Mobile Links --> <a href="#" id="mobile-menu-icon" class="mobile-menu-icon show-for-custom-down" title="<?php esc_attr_e('Mobile Menu', 'punjaban' ); ?>"><span class="lines"></span></a> <a href="#" class="mobile-search-icon" title="<?php esc_attr_e('Search', 'punjaban' ); ?>"> </a> <!-- Mobile Menu --> <?php register_nav_menus( array( 'mobile-primary-menu' => 'Mobile Navigation Menu', ) ); wp_nav_menu( array( 'theme_location' => 'primary', 'container_class' => 'mobile-primary-menu' ) ); ?> ,因此请仔细观察此情况,如果需要请注意<!-- Mobile Links --> <a href="#" id="mobile-menu-icon" class="mobile-menu-icon show-for-custom-down" title="Mobile Menu"><span class="lines"></span></a> <a href="#" class="mobile-search-icon" title="Search"> </a> <!-- Mobile Menu --> <div class="mobile-primary-menu"><ul id="menu-primary-menu" class="menu"><li id="menu-item-21" class="search-icon menu-item menu-item-type-custom menu-item-object-custom menu-item-21"><a rel="nofollow" href="#">Search</a></li> <li id="menu-item-407" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-407"><a rel="nofollow" href="/shop">SHOP</a></li> <li id="menu-item-239" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-239"><a rel="nofollow" href="/recipes">RECIPES</a></li> <li id="menu-item-17" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-17"><a rel="nofollow" href="/stockist">STOCKISTS</a></li> <li id="menu-item-598" class="fourth-child menu-item menu-item-type-post_type menu-item-object-page menu-item-598"><a rel="nofollow" href="http://www.punjaban.co.uk/our-story/">OUR STORY</a></li> <li id="menu-item-19" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-19"><a rel="nofollow" href="/blog">BLOG</a></li> <li id="menu-item-300" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-300"><a rel="nofollow" href="http://www.punjaban.co.uk/contact/">CONTACT</a></li> </ul></div>