Skip to content

Linux Attitude

Le libre est un état d'esprit

Archive

Tag: Standard

Niveau :      
Résumé : zdump ; zic

Le temps est absolu

Le temps est quelque chose de sensible. Si mon serveur est en retard il va croire que la personne qui vient de s'authentifier sur mon site essaie de me flouer en me donnant une date invalide. S'il est en avance, il va croire qu'il n'est pas venu depuis longtemps et va le déconnecter.

Il est donc important d'être toujours à l'heure, car l'heure c'est l'heure et quand il est pas encore l'heure c'est pas l'heure et s'il n'est plus l'heure ce n'est toujours pas l'heure. Vous me suivez ?

Mais pour une fois je ne vais pas vous parler de l'heure selon NTP, mais l'heure selon Saint Matthieu, enfin presque.

Supposons que, grâce à votre professionnalisme, votre machine soit à l'heure, voire à la seconde, grâce à NTP. Supposons que vous vouliez connaitre cette heure. Que faites-vous ? Vous la demandez au noyau (via time ou gettimeofday), et il vous la donne en UTC ...

Mais en pratique vous voulez l'heure de chez vous, celle qui dit que le soleil va se coucher dans la belle province. Bien sûr la libc va faire la conversion pour vous (via localtime, mais voyons comment elle fait.

Enfin presque

La date et l'heure s'expriment de plusieurs façons. L'heure UTC est la version "absolue"', c'est à dire qu'elle ne dépend pas des différentes régions de la planète où l'on se place. Mais tous les pays ne l'entendent pas de cette oreille et veulent chacun définir leur heure. Définition qui peut changer dans le temps ...

Pour faire la conversion, il faut donc connaître toutes ces règles. Heureusement des acharnés on fait ce travail de récupération et les ont déposées dans /usr/share/timezone sur le système de fichier.

Vous croyez qu'il n'y à que 24 fuseaux horaires ? Faux il y en a un peu plus. Maintenant comptons les timezone :

$ find /usr/share/zoneinfo/ -type f | wc -l
1764

Imaginez le temps qu'il a fallu pour compiler ces données ...

Vous constaterez que ce sont des fichiers binaires. La libc les lit directement (pour en savoir un peu plus, man tzfile et man tzset), mais pour nous humains ? On utilise zdump

$ zdump -v Europe/Paris

Vous y verrez les changements d'heure une seconde avant et une seconde après chaque changement. Remarquez qu'il y a plus d'information dans le binaire que dans le dump qui ne fait qu'afficher les dates de saut temporel.

Pas du tout

Mais aujourd'hui est un grand jour, je vais faire ma propre nation (une de plus). J'y édicterai un nouvel horaire, UTC+1,25 et heure d'été en UTC +0,75. Le changement se fera à MON anniversaire.

Il faut donc que je crée un fichier de zone correspondant à mon pays. Prenons le source suivant :

# règles de changement d'heure
Rule peck 2010 max odd Mar 6 4:00 -0:30 -
Rule peck 2010 max odd Sep 6 4:00 0 -
# définition de l'heure standard dans la zone
Zone peck 1:15 peck PCK

Et on le compile avec zic :

# notez que j'ai récupéré yearistype dans le source de tzdata
# il permet l'usage de odd dans mon fichier de règles
$ /usr/sbin/zic -d . -y "sh yearistype.sh" peck

Il suffit maintenant de le déposer dans /usr/share/timezone et voilà ce qu'on peut obtenir :

$ TZ=peck LC_TIME=C date
Mon Mar  7 17:48:02 PCK 2011
# notez la différence (UTC+x et PCK)
$ TZ=peck LC_TIME=fr_FR date
lundi 7 mars 2011, 17:48:37 (UTC+0045)

Votre timezone perso !

Pour des exemples complets et complexes de zones, vous pouvez regarder le source du paquet tzdata. C'est votre référence, mais je doute que vous ayez à y toucher prochainement !

Niveau :      
Résumé : opensearch

Utilisez-vous firefox (pas que lui, mais bon) ?
Avez-vous déjà utilisé la barre de recherche en haut à droite (probablement google) ?
Avez-vous remarqué que vous pouvez rechercher sur autre chose que sur google avec cette barre (petite flèche) ?
Savez-vous que vous pouvez ajouter Linux Attitude dans votre liste de recherche (petite flèche, bouton ajouter) ?
Savez-vous que vous pouvez vous aussi ajouter votre propre moteur à cette liste ?

Voici comment il faut procéder. Si vous avez un moteur de blog c'est déjà fait pour vous, ce n'est pas très intéressant. Sinon, vous devez disposer d'une page permettant de faire une requête utilisant un paramètre (peut-être même pas une recherche en fait).

