Questo è il mondo disordinato degli pseudo terminali.
Localmente, quando ridimensioni il tuo terminale, il tuo gruppo di processi in primo piano riceve un SIGWINCH
e puoi usare ioctl
per recuperare la nuova dimensione. Ma cosa c'entra questo con il telecomando processo vim ?
L'argomento è piuttosto complicato, ma il succo è che il server di rimozione (sshd) fa questo:
- Apre un dispositivo pseudoterminale master utilizzando
posix_openpt
(oopenpty
) - Forcia un nuovo figlio (tipicamente questo è destinato a diventare un guscio)
- Interrompe la sua connessione al terminale usando
setsid()
- Apre il dispositivo terminale (creato nel passaggio 1) che diventa il suo terminale di controllo
- Sostituisce i descrittori standard (
STDIN_FILENO
e amici) con fd del passaggio 4
A questo punto tutto ciò che il processo del server scrive sul lato master finisce come input sul lato slave MA con una disciplina della linea terminale quindi il kernel fa un po' di magia - come inviare segnali - quando scrive determinate combinazioni, e puoi anche emettere ioctl
chiamate con effetti utili.
Il modo migliore per pensarci è esplorare il openssh
suite.
-
Il client controlla
SIGWINCH
- vediclientloop.c
e impostareceived_window_change_signal = 1
quando lo riceve -
La funzione
client_check_window_change
controlla quel flag e lo comunica al server :packet_start(SSH_CMSG_WINDOW_SIZE); packet_put_int((u_int)ws.ws_row); ...
Quindi ora il server dovrebbe ricevere un pacchetto che specifica una dimensione (potenzialmente nuova).
-
Il server chiama
pty_change_window_size
con le dimensioni ricevute che fa la vera magia:struct winsize w; w.ws_row = row; ... (void) ioctl(ptyfd, TIOCSWINSZ, &w); /* This is it! */
Questo imposta la nuova dimensione della finestra dello slave. Se la nuova dimensione differisce dalla vecchia, il kernel invia un SIGWINCH
al gruppo di processi in primo piano associato a quel pty. Quindi vim
riceve anche quel segnale e può aggiornare la sua idea della dimensione del terminale.