Este es el desordenado mundo de las pseudo terminales.
Localmente, cuando cambia el tamaño de su terminal, su grupo de procesos en primer plano obtiene un SIGWINCH
y puedes usar ioctl
para obtener el nuevo tamaño. Pero, ¿qué tiene esto que ver con el control remoto proceso vim ?
El tema es bastante complicado, pero la esencia es que el servidor de eliminación (sshd) hace esto:
- Abre un dispositivo pseudoterminal maestro usando
posix_openpt
(oopenpty
) - Bifurca a un niño nuevo (por lo general, esto se convierte en un caparazón)
- Corta su conexión terminal usando
setsid()
- Abre el dispositivo terminal (creado en el paso 1) que se convierte en su terminal de control
- Reemplaza los descriptores estándar (
STDIN_FILENO
y amigos) con el fd del paso 4
En este punto, cualquier cosa que el proceso del servidor escriba en el lado maestro termina como entrada en el lado esclavo PERO con una disciplina de línea terminal por lo que el núcleo hace un poco de magia, como enviar señales, al escribir ciertas combinaciones, y también puede emitir ioctl
llamadas con efectos útiles.
La mejor manera de pensar en esto es explorar el openssh
suite.
-
El cliente monitorea para
SIGWINCH
- verclientloop.c
y establecereceived_window_change_signal = 1
cuando lo recibe -
La función
client_check_window_change
comprueba esa bandera y le dice al servidor :packet_start(SSH_CMSG_WINDOW_SIZE); packet_put_int((u_int)ws.ws_row); ...
Así que ahora el servidor debería recibir un paquete que especifica un tamaño (potencialmente nuevo).
-
El servidor llama a
pty_change_window_size
con los tamaños recibidos que hace la verdadera magia:struct winsize w; w.ws_row = row; ... (void) ioctl(ptyfd, TIOCSWINSZ, &w); /* This is it! */
Esto establece el nuevo tamaño de ventana del esclavo. Si el nuevo tamaño difiere del anterior, el kernel envía un SIGWINCH
al grupo de procesos en primer plano asociado con ese pty. Así vim
también recibe esa señal y puede actualizar su idea del tamaño del terminal.