Le principe est simple, il suffit de suivre le standard OpenSearch. Prenons l'exemple minimaliste de ce site :

<?xml version="1.0" encoding="UTF-8"?>
		<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
			<ShortName>Linux attitude</ShortName>
			<Description>Rechercher dans Linux attitude.</Description>
			<Url type="text/html" template="http://linux-attitude.fr/?q={searchTerms}"/>
		</OpenSearchDescription>

il suffit ensuite d'indiquer dans la page html que le moteur de recherche est disponible :

<link rel="search" href="http://linux-attitude.fr/dcOpenSearch/description.xml" type="application/opensearchdescription+xml" title="Linux attitude" />

Et si une favicon est définie pour le site, elle sera utilisée dans la barre de recherche pour décrire le moteur.

En lisant la norme vous verrez qu'il existe beaucoup de paramètres possibles, beaucoup sont inutiles. Le plus important est de lire le paragraphe décrivant les paramètres de la recherche. Et pour les plus courageux, OpenSearch recommande de retourner les résultats au format RSS ou Atom.

Il existe aussi quelques extensions proposées. La plus intéressante est la suggestion qui permet de jouer à la google suggest et de proposer des mots de recherche à l'utilisateur. Je prendrai peut-être le temps un jour de développer cela.

Niveau :      
Résumé : ar

Connaissez-vous la commande ar ? Ar fait partie de ces commandes à 2 lettres créées à l'époque ou un octet coûtait plus cher que votre salaire mensuel.

Commande

Comme son nom l'indique, ar sert tout simplement à créer des archives :

$ ar rc archive.ar fichier

Et voila on vient de créer une archive avec un fichier dedans. ar sait gérer l'ajout, le remplacement et la suppression de fichier dans une archive, le tout avec des commandes très courtes :

# on remplace le contenu de fichier dans l'archive
$ ar r archive.ar fichier
# on supprime le fichier de l'archive
$ ar d archive.ar fichier

Format

Mais venons-en au point intéressant, ar est un format de fichier extrêmement simple. En fait, dans la plus pure tradition unix et au prix de quelques octets, le format est lisible puisque c'est du texte.

Lisons notre archive :

