如何通过 ssh 或 telnet 将终端大小更改发送到命令行应用程序?
用户使用 ssh 或 telnet 连接到远程机器。
他们开始在 VIM 中编辑文档。
然后他们调整终端窗口的大小。
终端必须告诉 ssh/telnet 窗口大小已经改变。这是怎么发生的?
然后 ssh/telnet 使用它自己的特定方法将该更改发送到 sshd/telnetd。这些方法是什么?
sshd/telnetd 然后告诉应用程序终端大小已经改变。这是怎么做的。和从终端到 ssh/telnet 的方法一样吗?
这是伪终端的混乱世界。
在本地,当您调整终端大小时,您的前台进程组会得到一个SIGWINCH,您可以使用它ioctl来获取新大小。但这与远程vim 进程有什么关系?
这个主题非常复杂,但要点是删除服务器(sshd)这样做:
posix_openpt使用(或openpty)打开一个主psedoterminal设备setsid()STDIN_FILENO和朋友)此时,服务器进程写入主端的任何内容最终都会作为从端的输入,但带有终端线路规则,因此内核在编写某些组合时会做一些魔术 - 比如发送信号,您也可以发出ioctl调用具有有用的效果。
考虑这一点的最佳方法是探索openssh套件。
客户端监听SIGWINCH- 查看clientloop.c并received_window_change_signal = 1在收到时设置
该函数client_check_window_change检查该标志并告诉服务器:
packet_start(SSH_CMSG_WINDOW_SIZE);
packet_put_int((u_int)ws.ws_row);
...
所以现在服务器应该收到一个指定(可能是新的)大小的数据包。
服务器使用接收到的大小进行调用pty_change_window_size,这具有真正的魔力:
struct winsize w;
w.ws_row = row;
...
(void) ioctl(ptyfd, TIOCSWINSZ, &w); /* This is it! */
这将设置从属设备的新窗口大小。如果新大小与旧大小不同,内核将向与该 pty 关联的前台进程组发送一个。SIGWINCH因此vim也获得了该信号并可以更新其对终端大小的想法。