如何通过ssh或telnet将终端大小更改发送到命令行应用程序?

时间:2013-10-03 10:48:34

标签: linux vim ssh terminal telnet

如何通过ssh或telnet将终端大小更改发送到命令行应用程序?

  1. 用户使用ssh或telnet连接到远程计算机。

  2. 他们开始在VIM中编辑文档。

  3. 然后他们调整了终端窗口的大小。

  4. 终端必须告诉ssh / telnet窗口大小已经改变。这是怎么发生的?

    ssh / telnet然后使用它自己的特定方法将该更改发送到sshd / telnetd。这些方法是什么?

    然后,

    sshd / telnetd告诉应用程序终端大小已更改。怎么做它是从终端到ssh / telnet的方法相同吗?

2 个答案:

答案 0 :(得分:10)

这是伪终端的混乱世界。

在本地,当您调整终端大小时,前台进程组会获得SIGWINCH,您可以使用ioctl来获取新大小。但是这与远程 vim进程有什么关系呢?

主题相当复杂,但要点是删除服务器(sshd)执行此操作:

  1. 使用posix_openpt(或openpty
  2. 打开主psedoterminal设备
  3. 分叉一个新的孩子(通常这必然会成为一个shell)
  4. 使用setsid()
  5. 切断其终端连接
  6. 打开成为其控制终端的终端设备(在步骤1中创建)
  7. 用步骤4中的fd替换标准描述符(STDIN_FILENO和朋友)
  8. 此时服务器进程写入主端的任何内容最终都作为从端的输入但是具有终端线路规则,因此内核有点神奇 - 就像发送信号一样 - 当编写某些组合,您也可以发出有效效果的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! */ 来实现真正的魔法:

      SIGWINCH

    这将设置从属的新窗口大小。如果新大小与旧大小不同,则内核会将vim发送到与该pty关联的前台进程组。因此{{1}}也可以获得该信号,并可以更新其终端大小的想法。

答案 1 :(得分:1)

调整终端窗口大小会生成SIGWINCH信号。

另请参阅相关的glibc documentation