在伪终端的Ncurses程序 [英] Ncurses programs in pseudo-terminals

查看:118
本文介绍了在伪终端的Ncurses程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我继续试图了解伪终端如何工作的,我已经写了一个小程序来尝试运行bash的。

In my continuing attempt to understand how pseudo-terminals work, I have written a small program to try to run bash.

问题是,我断行似乎处于关机状态。 (外壳提示仅出现后,我preSS进入。)

The problem is, my line-breaking seems to be off. (The shell prompt only appears AFTER I press enter.)

此外,我还是不能正常使用ncurses的程序,比如vi。谁能告诉我如何设置伪终端呢?

Furthermore, I still cannot properly use ncurses programs, like vi. Can anyone tell me how to setup the pseudo-terminal for this?

我写的不好的程序可以在这里找到,我鼓励你编译。操作系统是GNU / Linux的,谢谢。

My badly written program can be found here, I encourage you to compile it. The operating system is GNU/Linux, thanks.

编辑:编译如下:GCC program.c -lutil -o程序

Compile like this: gcc program.c -lutil -o program

再次编辑:它看起来像怪异的间距问题是由于用printf(),仍然不能解决与ncurses的程序问题,但

EDIT AGAIN: It looks like the issue with weird spacing was due to using printf(), still doesn't fix the issue with ncurses programs though.

推荐答案

有在程序中的几个问题。一些比较容易修复 - 他人与其说

There are several issues in your program. Some are relatively easy to fix - others not so much:


  1. forkpty() 和它的朋友来自BSD和 POSIX不兼容的。他们应避免新的方案。从 PTY(7)手册页

  1. forkpty() and its friends come from BSD and are not POSIX compatible. They should be avoided for new programs. From the pty(7) manual page:

从历史上看,两人的API伪终端已经发展:BSD和System V. SUSv1标准化基于System V的API一个API伪终端,而这个API应该在使用虚拟终端的所有新项目中使用

Historically, two pseudoterminal APIs have evolved: BSD and System V. SUSv1 standardized a pseudoterminal API based on the System V API, and this API should be employed in all new programs that use pseudoterminals.

您应该使用 posix_openpt() 来代替。这个问题可能并不重要,但你应该意识到这一点。

You should be using posix_openpt() instead. This issue is probably not critical, but you should be aware of it.

您在混合调用原始系统调用( 阅读( ) 的write() )和文件流( 的printf () 与fgets() )功能。这是混淆自己一个很好的办法。一般来说,你应该选择的有一个的办法,并坚持下去。在这种情况下,它可能是最好使用低级别的系统调用( 阅读() 的write() ),以避免从我的presence / C库函数使用O缓冲区。

You are mixing calls to raw system calls (read(), write()) and file-stream (printf(), fgets()) functions. This is a very good way to confuse yourself. In general you should choose one approach and stick with it. In this case, it's probably best to use the low-level system calls (read(), write()) to avoid any issues that would arise from the presence of the I/O buffers that the C library functions use.

您的假设基于行的模式为您的终端,通过使用 的printf() 与fgets() 。这并不总是正确的,尤其是像 VIM 互动节目的时候。

You are assuming a line-based paradigm for your terminals, by using printf() and fgets(). This is not always true, especially when dealing with interactive programs like vim.

您是假设C风格的单字节空终止字符串的范例。通常的终端处理字符和字节 - 不是字符串。虽然大部分的字符集编码避免使用一个零字节的不是所有这样做的

You are assuming a C-style single-byte null-terminated string paradigm. Terminals normally deal with characters and bytes - not strings. And while most character set encodings avoid using a zero byte, not all do so.

由于(2),(3)和(4)以上,在不使用的 阅读() 和的 的write() 正确。你应该用自己的返回值,以确定他们有多少字节进行处理,而不是基于字符串的函数如 的strlen()

As a result of (2), (3) and (4) above, you are not using read() and write() correctly. You should be using their return values to determine how many bytes they processed, not string-based functions like strlen().

这是这样的,在我看来,将是最困难的问题要解决:你是隐含假设:

This is the issue that, in my opinion, will be most difficult to solve: You are implicitly assuming that:


  • 终端(或其驱动程序)是无状态的:的事实并非如此。期。有迹象表明,我怀疑至少有两个状态的控制是基于ncurses的程序无法正常工作的原因:的行模式局部回声控制终奌站。至少这些必须的父/主站和为了避免各种奇怪工件从属终端之间匹配

  • The terminal (or its driver) is stateless: It is not. Period. There are at least two stateful controls that I suspect are the cause of ncurses-based programs not working correctly: The line mode and the local echo control of the terminal. At least these have to match between the parent/master and the slave terminal in order to avoid various strange artifacts.

终端的控制接口,可以仅通过传递字节来回传递,通过:的它并非总是如此。现代虚拟终端允许某种程度的出带外控制通过 的ioctl( )电话为Linux的这里描述

The control-interface of a terminal can be passed-through just by passing the bytes back and forth: It is not always so. Modern virtual terminals allow for a degree of out-of-band control via ioctl() calls, as described for Linux here.

要解决这个问题,最简单的方法可能是设置父终端原始模式,让奴隶伪终端驱动程序处理的尴尬细节。

The simplest way to deal with this issue is probably to set the parent terminal to raw mode and let the slave pseudo-terminal driver deal with the awkward details.

您可能想看看这这似乎很好地工作计划。它来自于本书 Linux的编程接口和完整的源$ C ​​$ c是的此处。的免责声明:我没有读过书,我也不是推动它 - 我刚刚发现使用谷歌程序

You may want to have a look at this program which seems to work fine. It comes from the book The Linux Programming Interface and the full source code is here. Disclaimer: I have not read the book, nor am I promoting it - I just found the program using Google.

这篇关于在伪终端的Ncurses程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