Friday, September 26, 2008

Screwed up terminals: the solution

Anyone who has been doing C programming on Linux has encountered this at least one, or is a very rigourous programmer. A certain binary sequence (that you normally never encounter in ASCII text, but that might be present in that binary file you accidentally dumped on your terminal) will switch you to the "graphical and lines" character set where everything gets completely unreadable.

Si vous programmez sous Linux ce genre d'écran illisible ne vous est forcément pas inconnu. Tôt ou tard, vous (ou un de vos collègues) a forcément malencontreusement envoyé un fichier mp3 ou une image ou un programme sur la sortie du terminal et pas de chance: il contenait cette petite séquence ANSI qui force la console à passer sur le jeu de caractères graphiques, utilisé entre autres par ncurses pour dessiner ses boites et ses menus.

It was fairly easy to fix under SuSE and RedHat back in Y2K as a simple "reset" command typed on the terminal restored the display. Unfortunately, ubuntu Linux distributions do not seem to think a terminal reset should include reset the character set to its default value...

It occurred once again today. Once too much. I dug the ANSI commands set and wrote a small perl tool that let me toy with ANSI escape codes. Here it comes: ANSIHACK.PL (in uppercase so that you can recognize it even when your terminal is screwed :P)

#!/usr/bin/perl
print "\x1b($1\nMODE $1 ENABLED.\n" if $ARGV[0]=~/\-\-SET([0-9A-B])/;
print "\x1bc\x1b(A" if $ARGV[0] eq '--RESET';
shift @ARGV if $ARGV[0]=~/^\-\-/;
print "\x1b[$ARGV[0]\n";
print "done/DONE.\n";
exit(0);
Actually, the commands that trigger a charset switch are Esc(x and Esc)x. Charset A is our default, regular 'ascii' charset (used in --RESET form) but you can also toy with other charsets (B, 0, 1 and 2) with e.g. ANSIHACK.PL --SET0 (that screws things up) and ANSIHACK.PL --SETA (which restores things to normal).

C'était assez simple à résoudre du temps de SuSE et RedHat (tapez 'reset' en aveugle, puis appuyez sur ENTER les doigts croisés en sautant sur un pied un soir de pleine lune avec un baton de réglisse entre les dents). Mais sous ubuntu. Rien. reset efface le contenu du terminal, mais ne résoud pas le problème qui nous occupe. D'où ce petit script pour jouer avec les commandes ANSI. Les vieux de la vieille pourront se faire un alias reset='bin/ANSIHACK.PL --SETA' ;)

|-|oPe !7 |-|e|_p$ ;)

edit: the real explanation is that a '0x0e' character (shift out) had been issued and only a '0x0f' character (shift in) would bring the default charset. The ANSI hack almost works, but it screws up the '#' character into some £...

1 comment:

Anonymous said...

Ben moi je ne connaissais pas reset !!!

du coup un petit printf "\x1bc" c'est bien pratique :)