在我不断尝试理解伪终端如何工作的过程中,我编写了一个小程序来尝试运行bash。
问题是,我的突破似乎是关闭的。 (仅当我按下回车键时才显示shell提示。)
此外,我还是无法正常使用ncurses程序,比如vi。谁能告诉我如何为此设置伪终端?
My badly written program can be found here, I encourage you to compile it。操作系统是GNU / Linux,谢谢。
编辑:编译如下:gcc program.c -lutil -o program
再次编辑:看起来奇怪间距的问题是由于使用了printf(),但仍然无法解决ncurses程序的问题。
答案 0 :(得分:4)
您的计划中有几个问题。有些相对容易修复 - 其他则不是很多:
forkpty()
及其朋友来自BSD且与POSIX不兼容。新程序应该避免使用它们。来自pty(7) manual page
:
历史上,两个伪终端API已经发展:BSD和System V. SUSv1标准化基于System V API的伪终端API,并且该API应该用于所有使用伪终端的新程序。
您应该使用posix_openpt()
代替。这个问题可能并不重要,但您应该了解它。
您正在混合对原始系统调用(read()
,write()
)和文件流(printf()
,fgets()
)函数的调用。这是一个让自己迷惑的好方法。一般来说,您应该选择一个方法并坚持下去。在这种情况下,最好使用低级系统调用(read()
,write()
)来避免因C库函数使用的I / O缓冲区的存在而引起的任何问题
您假设使用printf()
和fgets()
为您的终端设置了基于行的范例。这并非总是如此,尤其是在处理vim
等交互式程序时。
您假设一个C风格的单字节以空字符结尾的字符串范例。终端通常处理字符和字节 - 而不是字符串。虽然大多数字符集编码都避免使用零字节,但并非都是这样做。
由于上述(2),(3)和(4),您未正确使用read()
和write()
。您应该使用它们的返回值来确定它们处理的字节数,而不是像strlen()
这样的基于字符串的函数。
在我看来,这个问题最难以解决:你隐含地假设:
终端(或其驱动程序)是无状态的:不是。期。我怀疑至少有两个有状态控件是基于ncurses的程序无法正常工作的原因:终端的line mode和local echo control。至少这些必须在父/主终端和从终端之间进行匹配,以避免各种奇怪的伪像。
只需通过来回传递字节就可以传递终端的控制接口:并非总是如此。现代虚拟终端允许通过ioctl()
调用进行一定程度的带外控制,如针对Linux here所述。
处理此问题的最简单方法可能是将父终端设置为原始模式,让slave伪终端驱动程序处理尴尬的细节。
你可能想看看this program似乎工作正常。它来自书籍The Linux Programming Interface,完整的源代码是here。 免责声明:我没有看过这本书,也没有推广它 - 我刚刚使用Google找到了这个程序。