gpt4 book ai didi

c++ - 在 pty 下运行命令时出现双回显

转载 作者:行者123 更新时间:2023-12-01 23:13:21 33 4
gpt4 key购买 nike

我正在编写一个程序来创建 pty,然后 fork 并执行 ssh以 pty 的从属端作为其 stdin 的命令。完整的源代码在这里。

using namespace std;
#include <iostream>
#include <unistd.h>
#include <fcntl.h>

int main() {

int fd = posix_openpt(O_RDWR);
grantpt(fd);
unlockpt(fd);

pid_t pid = fork();

if (pid == 0) { //slave

freopen(ptsname(fd), "r", stdin);

execlp("ssh", "ssh", "user@192.168.11.40", NULL);

} else { //master

FILE *f = fdopen(fd, "w");
string buf;

while (true) {

getline(cin, buf);

if (!cin) {
break;
}

fprintf(f, "%s\n", buf.c_str());

}

}

}

执行此程序并输入 echo hello 后(和换行符),子命令在其输出之前重新发送我的输入,从而复制我的输入行:

~ $ echo hello
echo hello #duplication
hello

~ $

我认为这是因为 pty 的行为几乎与普通终端相同。如果我添加 freopen("log.txt", "w", stdout);"并输入相同的命令,我得到的只是

echo hello #This is printed because I typed it.

以及 log.txt 的内容是这样的:

~ $ echo hello #I think this is printed because a pty simulates input.
hello

~ $

如何避免重复?

<小时/>

这可以实现吗?

我知道这是可以实现的,但不知道如何实现。事实上,rlwrap命令的行为与我的程序相同,只是它没有任何重复:

~/somedir $ rlwrap ssh user@192.168.11.40
~ $ echo hello
hello

~ $

我正在阅读rlwrap的源代码现在,但尚未了解其实现。

<小时/>

补充

按照 this question 中的建议(对我来说,不是答案,但OP很有帮助。),取消设置 ECHO终端标志禁用双重回显。就我而言,将此片段添加到从属 block 解决了问题。

termios terminal_attribute;
int fd_slave = fileno(fopen(ptsname(fd_master), "r"));
tcgetattr(fd_slave, &terminal_attribute);
terminal_attribute.c_lflag &= ~ECHO;
tcsetattr(fd_slave, TCSANOW, &terminal_attribute);

需要注意的是,这不是rlwrap做。据我测试rlwrap <command>永远不会为任何 <command> 重复其输入行然而,我的程序对某些 <command> 回显两次s。例如,

~ $ echo hello
hello #no duplication

~ $ /usr/bin/wolfram
Mathematica 12.0.1 Kernel for Linux ARM (32-bit)
Copyright 1988-2019 Wolfram Research, Inc.

In[1]:= 3 + 4
3 + 4 #duplication (my program makes this while `rlwrap` doesn't)

Out[1]= 7

In[2]:=

这是因为 <command> (ssh 当我远程运行 wolfram 时)重新启用回显?无论如何,我应该继续阅读rlwrap的源代码.

最佳答案

正如您已经观察到的,在子进程调用 exec() 之后,从属端的终端标志不再受您的控制,并且子进程可能(并且经常会)重新启用 echo 。这意味着在调用 exec 之前更改子进程中的终端标志并没有多大用处。

两者rlwraprlfe以自己的(不同的)方式解决问题:

无论您使用什么方法,您都必须知道您的输入是已经(在 rlfe 的情况下)还是将会(在 rlwrap 中)的情况)也得到了回应。 rlwrap 至少通过在父进程中关闭 pty 的从属端,然后观察其终端设置(在本例中为 ECHO 位在其 c_lflag 中)来了解从机是否会回显。

当然,所有这些都相当麻烦。 rlfe 方法可能更简单,因为它不需要使用 readline 库,并且您可以简单地 strcmp() 接收到的输出与您刚刚发送的输入(只有在cat命令禁用其输入回显的不可能情况下才会出错)

关于c++ - 在 pty 下运行命令时出现双回显,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59007528/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com