当前位置: 首页 > article >正文

在C语言中使用伪终端与bash交互

  1. 了解伪终端概念
    • 伪终端(PTY)由一对设备组成:主设备(master)和从设备(slave)。数据写入主设备会出现在从设备,反之亦然。这允许一个进程通过主设备与另一个进程(如bash)通过从设备进行通信。
  2. 相关函数
    • openpty:用于创建伪终端对。其原型为int openpty(int *amaster, int *aslave, char *name, const struct termios *termp, const struct winsize *winp)amasteraslave是指向文件描述符的指针,分别用于主设备和从设备;name可用于获取从设备的路径名;termp可用于设置终端属性;winp可用于设置窗口大小。
    • fork:创建一个新进程,子进程通常用于执行bash,父进程用于与伪终端主设备交互。
    • dup2:在子进程中用于将标准输入、输出和错误重定向到伪终端从设备。
    • writeread:用于在父进程中向伪终端主设备写入命令,并读取bash的输出。
  3. 示例代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <termios.h>
#include <string.h>

#define BUFFER_SIZE 1024

// 设置文件描述符为非阻塞模式
void set_nonblocking(int fd) {
    int flags = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

int main() {
    int master, slave;
    pid_t pid;
    char buffer[BUFFER_SIZE];
    struct termios oldtty, newtty;

    // 创建伪终端对
    if (openpty(&master, &slave, NULL, NULL, NULL) == -1) {
        perror("openpty");
        return 1;
    }

    // 保存当前终端设置
    tcgetattr(STDIN_FILENO, &oldtty);
    newtty = oldtty;
    // 设置终端为非规范模式
    newtty.c_lflag &= ~(ICANON | ECHO);
    // 设置终端属性
    tcsetattr(STDIN_FILENO, TCSANOW, &newtty);

    // 设置伪终端主设备为非阻塞模式
    set_nonblocking(master);

    // 创建子进程
    pid = fork();
    if (pid == -1) {
        perror("fork");
        close(master);
        close(slave);
        return 1;
    } else if (pid == 0) {
        // 子进程
        close(master);
        // 将标准输入、输出和错误重定向到伪终端从设备
        if (dup2(slave, STDIN_FILENO) == -1) {
            perror("dup2 stdin");
            return 1;
        }
        if (dup2(slave, STDOUT_FILENO) == -1) {
            perror("dup2 stdout");
            return 1;
        }
        if (dup2(slave, STDERR_FILENO) == -1) {
            perror("dup2 stderr");
            return 1;
        }
        close(slave);

        // 启动bash
        execl("/bin/bash", "bash", (char *)NULL);
        perror("execl");
        return 1;
    } else {
        // 父进程
        close(slave);

        // 向bash发送命令
        const char *command = "ls\n";
        if (write(master, command, strlen(command))!= strlen(command)) {
            perror("write");
        }

        // 读取bash的输出
        ssize_t bytes_read;
        while ((bytes_read = read(master, buffer, sizeof(buffer) - 1)) > 0) {
            buffer[bytes_read] = '\0';
            printf("%s", buffer);
        }

        // 等待子进程结束
        waitpid(pid, NULL, 0);

        // 恢复终端设置
        tcsetattr(STDIN_FILENO, TCSANOW, &oldtty);

        close(master);
    }

    return 0;
}
  1. 代码解释
    • 创建伪终端对:使用openpty创建伪终端主设备master和从设备slave
    • 终端设置:保存当前终端设置oldtty,并修改为非规范模式newtty,这样可以实时读取输入而无需等待换行符。
    • 设置非阻塞模式:将伪终端主设备设置为非阻塞模式,以便在读取输出时不会阻塞。
    • 进程创建:通过fork创建子进程,子进程执行bash,父进程与伪终端主设备交互。
    • 子进程操作:关闭master,将标准输入、输出和错误重定向到slave,然后执行bash
    • 父进程操作:关闭slave,向master写入命令(如ls\n),循环读取并打印bash的输出,等待子进程结束,最后恢复终端设置。

这样,通过上述代码,你可以在C语言程序中使用伪终端与bash进行交互。


http://www.kler.cn/a/465407.html

相关文章:

  • PHP 使用集合 处理复杂数据 提升开发效率
  • 《GICv3_Software_Overview_Official_Release_B》学习笔记
  • HTML——73.button按钮
  • 算法——回溯模式
  • GXUOJ-算法-补题:22级《算法设计与分析》第一次课堂练习
  • python openyxl 用法 教程
  • MATLAB 车牌自动识别系统设计 图像分割与图像增强方法 车牌识别
  • linux网络 | 深度学习http的相关概念
  • k8s基础(2)—Kubernetes-Namespace
  • JAVA学习笔记_Redis进阶
  • 【数据仓库金典面试题】—— 包含详细解答
  • SQL Server导出和导入可选的数据库表和数据,以sql脚本形式
  • UML之关联
  • 【数据结构】双向循环链表的使用
  • springboot集成阿里云短信服务
  • CentOS — 目录管理
  • 瑞_Linux中部署配置Java服务并设置开机自启动
  • 软件工程期末大复习(三)
  • 图像相似性计算
  • 小程序用户体验优化策略:提升用户留存与活跃度
  • 关于电话的正则表达式
  • PyTorch Instance Normalization介绍
  • 第81期 | GPTSecurity周报
  • 【前端,TypeScript】TypeScript速成(六):函数
  • 自动化办公 | 根据成绩进行自动评级
  • 昆仑万维大数据面试题及参考答案