Résumé

  • Le Network Virtual Terminal de Telnet ne reproduisait pas chaque terminal : il imposait une représentation intermédiaire où CR LF signifiait nouvelle ligne et CR NUL retour chariot seul.
  • Le caractère placé après CR fermait une décision binaire ; l’émetteur annonçait une action et le destinataire la convertissait selon son système local.
  • La RFC 1123 dut ensuite clarifier la touche Entrée, tandis que le mode binaire supprimait ce traitement et que Net-Unicode conserva CRLF en décourageant CR NUL.

Un caractère qui ne faisait rien, sauf lever le doute

Dans le modèle NVT, CR ramène la tête d’impression à la marge gauche sans changer de ligne. LF descend d’une ligne en gardant la position horizontale. Ensemble, CR LF désigne l’action courante que nous appelons une nouvelle ligne.

Cette arithmétique de mouvements n’était pas universelle. Certains terminaux associaient déjà les deux gestes ; certains systèmes terminaient leurs lignes par LF, d’autres par CR, d’autres encore par une structure qui n’était aucun de ces octets. Une machine recevant CR devait donc éviter deux erreurs : agir trop tôt, puis doubler un mouvement quand LF arrivait ; ou attendre sans savoir quand l’intention était complète.

La RFC 318, en 1972, formula une solution de parseur. Garder CR en suspens, puis lire un caractère de plus. LF signifiait la fonction nouvelle ligne. Si l’émetteur voulait le seul retour chariot, il envoyait CR NUL. NUL restait une non-opération pour l’imprimante, mais il terminait la décision du protocole.

Ce détail renverse une intuition moderne : l’absence d’effet n’est pas l’absence d’information. À cet endroit précis, NUL certifiait qu’aucun LF n’appartenait au CR précédent.

Un terminal commun, pas un catalogue mondial

La RFC 854 fit du Network Virtual Terminal l’état de départ de Telnet. Chaque extrémité traduisait ses habitudes locales vers une machine imaginaire volontairement modeste, puis traduisait les actions reçues vers son terminal, son pseudo-terminal ou son processus.

Le protocole commun ne décidait ni de la largeur physique, ni du stockage local, ni du pilote de terminal. Il définissait seulement les actions nécessaires à l’interopérabilité. NUL ne produisait rien ; LF avançait verticalement ; CR revenait à la marge ; CR LF formait une seule nouvelle ligne.

La règle devint impérative : en NVT ASCII par défaut, un CR devait être suivi de LF ou de NUL. Un CR isolé devait être évité. Après réception de CR NUL, l’implémentation retirait NUL avant la conversion vers le jeu de caractères local. Le second octet appartenait donc à la représentation réseau, pas nécessairement aux données livrées au programme.

La symétrie comptait. La règle valait dans les deux sens, même lorsqu’une extrémité savait qu’elle ne pilotait pas une véritable imprimante. L’objectif n’était pas de conserver une fiction matérielle ; il était de conserver une décision observable.

La touche Entrée n’était pas un octet

Une difficulté demeurait : que voulait dire l’utilisateur lorsqu’il appuyait sur Return ou Enter ? La syntaxe de sortie de l’imprimante NVT était précise, mais la RFC 854 ne fixait pas assez clairement ce que le client devait produire pour cette touche.

La RFC 1123 constata le désaccord. Des clients envoyaient CR LF, d’autres CR NUL. Sur un serveur ASCII correctement construit, les deux devaient produire l’effet de la touche locale de fin de ligne. Sur d’autres hôtes, assimiler CR NUL à une fin de ligne pouvait rendre impossible la saisie d’un vrai retour chariot ; refuser cette assimilation cassait des clients existants.

La clarification sépara les rôles. Un User Telnet devait savoir envoyer CR LF, CR NUL et LF. Sur un hôte ASCII, il devait de préférence proposer un choix contrôlé par l’utilisateur et prendre CR LF comme valeur initiale pour la touche de fin de ligne. Pour des données qui n’étaient pas une saisie terminal-vers-ordinateur — sortie du serveur ou protocole applicatif encapsulé — la fin de ligne devait être CR LF.

