c - 写入 `forkpty`子进程: `less` pager

标签 c ipc execvp pty

我正在尝试使用forkptyexecvpless分页程序,然后从父进程中写入一些文本,这样子 less 进程将其作为其输入的方式。

我一直在研究如何实现这一点,但我无法使用 forkpty 来实现某些功能,而我却使用 pipe > fork

发生的情况是我看不到任何输出,然后程序正常退出。

编辑:我注意到,如果我在 forkpty 之后从 master 读取内容,我会看到 less 中的“缺少文件名(“less --help”寻求帮助)” ,但是怎么会$ echo test | less,那么工作正常吗?更改 exec_argv 以将 "-" 传递给 less 仍然存在相同的原始问题(无输出)。

我是否遗漏了一些明显的东西?

使用pipefork的工作代码

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

int main() {
    int read_write_fds[2];

    if (pipe(read_write_fds) == -1) {
        perror("pipe");
        return EXIT_FAILURE;
    }

    pid_t pid = fork();

    if (pid == -1) {
        perror("fork");
        return EXIT_FAILURE;
    }

    if (!pid) {
        if (close(read_write_fds[1]) == -1) {
            perror("CHILD: close write");
            return EXIT_FAILURE;
        }
        if (dup2(read_write_fds[0], STDIN_FILENO) == -1) {
            perror("CHILD: dup2 read STDIN_FILENO");
            return EXIT_FAILURE;
        }
        if (close(read_write_fds[0]) == -1) {
            perror("CHILD: close read");
            return EXIT_FAILURE;
        }

        char* exec_argv[] = {"less", NULL};
        execvp(exec_argv[0], exec_argv);
        perror("CHILD: execvp");
        return EXIT_FAILURE;
    }

    if (close(read_write_fds[0]) == -1) {
        perror("PARENT: close read");
        return EXIT_FAILURE;
    }

    char text[] = "Hello, world!\n";
    char* text_ptr = text;
    size_t bytes_left = sizeof(text) - 1;

    while (bytes_left > 0) {
        ssize_t bytes_written = write(read_write_fds[1], text_ptr, bytes_left);

        if (bytes_written == -1) {
            perror("PARENT: write");
            return EXIT_FAILURE;
        }

        bytes_left -= bytes_written;
        text_ptr += bytes_written;
    }

    if (close(read_write_fds[1]) == -1) {
        perror("PARENT: close write");
        return EXIT_FAILURE;
    }
    if (waitpid(pid, NULL, 0) == -1) {
        perror("PARENT: waitpid");
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

使用forkpty的非工作代码

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

int main() {
    int master;
    pid_t pid = forkpty(&master, NULL, NULL, NULL);

    if (pid == -1) {
        perror("forkpty");
        return EXIT_FAILURE;
    }

    if (!pid) {
        char* exec_argv[] = {"less", NULL};
        execvp(exec_argv[0], exec_argv);
        perror("CHILD: execvp");
        return EXIT_FAILURE;
    }

    char text[] = "Hello, world!\n";
    char* text_ptr = text;
    size_t bytes_left = sizeof(text) - 1;

    while (bytes_left > 0) {
        ssize_t bytes_written = write(master, text_ptr, bytes_left);

        if (bytes_written == -1) {
            perror("PARENT: write");
            return EXIT_FAILURE;
        }

        bytes_left -= bytes_written;
        text_ptr += bytes_written;
    }

    if (close(master) == -1) {
        perror("PARENT: close");
        return EXIT_FAILURE;
    }

    if (waitpid(pid, NULL, 0) == -1) {
        perror("PARENT: waitpid");
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

最佳答案

(小问题:在 fork() 之后的子进程中,您应该使用 _exit()。)

您在此处看不到输出的原因是因为子进程的 stdin、stdout 和 stderr 都附加到新的 PTY。您需要从 master 读取数据并对数据执行某些操作。

关于c - 写入 `forkpty`子进程: `less` pager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42881519/

相关文章:

multithreading - 如何从clojure中的子进程执行非阻塞读取标准输出?

linux - 如果找不到文件,如何使 find -name 返回错误

objective-c - 从传递 float 组的 C 函数调用 Objective C 函数

使用管道、重定向和文件流与子进程通信

c - c中的指针操作

我可以在 fork()==0 中使用 wait(NULL) 吗?

java - Windows 中 Java 和 C 之间的任何 IPC 机制——不需要套接字

linux - 几个相同进程之间的IPC通信

c - 在 main 中等待 execvp

c++ - execvp( command.argv[0], command.argv) 后程序停止