在我不断尝试理解伪终端如何工作的过程中,我编写了一个小程序来尝试运行bash.
问题是,我的突破似乎是关闭的.(仅在我按回车键后才显示shell提示.)
此外,我仍然无法正常使用ncurses程序,如vi.谁能告诉我如何为此设置伪终端?
我写得很糟糕的程序可以在这里找到,我鼓励你编译它.操作系统是GNU/Linux,谢谢.
编辑:像这样编译:gcc program.c -lutil -o program
再次编辑:看起来奇怪间距的问题是由于使用printf(),但仍然没有解决ncurses程序的问题.
你的程序有几个问题。有些相对容易修复 - 其他则不然:
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 的程序无法正常工作的原因:线路模式和终端的本地回声控制。至少这些必须在父/主和从终端之间匹配,以避免各种奇怪的工件。
终端的控制接口可以通过来回传递字节来传递:并非总是如此。现代的虚拟终端允许通过一定程度的外的带外控制的ioctl()呼叫,用于Linux描述这里。
处理这个问题最简单的方法可能是将父终端设置为原始模式,让从伪终端驱动程序处理尴尬的细节。
您可能想看看这个似乎运行良好的程序。它来自The Linux Programming Interface一书,完整的源代码在这里。免责声明:我没有读过这本书,也没有宣传它 - 我只是使用 Google 找到了该程序。