Le serveur conservait ensuite la traduction locale. En mode terminal brut, il pouvait livrer CR au programme ; en mode formaté, il appliquait la convention de ligne du système. L’égalité demandée portait sur l’effet à la frontière du terminal, non sur une identité perpétuelle des octets.

Le mode binaire changeait de lecteur

L’option Binary de la RFC 856 ne consistait pas à ajouter un bit au même texte. Elle devait être négociée séparément dans chaque direction. Une fois acceptée, les octets ordinaires devenaient des données sur huit bits ; IAC gardait toutefois sa fonction de commande Telnet et devait être doublé lorsqu’il représentait la valeur 255 dans les données.

La RFC 1123 fixa la conséquence : aucun traitement de fin de ligne en mode binaire. Il était interdit d’insérer CR NUL ou CR LF. Ainsi, la même séquence n’appartenait plus au même interprète. En NVT ASCII, CR ouvrait une décision de représentation. En binaire, CR, LF et NUL restaient des octets applicatifs.

Supprimer systématiquement NUL après CR devient alors une corruption. L’observation doit conserver le sens de circulation et l’état négocié, faute de quoi une capture « nettoyée » perd précisément la preuve qui permet de juger la transformation.

Linemode déplaçait l’édition, pas le sens

La RFC 1184 répondait au coût de l’édition caractère par caractère sur les réseaux lents. En mode d’édition local, le client pouvait préparer une ligne complète avant de l’envoyer. Sa terminaison normale devenait CR LF.

Hors édition, un retour chariot voyageait comme CR NUL, un saut de ligne comme LF, et une touche spéciale signifiant « ligne terminée » comme CR LF. Le serveur restait maître du traitement de sa sortie : CR LF pour nouvelle ligne, CR NUL pour le seul retour chariot, LF pour le seul mouvement vertical.

Le lieu de l’édition pouvait donc changer sans déplacer l’autorité sémantique sur les données émises par l’autre côté. Optimiser la latence n’obligeait pas à redéfinir la représentation partagée.

De l’imprimante virtuelle au texte Unicode

La RFC 5198 raconta plus tard l’héritage de NVT ASCII en définissant Net-Unicode. Elle conserva CRLF comme fin de ligne et la contrainte selon laquelle CR doit être suivi de LF ou de NUL. Mais elle déconseilla CR NUL : les compositions par surimpression étaient devenues marginales, et NUL pouvait arrêter dangereusement une chaîne dans certains langages.

Ce changement ne réfute pas la solution initiale. Il montre comment un invariant installé survit tandis que l’usage exceptionnel se rétrécit. CRLF resta le point commun ; le retour chariot solitaire perdit une grande partie de sa raison d’être.

Le registre IANA des options Telnet conserve les numéros de Binary, Linemode et des options de disposition. Il établit une nomenclature, pas un taux de déploiement ni la conformité des produits actuels.

Ce que la ponctuation rendait vérifiable

Telnet n’avait besoin d’aucune autorité centrale pour arbitrer chaque touche. L’émetteur choisissait une action NVT ; le destinataire lisait localement le caractère suivant et appliquait une règle déterministe. La diversité demeurait aux bords.

Les accidents commençaient lorsqu’un intermédiaire retirait cette ponctuation trop tôt : normalisation de tous les CR, suppression de NUL avant de connaître le mode, conversion d’une touche en nouvelle ligne avant que l’application ne puisse demander un CR brut. Une commodité locale devenait alors une falsification du contrat partagé.

Sources et limites de preuve

Ces textes établissent le modèle, ses corrections et ses exceptions négociées. Ils ne mesurent pas l’usage contemporain, ne certifient aucun produit et ne démontrent pas une uniformité historique. CR NUL reste ici une règle située de représentation, non une propriété générale de tout texte.