Content-type: text/html
Lisez les FAQ et la documentation spécifique au portage de perl sur votre système d'exploitation (par ex. perlvms, perlplan9, etc.). Vous devriez y trouver de plus amples informations sur les spécificités de votre perl.
Term::Cap Distribution standard
Term::ReadKey CPAN
Term::ReadLine::Gnu CPAN
Term::ReadLine::Perl CPAN
Term::Screen CPAN
Term::Cap Distribution standard
Curses CPAN
Term::ANSIColor CPAN
Tk CPAN
Certains cas spécifiques sont étudiés ci-dessous.
use Term::ANSIColor;
print color("red"), "Stop!\n", color("reset");
print color("green"), "Go!\n", color("reset");
Ou comme ceci :
use Term::ANSIColor qw(:constants);
print RED, "Stop!\n", RESET;
print GREEN, "Go!\n", RESET;
open(TTY, "+</dev/tty") or die "no tty: $!";
system "stty cbreak </dev/tty >/dev/tty 2>&1";
$key = getc(TTY); # peut marcher
# OU BIEN
sysread(TTY, $key, 1); # marche sans doute
system "stty -cbreak </dev/tty >/dev/tty 2>&1";
Le module Term::ReadKey de CPAN offre une interface prête à l'emploi, et devrait être plus efficace que de lancer des stty pour chaque touche. Il inclut même un support limité pour Windows.
use Term::ReadKey;
ReadMode('cbreak');
$key = ReadKey(0);
ReadMode('normal');
Cependant, cela requiert que vous ayez un compilateur C fonctionnel, qui puisse être utilisé pour compiler et installer des modules de CPAN. Voici une solution n'utilisant que le module standard POSIX, qui devrait être disponible en natif sur votre système (s'il est lui-même POSIX).
use HotKey;
$key = readkey();
Et voici le module HotKey, qui cache les appels POSIX gérant les structures termios, qui sont assez ésotériques, il faut bien l'avouer :
# HotKey.pm
package HotKey;
@ISA = qw(Exporter);
@EXPORT = qw(cbreak cooked readkey);
use strict;
use POSIX qw(:termios_h);
my ($term, $oterm, $echo, $noecho, $fd_stdin);
$fd_stdin = fileno(STDIN);
$term = POSIX::Termios->new();
$term->getattr($fd_stdin);
$oterm = $term->getlflag();
$echo = ECHO | ECHOK | ICANON;
$noecho = $oterm & ~$echo;
sub cbreak {
$term->setlflag($noecho); # ok, on ne veut pas d'écho non plus
$term->setcc(VTIME, 1);
$term->setattr($fd_stdin, TCSANOW);
}
sub cooked {
$term->setlflag($oterm);
$term->setcc(VTIME, 0);
$term->setattr($fd_stdin, TCSANOW);
}
sub readkey {
my $key = '';
cbreak();
sysread(STDIN, $key, 1);
cooked();
return $key;
}
END { cooked() }
1;
use Term::ReadKey;
ReadMode('cbreak');
if (defined ($char = ReadKey(-1)) ) {
# il y avait un caractère disponible, maintenant dans $char
} else {
# pas de touche pressée pour l'instant
}
ReadMode('normal'); # restaure le terminal en mode normal
system("clear");
Si ce doit être une opération fréquente, sauvegardez la séquence de nettoyage pour pouvoir ensuite l'afficher 100 fois sans avoir à appeler un programme externe autant de fois :
$clear_string = `clear`;
print $clear_string;
Si vous prévoyez d'autres manipulations d'écran, comme le positionnement du curseur, etc., utilisez plutôt le module Term::Cap :
use Term::Cap;
$terminal = Term::Cap->Tgetent( {OSPEED => 9600} );
$clear_string = $terminal->Tputs('cl');
use Term::ReadKey;
($wchar, $hchar, $wpixels, $hpixels) = GetTerminalSize();
Cela est plus portable qu'un appel direct à "ioctl", mais n'est pas aussi illustratif :
require 'sys/ioctl.ph';
die "no TIOCGWINSZ " unless defined &TIOCGWINSZ;
open(TTY, "+</dev/tty") or die "No tty: $!";
unless (ioctl(TTY, &TIOCGWINSZ, $winsize='')) {
die sprintf "$0: ioctl TIOCGWINSZ (%08x: $!)\n", &TIOCGWINSZ;
}
($row, $col, $xpixel, $ypixel) = unpack('S4', $winsize);
print "(row,col) = ($row,$col)";
print " (xpixel,ypixel) = ($xpixel,$ypixel)" if $xpixel || $ypixel;
print "\n";
Il y a un exemple de ceci sous ``crypt'' in perlfunc). Tout d'abord, on place le terminal en mode ``sans écho'', puis on lit simplement le mot de passe. Cela peut se faire avec un bon vieil ioctl(), avec le contrôle terminal de POSIX (voir POSIX, et le chapitre 7 du Camel), ou encore par un appel au programme stty, avec divers degrés de portabilité.
On peut aussi, sur la plupart des systèmes, utiliser le module Term::ReadKey de CPAN, qui est le plus simple à utiliser et le plus portable en théorie.
use Term::ReadKey;
ReadMode('noecho');
$password = ReadLine(0);
print DEV "atv1\012"; # mauvais, pour certains périphériques
print DEV "atv1\015"; # bon, pour certains périphériques
Bien que pour les fichiers de texte normaux, un ``\n'' fasse l'affaire, il n'y a toujours pas de schéma unifié pour terminer une ligne qui soit portable entre Unix, DOS/Win et Macintosh, sauf à terminer TOUTES les lignes par un ``\015\012'', et de retirer ce dont vous n'avez pas besoin dans le résultat en sortie. Cela s'applique tout particulièrement aux E/S sur les prises (sockets) et à la purge des tampons, problèmes qui sont discutés ci-après.
$oldh = select(DEV);
$| = 1;
select($oldh);
Vous verrez aussi du code qui réalise l'opération sans variable temporaire :
select((select(DEV), $| = 1)[0]);
Ou, si le fait de charger quelque milliers de lignes de code, simplement par peur d'une toute petite variable comme $|, ne vous ennuie pas outre mesure :
use IO::Handle;
DEV->autoflush(1);
Comme expliqué dans le point précédent, cela ne marchera pas si vous utilisez des E/S sur une prise entre Unix et un Macintosh. Vous devrez câbler vos terminaisons de ligne, dans ce cas.
En cherchant à lire sa boîte vocale, le fameux Jamie Zawinski <jwz@netscape.com>, après de nombreux grincements de dents et une lutte avec sysread, sysopen, les caprices de la fonction POSIX tcgetattr, et de nombreuses autres fonctions promettant de s'éclater la nuit, est finalement arrivé à ceci :
sub open_modem {
use IPC::Open2;
my $stty = `/bin/stty -g`;
open2( \*MODEM_IN, \*MODEM_OUT, "cu -l$modem_device -s2400 2>&1");
# lancer cu trafique les paramètres de /dev/tty, même lorsqu'il a
# été lancé depuis un tube...
system("/bin/stty $stty");
$_ = <MODEM_IN>;
chop;
if ( !m/^Connected/ ) {
print STDERR "$0: cu printed `$_' instead of `Connected'\n";
}
}
Sérieusement, cela n'est pas possible si ce sont des mots de passe Unix - le système de cryptage des mots de passe sur Unix utilise une fonction de hachage à sens unique. C'est plus du hachage que de l'encryption. La meilleure méthode consiste à trouver quelque chose d'autre qui se hache de la même façon. Il n'est pas possible d'inverser la fonction pour retrouver la chaîne d'origine. Des programmes comme Crack peuvent essayer de deviner les mots de passe de façon brutale (et futée), mais ne vont pas (ne peuvent pas) garantir de succès rapide.
Si vous avez peur que vos utilisateurs ne choisissent de mauvais mots de passe, vous devriez le vérifier au vol lorsqu'ils essaient de changer leur mot-de-passe (en modifiant la commande passwd(1) par exemple).
system("cmd &")
ou utiliser fork comme expliqué dans ``fork'' in perlfunc, avec des exemples supplémentaires dans perlipc. Voici quelques petites choses dont il vaut mieux être conscient sur un système de type Unix:
$SIG{CHLD} = sub { wait };
Voir ``Signaux'' in perlipc pour d'autres exemple de code réalisant cela. Il n'est pas possible d'obtenir des zombies avec "system("prog &")".
Faites attention : très peu de bibliothèques C sont réentrantes. Il s'ensuit que si vous essayez de faire un print() dans la routine de traitement appelée pendant l'exécution d'une autre opération de stdio, les structures internes vont être corrompues, et votre processus va faire un ``core dump''. Cela peut parfois être évité en utilisant syswrite() au lieu de print().
À moins d'être prodigieusement attentif, les seules choses vraiment sûres à l'intérieur d'une routine de traitement de signal sont : positionner une variable, et terminer le programme par exit(). Et dans le premier cas, il faut bien prendre garde à ce que l'affectation ne cause pas d'appel à malloc() (par exemple, en positionnant une variable déjà allouée).
Ainsi :
$Interrupted = 0; # on s'assure que la variable est allouée
$SIG{INT} = sub {
$Interrupted++;
syswrite(STDERR, "ouch\n", 5);
}
Cependant, parce que les appels systèmes sont relancés pas défaut, vous allez vite vous apercevoir qu'au sein d'un appel système bloquant comme <FH>, read(), connect(), ou wait(), la seule façon d'en sortir est via un longjump() ; c'est-à-dire, en causant une exception. Voir le traitement d'alarme pour un appel bloquant flock() dans ``Signaux'' in perlipc, ou le chapitre 6 du Camel.
Si par contre vous désirez seulement changer de fuseau horaire, vous pourrez certainement vous en sortir en positionnant une variable d'environnement :
$ENV{TZ} = "MST7MDT"; # unixien
$ENV{'SYS$TIMEZONE_DIFFERENTIAL'}="-5" # vms
system "trn comp.lang.perl.misc";
Si votre système supporte à la fois la fonction syscall() en Perl et un appel système tel que gettimeofday(2), alors vous pouvez peut-être faire quelque chose comme ceci :
require 'sys/syscall.ph';
$TIMEVAL_T = "LL";
$done = $start = pack($TIMEVAL_T, ());
syscall(&SYS_gettimeofday, $start, 0) != -1
or die "gettimeofday: $!";
#############################
# FAITES VOS OPERATIONS ICI #
#############################
syscall( &SYS_gettimeofday, $done, 0) != -1
or die "gettimeofday: $!";
@start = unpack($TIMEVAL_T, $start);
@done = unpack($TIMEVAL_T, $done);
# corriger les microsecondes
for ($done[1], $start[1]) { $_ /= 1_000_000 }
$delta_time = sprintf "%.4f", ($done[0] + $done[1] )
-
($start[0] + $start[1] );
Par exemple, on peut utiliser ceci pour s'assurer qu'un programme filtre est bien parvenu à vider son tampon de sortie sans remplir tout le disque :
END {
close(STDOUT) || die "stdout close failed: $!";
}
Par contre, le bloc END n'est pas appelé lorsqu'un signal non capturé tue le programme, donc si vous utilisez les blocs END, vous devriez aussi utiliser :
use sigtrap qw(die normal-signals);
En Perl, le traitement des exceptions s'effectue au travers de l'opération eval(). Vous pouvez utiliser eval() en lieu et place de setjmp, et die() pour longjmp(). Pour plus de détails sur cela, lire la section sur les signaux, et plus particulièrement le traitement limitant le temps de blocage pour un flock() dans ``Signaux'' in perlipc et le chapitre 6 du Camel Book.
Si tout ce qui vous intéresse est le traitement des exceptions proprement dit, essayez la bibliothèque exceptions.pl (qui fait partie de la distribution standard de Perl).
Si vous préférez la syntaxe de atexit() (et désirez rmexit() aussi), essayez le module AtExit disponible sur CPAN.
Notez que bien que SunOS et Solaris soient compatibles au niveau des binaires, ces valeurs sont néanmoins différentes. Allez comprendre !
Rappelez-vous de vérifier les modules qui sont livrés avec votre distribution, ainsi que CPAN - quelqu'un a peut-être deja écrit un module pour le faire.
1. devenir super-utilisateur
2. cd /usr/include
3. h2ph *.h */*.h
Si votre système supporte le chargement dynamique, et pour des raisons de portabilité et de sanité, vous devriez plutôt utiliser h2xs (qui fait lui aussi partie de la distribution standard de perl). Cet outil convertit un fichier d'inclusion C en une extension Perl. Voir perlxstut pour savoir comment débuter avec h2xs.
Si votre système ne support pas le chargement dynamique, vous pouvez néanmoins utiliser h2xs. Voir perlxstut et ExtUtils::MakeMaker pour plus d'information (brièvement, utilisez simplement make perl et non un simple make pour reconstruire un perl avec une nouvelle extension statiquement liée).
On peut aussi utiliser le module IPC:Open3 (lui aussi dans la distribution standard), mais attention: l'ordre des arguments est différent de celui utilisé par IPC::Open2 (voir IPC::Open3).
$exit_status = system("mail-users");
$output_string = `ls`;
system $cmd; # avec system()
$output = `$cmd`; # avec les guillemets inversés (``)
open (PIPE, "cmd |"); # avec open()
Avec system(), STDOUT et STDERR vont tous deux aller là où ces descripteurs sont dirigés dans le script lui-même, sauf si la commande les redirige par ailleurs. Les guillemets inversés et open() lisent seulement la sortie sur STDOUT de votre commande.
Avec ces routines, vous pouvez changer les descripteurs de fichier avec l'appel :
open(STDOUT, ">logfile");
system("ls");
ou vous pouvez utiliser les redirections du shell de Bourne :
$output = `$cmd 2>some_filè;
open (PIPE, "cmd 2>some_file |");
Vous pouvez aussi utiliser les redirections de fichier pour rendre STDERR un synonyme de STDOUT :
$output = `$cmd 2>&1`;
open (PIPE, "cmd 2>&1 |");
Cependant, vous ne pouvez pas simplement ouvrir STDERR en synonyme de STDOUT depuis votre programme Perl, et ne pas recourir ensuite à la redirection en shell. Ceci ne marche pas :
open(STDERR, ">&STDOUT");
$alloutput = `cmd args`; # stderr n'est toujours pas capturé
Cela échoue parce que open() rend STDERR un synonyme de STDOUT au moment où l'appel à open() a été effectué. Les guillemets inversés redirigent ensuite STDOUT vers une chaîne, mais ne changent pas STDERR (qui va toujours là où allait le STDOUT d'origine).
Notez bien que vous devez utiliser la syntaxe de redirection du shell de Bourne (sh(1)) dans les guillemets inversés, et non celle de csh(1) ! Des précisions sur les raisons pour lesquelles Perl utilise le shell de Bourne pour system() et les guillemets inversés, ainsi que lors des ouvertures de tubes, se trouvent dans http://www.perl.com/CPAN/doc/FMTEYEWTK/versus/csh.whynot .
Pour capturer à la fois le STDOUT et le STDERR d'une commande :
$output = `cmd 2>&1`; # soit avec des guillemets
$pid = open(PH, "cmd 2>&1 |"); # inversés, soit avec un tube
while (<PH>) { } # plus une lecture
Pour capturer seulement le STDOUT et jeter le STDERR d'une commande :
$output = `cmd 2>/dev/null`; # soit avec des guillemets
$pid = open(PH, "cmd 2>/dev/null |"); # inversés, soit avec un tube
while (<PH>) { } # plus une lecture
Pour capturer seulement le STDERR et jeter le STDOUT d'une commande :
$output = `cmd 2>&1 1>/dev/null`; # soit avec des guillemets
$pid = open(PH, "cmd 2>&1 1>/dev/null |"); # inversés, soit avec un tube
while (<PH>) { } # plus une lecture
Pour échanger le STDOUT et le STDERR d'une commande afin d'en capturer le STDERR mais laisser le STDOUT sortir à la place du STDERR d'origine :
$output = `cmd 3>&1 1>&2 2>&3 3>&-`; # soit avec des guillemets
$pid = open(PH, "cmd 3>&1 1>&2 2>&3 3>&-|");# inversés, soit avec un tube
while (<PH>) { } # plus une lecture
Pour lire le STDOUT et le STDERR d'une commande séparément, il est plus facile et sûr de les rediriger chacun dans un fichier, et ensuite de les lire lorsque la commande est terminée :
system("program args 1>/tmp/program.stdout 2>/tmp/program.stderr");
L'ordre est important dans tout ces exemples. Cela est dû au fait que le shell prend toujours en compte les redirections en les lisant strictement de gauche à droite.
system("prog args 1>tmpfile 2>&1");
system("prog args 2>&1 1>tmpfile");
La première commande redirige à la fois la sortie standard et la sortie d'erreur dans le fichier temporaire. La seconde commande n'y envoie que la sortie standard d'origine, et la sortie d'erreur d'origine se retrouve envoyé vers la sortie standard d'origine.
Pour savoir si le exec()a réussi, il vous faudra capturer SIGCHLD et lancer wait() pour lire la valeur de sortie. Vous devriez aussi capturer SIGPIPE si vous écrivez vers le fils --- vous pourriez vous rendre compte que l'exec() a échoué qu'au moment de ladite écriture. Tout cela est documenté dans perlipc.
Dans certains cas, même ceci ne fonctionne pas. Si le second argument d'un open() sur un tube contient des métacaractères du shell, perl réalise le fork(), puis lance un shell via exec() pour décoder les métacaractères et finalement lance le programme désiré. Dès lors, quand vous appelez wait(), vous ne pouvez plus qu'apprendre si le shell a bien été démarré. Le mieux est encore d'éviter les métacaractères du shell.
Sur des systèmes qui suivent plutôt le paradigme de spawn(), open() pourrait faire ce que vous en attendez --- sauf si perl utilisait un shell pour lancer votre commande. Dans ce cas, la description faite pour fork()/exec() s'appliquerait aussi ici.
`cp file file.bak`;
Et ils se disent : ``Voilà, je vais toujours utiliser les guillemets inversés pour lancer mes programmes''. Mauvaise idée : les guillemets inversés sont là pour capturer la sortie des programmes ; c'est la fonction system() qui est destinée à lancer des programmes.
Considérons la ligne suivante :
`cat /etc/termcap`;
Ici, la sortie n'est assignée à aucune variable, donc c'est juste une perte de mémoire (temporaire). Sans compter qu'on a oublié de vérifier la valeur de $? pour savoir si le programme s'était bien déroulé. Même si l'on avait écrit :
print `cat /etc/termcap`;
Dans la plupart des cas, cela pourrait et devrait probablement être écrit ainsi :
system("cat /etc/termcap") == 0
or die "cat program failed!";
Ce qui permet d'avoir la sortie rapidement (au fur et à mesure de sa génération, au lieu d'avoir à attendre jusqu'à la fin) et vérifie aussi la valeur de sortie.
Avec system() vous avez aussi un contrôle direct sur une possible interprétation de méta-caractères, alors que ce n'est pas permis avec des guillemets inversés.
@ok = `grep @opts '$search_string' @filenames`;
il faut procéder ainsi :
my @ok = ();
if (open(GREP, "-|")) {
while (<GREP>) {
chomp;
push(@ok, $_);
}
close GREP;
} else {
exec 'grep', @opts, $search_string, @filenames;
}
De même qu'avec system(), il n'y a aucune intervention du shell lorsqu'on donne une liste d'arguments à exec(). D'autres exemples de ceci se trouvent dans ``Ouvertures Sûres d'un Tube'' in perlipc.
Notez que si vous êtes coincés sous Microsoft, aucune solution à ce problème vexant n'est seulement possible. Même si Perl devait émuler fork(), vous seriez toujours coincés, parce que Microsoft ne fournit aucune API du style argc/argv. Leurs API refont toujours l'analyse à partir d'une chaîne simple, ce qui est fondamentalement mauvais, mais il est peu probable que vous puissiez convaincre les Dieux de Redmond de le reconnaître et de régler ce problème pour vous.
$where = tell(LOG);
seek(LOG, $where, 0);
Si tout ce que vous voulez faire est prétendre d'être telnet mais n'avez pas du tout besoin de la négociation initiale, alors l'approche classique bi-processus suffira :
use IO::Socket; # nouveau dans 5.004
$handle = IO::Socket::INET->new('www.perl.com:80')
|| die "can't connect to port 80 on www.perl.com: $!";
$handle->autoflush(1);
if (fork()) { # XXX: undef signifie un échec
select($handle);
print while <STDIN>; # tout ce qui vient de stdin va vers la prise
} else {
print while <$handle>; # tout ce qui vient de la prise va vers stdout
}
close $handle;
exit;
Pour vraiment altérer la ligne de commande visible, on peut assigner quelque chose à la variable $0, ainsi que documenté dans perlvar. Cependant, cela ne marchera pas sur tous les systèmes d'exploitation. Des logiciels démons comme sendmail y placent leur état, comme dans :
$0 = "orcus [accepting connections]";
fork && exit;
Le module Proc::Daemon, disponible sur le CPAN, fournit une fonction qui réalise ces actions pour vous.
if (-t STDIN && -t STDOUT) {
print "Now what? ";
}
Sur les systèmes POSIX, on peut tester son groupe de processus pour voir s'il correspond au groupe du terminal de contrôle comme suit :
use POSIX qw/getpgrp tcgetpgrp/;
open(TTY, "/dev/tty") or die $!;
$tpgrp = tcgetpgrp(fileno(*TTY));
$pgrp = getpgrp();
if ($tpgrp == $pgrp) {
print "foreground\n";
} else {
print "background\n";
}
$rc = system($cmd);
if ($rc & 127) { die "signal death" }
use Fcntl;
sysopen(FH, "/tmp/somefile", O_WRONLY|O_NDELAY|O_CREAT, 0644)
or die "can't open /tmp/somefile: $!":
perl Makefile.PL
make
make test
make install
Si votre version de perl est compilée sans support pour le chargement dynamique de librairies, alors il vous faudra remplacer l'étape 3 (make) par make perl et vous obtiendrez un nouvel exécutable perl avec votre extension liée statiquement.
Voir ExtUtils::MakeMaker pour plus de détails sur les extensions de fabrication. Voir aussi la question suivante.
1) "do $file" ressemble à "eval `cat $filè", sauf que le premier:
1.1: cherche dans @INC et met à jour %INC.
1.2: entoure le code eval()ué d'une portée lexicale *indépendante*.
2) "require $file" ressemble à "do $file", sauf que le premier:
2.1: s'arrange pour éviter de charger deux fois un même fichier.
2.2: lance une exception si la recherche, la compilation ou
l'exécution de $file échoue.
3) "require Module" ressemble à "require 'Module.pm'", sauf que le premier:
3.1: traduit chaque "::" en votre séparateur de répertoire.
3.2: indique au compilateur que Module est une classe,
passible d'appels indirects.
4) "use Module" ressemble à "require Module", sauf que le premier:
4.1: charge le module à la phase de compilation, et non à l'exécution.
4.2: importe ses symboles et sémantiques dans la paquetage courant.
En général, on utilise "use" avec un module Perl adéquat.
perl Makefile.PL PREFIX=/u/mydir/perl
puis, ou bien positionnez la variable d'environnement PERL5LIB avant de lancer les scripts utilisant ces modules/bibliothèques (voir perlrun), ou bien utilisez :
use lib '/u/mydir/perl';
C'est presque la même chose que :
BEGIN {
unshift(@INC, '/u/mydir/perl');
}
sauf que le module lib vérifie les sous-répertoires dépendants de la machine. Voir le pragma lib de Perl pour plus d'information.
use FindBin;
use lib "$FindBin::Bin";
use vos_propres_modules;
la variable d'environnement PERLLIB
la variable d'environnement PERL5LIB
l'option perl -Idir sur la ligne de commande
le pragma use lib, comme dans
use lib "$ENV{HOME}/ma_propre_biblio_perl";
Ce dernier est particulièrement utile, parce qu'il prend en compte les fichiers propres à une architecture donnée. Le module pragmatique lib.pm a été introduit dans la version 5.002 de Perl.
When included as an integrated part of the Standard Distribution of Perl or of its documentation (printed or otherwise), this works is covered under Perl's Artistic Licence. For separate distributions of all or part of this FAQ outside of that, see perlfaq.
Irrespective of its distribution, all code examples here are public domain. You are permitted and encouraged to use this code and any derivatives thereof in your own programs for fun or for profit as you see fit. A simple comment in the code giving credit to the FAQ would be courteous but is not required.
Traduit de l'anglais par Raphaël Manfredi. Cette traduction est :
Copyright (c) 1999 Raphaël Manfredi. Tous droits réservés.
Cette oeuvre est couverte par la licence artistique de Perl lorsqu'elle fait partie intégrante de la distribution standard de Perl, ou de sa documentation (imprimée ou autre). Pour d'autres modes de distribution de cette FAQ, en partie ou en totalité, voir perlfaq.
Indépendamment de sa distribution, tous les exemples de code sont placés dans le domaine publique. Vous êtes autorisés et encouragés à utiliser ce code et ses dérivés dans vos propres programmes, realisés soit pour le plaisir, soit par profit, comme bon vous semble. Une simple mention dans le code créditant cette FAQ serait une marque de politesse mais n'est pas obligatoire.