!<arch>
fichier/        1224766279  1000  1000  100644  7         `
blah

Le l'archive commence simplement par !<arch>, et chaque fichier est inclus tel quel dans l'archive préfixé d'une en-tête de taille fixe de 60 caractères. Vous voyez que vous pouvez vous-même en créer à la main. Une ligne d'en-tête est définie comme suit :

Début	Fin	Nom 			Format
0 	15 	File name 		ASCII
16 	27 	File modification ts 	Decimal
28 	33 	Owner ID 		Decimal
34 	39 	Group ID 		Decimal
40 	47 	File mode	 	Octal
48 	57 	File size in bytes 	Decimal
58 	59 	File magic 		\140\012

Facile a lire et à écrire, un seul petit inconvénient, la taille des noms de fichier est limitée. Il va donc falloir un peu d'astuce pour stocker les noms longs quelque part. Le ar de GNU les stocke dans un fichier virtuel nommé // et y fait référence sous la forme /numéro.

Niveau :      
Résumé : ethernet ; ip ; tcp

Aujourd'hui quelques explications de base sur le fonctionnement d'internet pour ceux qui voudraient mieux comprendre l'article précédent. On va parler simplement, experts, passez votre chemin.

Les couches réseau

Le réseau est conçu comme des lasagnes, chaque protocole s'appuie sur un autre protocole de couche inférieure. Ces couches ont été modélisées par l'iso sous le nom de modèle osi, lequel ne sert à rien (si ce n'est une numérotation bizarre) mais qu'il faut connaître (c'est idiot l'informatique parfois).

En pratique les couches sont donc les suivantes :

  • 1 physique : câble branché, des ondes passent dessus, on les transforme ensuite en bits -> pour les électriciens, électroniciens, microondistes, opticiologues et optoélectroniciens
  • 2 liaison : envoyer des données à l'autre bout du câble (chez vous c'est l'ethernet qui fait ça)
  • 3 réseau : envoyer des données partout sur le réseau (sur internet et quasiment partout c'est IP)
  • 4 transport : gestion d'une communication avec une autre machine sur la durée (souvent TCP ou UDP)
  • 7 au dessus chacun se démerde, ce sont les applications qui implémentent leur protocole (http, smtp ...)

Exemple d'un paquet (à ce niveau on dit une trame) qui passe sur le réseau : tcpip1.png

Chaque couche mérite un livre (voire une bibliothèque) à elle seule, je vais donc être nécessairement court. En fait, je vais me concentrer sur les différents équipements qu'on trouve sur chaque couche.

Switch

Le switch c'est ce qui permet d'aller un peu plus loin que le câble tout en restant au niveau ethernet. A partir de l'adresse MAC "to XX:XX" il envoie le paquet sur le bon port et à la bonne machine sans toucher au contenu du paquet.


continue reading...

Niveau :      
Résumé : echo -e

Vous croyez que 'ASCII est standard. Hé, bien ça n'a pas été le cas pendant longtemps. Entre les valeurs codées sur 5 bits, 6 bits, 7 bits, avec ou sans minuscules ou caractères spéciaux, rien n'était prévu pour que tout le monde se mette d'accord. IBM a pendant bien longtemps utilisé, et utilise encore, sur certains systèmes la norme EBCDIC qui n'a rien à de compatible avec l'ascii.

L'ASCII a donc été standardisé sur 7 bits, avec les caractères de base pour l'anglais, ainsi que divers codes comme ]+$ ... mais surtout, l'ASCII définit 32 caractères qui ne sont pas imprimables. En effet, les terminaux utilisaient (et utilisent encore) le même canal pour communiquer les caractères que pour ses appels de fonction. Ces 32 valeurs ont donc été prévues pour manipuler l'affichage. Parmi ces caractères les plus connus sont \n (retour à la ligne) et \t (tabulation). Notez des inconnus comme les caractères 14 et 15 qui permettent de changer de table de caractères (c'est grâce à eux que vous avez des interfaces textes bien dessinées), et d'autres ne sont plus du tout utilisés.

$ echo -e "\xe tqru \xf"

Notez qu'on peut envoyer des caractères à une application avec une combinaison de touches ctrl-... Mais ce n'était pas suffisant. D'un coté les caractères imprimables ont été étendus à 8 bits puis à l'unicode. D'un autre coté les fonctions du terminal ne se sont pas limitées à 32. Elles ont donc été étendues cette fois avec les séquences d'échappement ANSI. Cette fois il s'agit de préfixer une suite de caractères imprimables du caractère d'échappement (numéro 27). Il s'agit en fait d'un API. Les séquences les plus connues sont les changement de couleurs, exemple :

$ echo -e "\e[31;42mBonjour monde\e[0m"

Mais il y a pire, la plupart des terminaux utilisaient des centaines de séquences différentes (rarement standardisées). C'est ainsi qu'on a créé les bases termcap et terminfo pour essayer de faciliter la vie des clients.

Voila ce qui arrive quand on mélange données et code et qu'on ne respecte pas de standard. Faites donc attention à bien séparer code et données lorsque vous aurez à écrire un protocole.

Niveau :      
Résumé : tty ; infocmp

Comment fonctionne un terminal ?

D'un point de vue unix, un terminal est un fichier, comme tout le reste. C'est à travers ce fichier qu'une application communique avec son terminal.

Quel est ce fichier ?

Chaque type de terminal correspond à un fichier dans /dev avec un nom différent, ainsi les terminaux linux seront dans /dev/tty*, les terminaux physiques seront plutôt accédés par le port série /dev/ttyS*, les terminaux virtuels ancienne génération utiliseront /dev/tty** et les terminaux virtuels plus récents utiliseront plutot /dev/pts/* . Pour savoir sur quel terminal est connecté votre ligne de commande tapez :

$ tty

Et côté "serveur" du terminal virtuel ?

Cette question ne s'applique qu'aux terminaux virtuels tty** et pts/*, ceux-ci ont en effet un pendant serveur effectuant l'affichage réel du contenu du terminal (dans une fenêtre par exemple). Pour les tty** la partie serveur correspondante est /dev/pty** et pour les pts/* il s'agit de /dev/ptmx.

Comment communique-t-on avec un terminal ?

En lui envoyant tout simplement des caractères. L'application qui a connecté votre shell à votre terminal a simplement affecté stdout et stderr à l'entrée et stdin à la sortie du fichier en question. Si vous envoyez un 'A', un A sera imprimé dans le terminal à la position du curseur. Là où ça se complique, c'est qu'il est possible de faire beaucoup plus de choses que d'afficher des caractères. Les caractères non affichables correspondent en fait à des instructions pour les terminaux et c'est grâce à ces instructions qu'on peut mettre des couleurs ou afficher des boites de dialogues dans des terminaux.

Comment connaître ces caractères spéciaux ?

Là où ça se complique encore plus, c'est que chaque type de terminal utilise des séquences différentes et a des options de fonctionnement différentes. Ceci s'explique par la quantité de technologies différentes au début des terminaux. Et pourtant ce problème est resté avec les terminaux virtuels. C'est pourquoi il a été créé une base de données avec les caractéristiques de ceux-ci. C'est termcap, pour savoir à quoi elle ressemble pour votre terminal en cours :

$ infocmp -C

Termcap étant devenue une base de données un peu grosse, sa structure et sa syntaxe ont été modifiées et c'est devenu terminfo. pour savoir à quoi elle ressemble pour votre terminal en cours :

$ infocmp -I

Comme vous voyez c'est un bazar infâme, et je ne vous détaille même pas sa syntaxe.

Mais comment font les logiciels normaux ?

Ils utilisent ncurses. Ncurses est un remplaçant de curses qui vous fournit des fonctions de haut niveau permettant d'éviter de toucher aux bases terminfo et termcap. Ainsi vous pouvez appeler une fonction directement pour changer une couleur ou tracer une ligne dans le terminal. Allez un petit exemple pour la route :

$ dialog --infobox "Bonjour" 10 30

Niveau :      
Résumé : Unicode ; utf8

Qu'est-ce que l'unicode ?

L'unicode est une table de caractères. Tout comme l'ascii, l'ebd, l'iso-8859-1 ...

Cette table a pour but de prendre en compte touts les caractères disponibles dans le monde et ainsi résoudre les problèmes causés par les différentes tables. Cette table fait 1 million d'entrées (0x10FFFF pour être précis), mais rassurez-vous elle n'est pas entièrement remplie. Elle est divisée en blocs, chaque bloc correspondant à une catégorie de caractère, permettant ainsi l'évolution de la table sans devoir en changer l'ordonnancement.

Cette table est une liste de caractères et en pratique son utilisation se fait à travers une police de caractère (laquelle va représenter un ou plusieurs blocs). Bien évidemment avec une table aussi longue, il est difficile de trouver une police qui la couvrirait entièrement. Sur votre machine, il y a donc un grand nombre de polices parmi lesquelles on va chercher pour trouver le caractère qui nous intéresse.

C'est le consortium unicode qui développe cette table ainsi que les règles qui vont avec. Nous en sommes à la 5e version d'unicode. Pour un peu plus d'explications, suivez le guide.

Qu'est-ce que l'utf8 ?

L'utf8 est un encodage, tout comme l'est le 8 bits pour l'ascii. Il est juste un peu plus évolué. On pourrait donc imaginer une utilisation de l'utf8 pour encoder une table autre que l'unicode. Le but de l'utf8 est d'encoder la table unicode tout en évitant de casser un certain nombre d'applications existantes. Il profite du fait que l'ascii se retrouve directement sur les 127 premiers caractères de l'unicode. Tous les caractères de ce bloc restent inchangés et sont codés sur 8 bits. Par contre les autres caractères sont codés sur un nombre variables de bits (multiples de 8).

Il existe d'autres encodages que l'UTF-8 pour l'unicode. L'UCS-2, l'UTF-16, l'UCS-4, l'UTF-32 sont en général plus efficaces en taille que l'utf8 pour les caractères non latins. Par contre ils cassent les applications ascii.

Notez que tous ces encodages sont dépendants de la boutitude (endianness) de votre processeur. C'est pourquoi ils autorisent l'utilisation de caractères spéciaux au début des fichiers texte pour la détecter et permettre le transfert d'un tel fichier d'une architecture à une autre.

Ce qui explique que parfois vous voyiez quelques caractères bizarres au début de vos fichiers texte s'ils sont lus avec des applications qui ne le supportent pas. C'est particulièrement embêtant pour le php qui ne les reconnaît pas et les affiche en début de page (et empêche l'utilisation de header).

Pourquoi l'utiliser (ou pas) ?

L'utf8 est un encodage qui permet une transition relativement simple vers un encodage qui vous permettra de communiquer avec le monde entier. Nombreux sont ceux qui l'utilisent, sa compatibilité avec l'ascii fait qu'il est le seul à pouvoir fonctionner directement avec des protocoles ascii comme l'irc.

Par contre ces encodages créent une différence entre caractère et octets et pour éviter la confusion les développeurs doivent utiliser des fonctions qui calculent cette différence. Dans le cas de l'utf8, ce calcul est compliqué car les caractères sont tous potentiellement de taille différente. Au contraire, pour l'UTF-32 il s'agit d'une simple division par 4.

Un application utilisant l'utf-8 a donc le choix entre faire la conversion (consommateur en mémoire) ou travailler sur des chaînes UTF-8 (très consommateur en temps). Les opposants à l'utf8 vous diront donc que la migration va ralentir la plupart de vos applications. Ce qui est vrai. Peut-être que la voie à suivre serait celle de l'utf-32, ou l'utf-16 comme java ...