加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

bash – 一个不起眼的文件:记录VT100’软包裹’转义序列?

发布时间:2020-12-15 22:35:35 所属栏目:安全 来源:网络整理
导读:当通过SSH连接到远程BASH会话(终端类型设置为vt100)时,当光标到达列80时,控制台命令行将进行软包装. 我想要发现的是 space回车此时发送的序列记录在任何地方? 例如,发送以下字符串 std::string str = "0123456789" // 1 "0123456789" "0123456789" // 3 "01
当通过SSH连接到远程BASH会话(终端类型设置为vt100)时,当光标到达列80时,控制台命令行将进行软包装.

我想要发现的是< space><回车>此时发送的序列记录在任何地方?

例如,发送以下字符串

std::string str = "0123456789"  // 1
                        "0123456789"
                        "0123456789"    // 3
                        "0123456789"
                        "0123456789"    // 5
                        "012345678 9"
                        "0123456789_"   // 7
                        "0123456789"
                        "0";

从主机获取以下响应(Linux Mint发生)

01234567890123456789012345678901234567890123456789012345678<WS><WS><CR>90123456789_01234567890

解决方法

观察到的行为实际上不是bash的一部分;相反,它是readline库行为的一部分.如果你只是简单地使用echo(内置bash)来输出足够的文本来强制自动换行,那么它就不会发生,如果bash产生的错误信息比控制台宽,也不会发生. (例如,尝试使用超过80个字符的参数与任何现有文件不对应的命令.)

所以它不是官方的“软包装序列”,也不是任何标准的一部分.相反,它是与控制台显示器管理相关的许多恼人问题之一的实用解决方案.

换行的终端实现存在歧义:

>在最右边的位置插入一个字符后,终端会换行.
>终端在发送下一个字符之前进行换行.

因此,无法在最后一列位置之后可靠地发送换行符.如果终端已经包装(上面的选项1),那么换行将创建一个额外的空白行.否则(选项2),以下换行将被“吃掉”.

目前,几乎所有终端都遵循选项2的一些变体,这是DEC VT-100终端的行为.在terminfo终端描述数据库的词汇表中,这称为xenl:“eat-newline-glitch”.

实际上有两个可能的选项2的子变量.在VT-100(和xterm)实际实现的一个子变量中,光标最后在行的末尾处于异常状态;实际上,它是屏幕外的一个字符位置,因此您仍然可以将光标退回到同一行.其他历史终端“吃”换行符,但无论如何都将光标定位在下一行的开头,这样就不可能有退格. (除非终端具有bw功能.)

这为需要准确跟踪光标位置的程序带来了问题,即使对于回显输入这样看似简单的应用程序也是如此. (显然,回显输入的最简单方法是让终端自己执行此操作,但这样就无法实现额外的控制字符,如制表符完成.)假设用户输入的文本一直到右边距,然后键入退格字符,用于删除键入的最后一个字符.通常,您可以通过输出cub1(向左移动1)代码然后输出el(清除到行尾)来实现退格删除. (如果删除位于一行的中间,则更复杂,但原理是相同的.)

但是,如果光标可能位于下一行的开头,则无效.如果您知道光标位于下一个的开头,则可以在执行el之前向上移动然后向右移动,但如果光标仍在同一行上,则无法工作.

从历史上看,被认为是“正确”的是强制光标强制光标到下一行. (以下引用来自ncurses发行版中找到的文件terminfo.src.我不知道是谁编写的或何时编写):

# Note that the <xenl> glitch in vt100 is not quite the same as on the Concept,# since the cursor is left in a different position while in the
# weird state (concept at beginning of next line,vt100 at end
# of this line) so all versions of vi before 3.7 don't handle
# <xenl> right on vt100. The correct way to handle <xenl> is when
# you output the char in column 80,immediately output CR LF
# and then assume you are in column 1 of the next line. If <xenl>
# is on,am should be on too.

但还有另一种方法可以处理这个问题,甚至不需要你知道终端是否有xenl“毛刺”:输出一个空格字符,之后终端肯定会有换行,然后返回最左边的列.

事实证明,如果终端仿真器是xterm(可能还??有其他类似的仿真器),这个技巧还有另外一个好处,它允许你通过双击它来选择一个“单词”.如果自动换行发生在一个单词的中间,那么即使它被分成两行,你仍然可以选择整个单词,这将是理想的选择.如果你按照上面的terminfo文件中的建议,那么xterm将(非常合理地)将拆分单词视为两个单词,因为它们之间有明确的换行符.但是如果让终端自动换行,xterm会将结果视为一个单词. (尽管有空格字符的输出,但它可以做到这一点,大概是因为空格字符被覆盖了.)

简而言之,SPCR序列绝不是VT100终端的标准化功能.相反,它是对终端描述的特定特征与特定(和公共)终端仿真器的观察到的行为相结合的实用响应.这些代码的变体可以在各种代码库中找到,虽然据我所知它不是任何教科书或正式文档的一部分,但它肯定是终端处理民间文件的一部分[注2].

在readline的情况下,你会发现comment in the code比这个答案更具电信性:[注1]

/* If we're at the right edge of a terminal that supports xn,we're
     ready to wrap around,so do so.  This fixes problems with knowing
     the exact cursor position and cut-and-paste with certain terminal
     emulators.  In this calculation,TEMP is the physical screen
     position of the cursor. */

(xn是xenl的缩写形式.)

笔记

>当我输入这个答案时,评论位于git存储库当前视图中display.c的第1326行.在将来的版本中,它可能位于不同的行号,因此提供的链接将不起作用.如果您发现它已更改,请随时更正链接.
>在这个答案的原始版本中,我将此程序描述为“终端处理民间传说的一部分”,其中我使用“民俗”一词来描述从程序员传递给程序员的知识,而不是作为学术文章的一部分.和国际标准.虽然“民间传说”经常被用来带有负面含义,但我在没有这种偏见的情况下使用它. “绝杀”(根据wiktionary)提到“关于特定主题的所有事实和传统,这些事实和传统是通过教育或经验随着时间积累的”,并且源自古老的日耳曼语,意思是“教导”.因此,民俗学是“民间”的积累教育和经验,而不是建立:在Eric S. Raymond的the Cathedral and the Bazaar类比中,民间传说是义卖市场的知识基础.

这种用法引起了至少一位高技能practitioner的注意,他建议使用“深奥”一词来描述有关终端处理的这一点信息. “Esoteric”(再次根据wiktionary)适用于“仅为少数具有专业知识或兴趣的人或开悟的内圈所理解或可能被理解的信息”,源自希腊语?σωτερικ??,“inner圈”. (换句话说,大教堂的知识.)

虽然语义讨论至少是有趣的,但我通过使用希望不那么情绪化的单词“民俗”改变了文本.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读