当输入命令时 cat | tr a-z A-Z
(或只是 tr a-z A-Z
)我希望终端将我的输入逐行发送到 tr
的标准输入,并且对于每个我输入的行,看到它以所有大写字母显示,并重复这个直到我用 ^D 关闭标准输入。
我想在 C 中复制此行为并在 fork()
ed 子级中使用 exec()
调用执行 tr
,并通过 dup2()
的 pipe()
文件描述符开始与它交互。我已经成功地以这种方式打开管道,并以任何一种方式发送数据,但我不知道如何对同一个命令重复执行这两种操作。就像现在一样,我必须在写入命令输入管道的文件描述符后close()
,然后才能开始读取它返回的大写字母。但是在返回第一行之后,write()
当然将不再工作,因为该文件描述符现在是 EBADF
。
int input_fd[2], output_fd[2];
pipe2(input_fd, O_CLOEXEC);
pipe2(output_fd, O_CLOEXEC);
char*buf = new char[1024];
strncpy(buf, "Hello, world!\n", 15);
int pid = fork();
if(pid < 0) {
exit(EXIT_FAILURE);
} else if(pid == 0) {
close(input_fd[1]);
close(output_fd[0]);
int err = dup2(input_fd[0], STDIN_FILENO);
err = dup2(output_fd[1], STDOUT_FILENO);
execlp("/usr/bin/tr", "/usr/bin/tr", "a-z", "A-Z", 0);
// (error handling omitted)
}
close(input_fd[0]);
close(output_fd[1]);
int err;
err = write(input_fd[1], buf, 15);
close(input_fd[1]); // <--- how else to terminate the input?
err = read(output_fd[0], buf, strlen(buf));
std::cout << buf << std::endl;
strncpy(buf, "xxxxxxx", 8);
err = write(input_fd[1], buf, strlen(buf)); // <--- EBADF, because closed
我一直在寻找一种方法来做到这一点,以至于质疑它的可能性,但 cat | tr
正在运行 我能够验证 tr
的 PID 在收到每一行新输入后都没有改变。我已经阅读了所有文档和很多问题,但还没有找到这个问题的答案。
这能以一般方式完成吗?或者 bash 只是在玩魔术?
正如用户 n.m.
所建议的,打开一个伪终端允许我逐行与外部控制台程序进行对话。
谢谢!
我是一名优秀的程序员,十分优秀!