当与bind一起使用时,为什么TIOCSTI注入会禁用bash中的stty echo?

时间:2019-05-21 21:40:48

标签: bash terminal

我正在尝试绑定bash中的密钥以使用TIOCSTI(example here)将命令注入终端。直到我注入某些命令,此方法才能正常工作。最终目标是替换bash反向搜索(ctrl-r),但这是显示我的问题的示例。

# Test using a clean environment
env -i bash --noprofile --norc

# Define TIOCSTI helper
function inject() {   perl -e 'ioctl(STDIN, 0x5412, $_) for split "", join " ", @ARGV' "$@"; }

# Bind ctrl-b to inject 'yes | less' as a test
bind -x '"\C-b":"inject yes \| less"'

<press ctrl-b>yes | less<press enter>
WARNING: terminal is not fully functional
y  (press RETURN)
y
...
<press q to exit less>

# Terminal is now foobared. In particular I can't see what I type. Why?

# Enable echo
stty echo

如果我只是输入inject yes \| less并按Enter,那么终端就可以了。我认为TIOCSTI与在bash的bind中运行有关。注入yes | less,仅注入yes和长的git log会触发此事件,但是诸如echovi之类的许多其他事件则不会触发。有趣的是,我可以按ctrl-b注入命令,删除行中的所有内容,然后自己重​​新输入,但仍然会丢失回显。就像readline被一些我无法删除的不可见字符所毒害。

我为什么会丢失回声?

我该如何解决?例如。也许还需要通过TIOCSTI发送更多代码以确保安全。

GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)

1 个答案:

答案 0 :(得分:0)

如果只需要某种键盘宏,则可以在〜/ .inputrc中放置这样的示例(例如):

# F12 has a keyboard macro:
"\e[24~": "cls; (date; make 2>&1 || flash 1 >/dev/console 2>&1; date) | tee make.res^M"

注1:^ M是实际的Control-M字符(即\ r,CR,回车符)。

注2:我认为'.inputrc'对间距有些挑剔;我似乎想知道,密钥和宏定义之间必须恰好有一个空格。

注意3:例如,要查看F12的输出,请运行cat并按F12键并记下它打印的字符串。

在风风火火的年代,我曾经有多年了,我自己编译了所有该死的软件包,并只保留了所有make日志(cls基本上是tput clear的脚本, flash是一种自家编写的脚本,用于闪烁终端并响铃:)

尾注:像上面这样的宏最后包含一个CR,这让我感到紧张,我(现在)认为很危险。只是将命令放在提示符后,等待您的交互式CR(或^ C)的宏对我来说是更安全的方法。