免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2204 | 回复: 4

向pty 输入功能键,为何输入和回显的内容不一致 [复制链接]

论坛徽章:
0
发表于 2009-11-19 14:59 |显示全部楼层
代码是作为 server的,目的是来自 $session 的client 输入交给 $pty 后,再从 $pty 读出发回给 client。
问题是:
输入普通的字符 client 端都能正常回显,但是如果输入功能键,如:
"<-"左箭头,抓包看到发送的是:1B 5B 44
但是,实际看到的 $pty 回送给 $session 的是:5E 5B 5B 44
试了多次后,看到的都是:
1B扔给 $pty 后,返回的是 5E
但 诸如四个方向键对应的keymap: 1B 5B 41/42/43/44,返回的都是 1B 5B 5B 41/42/43/44; 对 F1~ F4发送的是: 1b 5b 5b 41/42/43/44,但发送的是:1B 5B 5B 5B 41/42/43/44——这些功能键,5B都多了一个
这样子的话,client端,没法正常显示这些功能字符了,除非每次从 $pty 读到数据后,再做一次转化,但这很麻烦啊,因此每个字符都要处理,但字符对应的keymap长度又不固定,就实在不懂怎么处理了……

因为对 pty 才开始学习,只能猜测 pty 的字符编码就是如此规则的,但如果这样的话,如何和client端的字符编码进行转换了?请教各位了,或者推荐点参考资料也好啊,谢谢了~

        next unless my $session = $sock->accept;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my $pty = new IO::Pty or die "can't make pty, $!";
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defined( my $child = fork() ) or die "can't fork, $!";
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if( $child ) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defined( my $child_m = fork() ) or die "can't fork_m, $!";
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if( $child_m ) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my $buffer;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$| = 1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while( sysread( $session, $buffer, 1 ) ) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print $pty $buffer;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}else {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my $buffer_read_pty;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$| = 1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while( sysread( $pty, $buffer_read_pty, 1 ) ) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print "master got: " . ord( $buffer_read_pty ) . "\n";
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print $session $buffer_read_pty;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(0);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close $session;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} else {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

论坛徽章:
0
发表于 2009-11-19 21:30 |显示全部楼层
都快沉到第二页了,哪位大侠,指点下了,翻了下 unix 环境高级编程 的 伪终端 一章,也没找到可能的原因...

论坛徽章:
0
发表于 2009-11-20 11:06 |显示全部楼层
想看结果,帮顶一下,呵呵。

论坛徽章:
0
发表于 2009-11-20 14:12 |显示全部楼层
研究两天了,找到一点线索:对于功能键,只是 $pty 读入到的回显结果和来自 $session 的内容不一致,但是从设备 $tty 还是能够收到 和 $session 相同的内容的。
因此我想了两种方法尝试解决:
1、关闭 $tty 的回显,由  $tty 将读入到的内容,再次 print 给 $pty
2、尝试关闭 $tty 对除特殊功能键的回显

可惜的是,两种方法,我都没搞定……
方法 1,在上面的代码 print $pty $buffer; 时,虽然已经设置了 $| = 1,但是子进程 $tty 还是只有在收到回车符后,才会返回来自 $pty 的输出($tty 也用的 sysread()读的)。因此,这种方法,除非敲了回车符后,才会回显,这肯定不满足需求……

方法 2,几乎试遍了所有的 stty 的参数,$tty 都没法关掉特殊字符的回显,倒是看到了  echoctl echoke 等选项,试了下,没效果

继续等待哪位指点下,自己也继续研究去,有结果在来顶帖子!

论坛徽章:
0
发表于 2009-11-20 14:43 |显示全部楼层
哈哈,让我找到一个workaround,在某个blog上(博主连个网名都没写...)上找到一句话:
"当本地模式具有规范输入标志(ICANON)时, 输出数据按行拷贝给用户. 在接收到换行符(或者文件结束符c_cc[VEOF],行结束符c_cc[VEOL]和c_cc[VEOL2])之前, 可以使用编辑控制符完成简单的编辑. c_cc[VERASE]删除前一字符, c_cc[VKILL]删除整行, c_cc[VWERASE]删除前一单词"
我就关注到这点: ”当本地模式具有规范输入标志(ICANON)时, 输出数据按行拷贝给用户“,这也就是上面方法 1 不成功的原因了,所以我把 slave tty 设置为 -icanon ,方法 1 果然实现了按 char 读取字符,因此能够实时输出了,不足的是,这只是个规避方法,回显实际是编码实现的,tty 本身提供的一些终端功能,会损失不少

继续研究更好的方法了~
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP