shell_proxy最小shell代理示例

19 阅读1分钟
// select_bash.c

// gcc select_bash.c -o select_bash

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/select.h>

#include <sys/wait.h>

  


int main(void)

{

    int to_child[2], to_parent[2];

    pipe(to_child);

    pipe(to_parent);

  


    pid_t pid = fork();

    if (pid == 0) {                       /* 子进程 */

        dup2(to_child[0],  STDIN_FILENO);

        dup2(to_parent[1], STDOUT_FILENO);

        dup2(to_parent[1], STDERR_FILENO);

        close(to_child[0]); close(to_child[1]);

        close(to_parent[0]); close(to_parent[1]);

        execl("/bin/bash", "bash", "--norc", NULL);

        _exit(127);

    }

  


    /* 父进程 */

    close(to_child[0]);

    close(to_parent[1]);

  


    int bash_out = to_parent[0];   /* 读 bash 输出 */

    int bash_in  = to_child[1];    /* 写给 bash */

  


    fd_set rfds;

    char buf[512];

    while (1) {

        FD_ZERO(&rfds);

        FD_SET(STDIN_FILENO, &rfds);   /* 监听键盘 */

        FD_SET(bash_out,     &rfds);   /* 监听 bash 输出 */

        int maxfd = (bash_out > STDIN_FILENO ? bash_out : STDIN_FILENO) + 1;

  


        if (select(maxfd, &rfds, NULL, NULL, NULL) < 0) break;

  


        /* 1. 键盘可读 → 写给 bash */

        if (FD_ISSET(STDIN_FILENO, &rfds)) {

            ssize_t n = read(STDIN_FILENO, buf, sizeof buf);

            if (n <= 0) break;

            write(bash_in, buf, n);    // 原样转发

        }

  


        /* 2. bash 有输出 → 打印到屏幕 */

        if (FD_ISSET(bash_out, &rfds)) {

            ssize_t n = read(bash_out, buf, sizeof buf);

            if (n <= 0) break;         // bash 退出

            write(STDOUT_FILENO, buf, n);

        }

    }

  


    close(bash_in);

    close(bash_out);

    waitpid(pid, NULL, 0);

    return 0;

}