                 Livre de chevet du developpeur FreeBSD

  Le groupe du projet de documentation FreeBSD

   Copyright (c) 2000, 2001, 2002, 2003 Le groupe du projet de
   documentation FreeBSD

   Bienvenue dans le livre de chevet du developpeur

   Version franc,aise de Frederic Praca
   <frederic.praca@freebsd-fr.org>.

   N.d.T.: La version franc,aise est publiee sur le serveur World
   Wide Web du groupe de traduction en langue franc,aise de la
   documentation de FreeBSD.

   N.d.T.: Contactez la liste de diffusion du groupe d'utilisateurs
   francophones de FreeBSD <freebsd-questions@FreeBSD-fr.org> si vous
   voulez collaborer `a la traduction.

   La traduction de ce manuel est "en cours". Dans la table des
   matieres ci-dessous:

     * Les chapitres marques de deux asterisques sont en cours de
       traduction.

     * Les chapitres marques de trois asterisques sont `a traduire.

     * L'asterisque simple est reserve aux chapitres et sections en
       cours de redaction dans la version U.S.

   Redistribution and use in source (XML DocBook) and 'compiled'
   forms (XML, HTML, PDF, PostScript, RTF and so forth) with or
   without modification, are permitted provided that the following
   conditions are met:

    1. Redistributions of source code (XML DocBook) must retain the
       above copyright notice, this list of conditions and the
       following disclaimer as the first lines of this file
       unmodified.

    2. Redistributions in compiled form (transformed to other DTDs,
       converted to PDF, PostScript, RTF and other formats) must
       reproduce the above copyright notice, this list of conditions
       and the following disclaimer in the documentation and/or other
       materials provided with the distribution.

     Important : THIS DOCUMENTATION IS PROVIDED BY THE FREEBSD
     DOCUMENTATION PROJECT "AS IS" AND ANY EXPRESS OR IMPLIED
     WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD
     DOCUMENTATION PROJECT BE LIABLE FOR ANY DIRECT, INDIRECT,
     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     THIS DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
     DAMAGE.

     --------------------------------------------------------------

   Table des matieres

   I. Introduction

                1. Developper sous FreeBSD

                2. La vision BSD

                3. Survol de l'architecture

                4. L'agencement de /usr/src

   II. Les fondamentaux

                5. Outils de programmation

                             5.1. Synopsis

                             5.2. Introduction

                             5.3. Introduction `a la programmation

                             5.4. Compiler avec cc

                             5.5. Make

                             5.6. Deverminer

                             5.7. Utiliser Emacs comme environnement
                             de developpement

                             5.8. Pour aller plus loin

                6. Programmation securisee

                             6.1. Synopsis

                             6.2. Methodologie de developpement
                             securise

                             6.3. Depassement de capacite

                             6.4. Les problemes lies `a SetUID

                             6.5. Limiter l'environnement de votre
                             programme

                             6.6. La confiance

                             6.7. Les conditions de course

   III. Le noyau

                7. Histoire du noyau Unix

                8. Notes sur le verrouillage

                             8.1. Les mutex

                             8.2. Les verrous du gestionnaire de
                             verrous (Lock Manager)

                             8.3. Variables protegees atomiquement

   IV. Memoire et memoire virtuelle

                9. La memoire virtuelle

   V. Systeme E/S (Entrees/Sorties)

                10. UFS

   VI. Communication InterProcessus (IPC)

                11. Les signaux

   VII. Le reseau

                12. Les prises

   VIII. Systemes de fichiers en reseau

                13. AFS

   IX. Gestion du terminal

                14. Syscons

   X. Le son

                15. OSS

   XI. Pilotes de peripherique

                16. Ecrire des pilotes de peripheriques pour FreeBSD

                             16.1. Introduction

                             16.2. L'editeur de liens dynamiques du
                             noyau - KLD

                             16.3. Acceder au pilote d'un
                             peripherique

                             16.4. Les peripheriques caracteres

                             16.5. Pilotes Reseau

                17. Les peripheriques PCI

                             17.1. Rechercher et rattacher

                             17.2. Les ressources du bus

                18. Controleurs SCSI Common Access Method (CAM) **

                             18.1. En cours de traduction

                19. Peripheriques USB ***

                             19.1. Introduction

                20. NewBus

   XII. Architectures

                21. IA-32

                22. Alpha

                23. IA-64

   XIII. Deverminage

                24. Truss

   XIV. Les couches de compatibilite

                25. Linux

   XV. Bibligraphie

                Bibliographie

   Liste des tableaux

   8-1. Liste du mutex

   8-2. lockmgr(9) List de verrou

   Liste des exemples

   5-1. Un fichier exemple .emacs

                            I. Introduction

   Table des matieres

   1. Developper sous FreeBSD

   2. La vision BSD

   3. Survol de l'architecture

   4. L'agencement de /usr/src

     --------------------------------------------------------------

                  Chapitre 1. Developper sous FreeBSD

   Ce document a pour but de decrire FreeBSD comme une plateforme de
   developpement, la vision de BSD, un survol de l'architecture,
   l'agencement de /usr/src, l'histoire, etc.

   Merci d'adopter FreeBSD comme votre plateforme de developpement !
   Nous esperons qu'elle ne vous laissera pas tomber.

     --------------------------------------------------------------

                       Chapitre 2. La vision BSD

     --------------------------------------------------------------

                  Chapitre 3. Survol de l'architecture

     --------------------------------------------------------------

                  Chapitre 4. L'agencement de /usr/src

   Le code source complet de FreeBSD est disponible depuis notre base
   CVS publique. Le code source est normalement installe sous
   /usr/src qui contient les sous-repertoires suivants.



   Repertoire                       Description                       
   bin/        Sources des fichiers de /bin                           
   contrib/    Sources des fichiers des logiciels fournis             
               ("contributed").                                       
   crypto/     Sources du DES                                         
   etc/        Sources des fichiers de /etc                           
   games/      Sources des fichiers de /usr/games                     
   gnu/        Utilitaires sous licence publique GNU                  
   include/    Sources des fichiers de /usr/include                   
   kerberosIV/ Sources de Kerbereros version IV                       
   kerberos5/  Sources de Kerbereros version 5                        
   lib/        Sources des fichiers de /usr/lib                       
   libexec/    Sources des fichiers de /usr/libexec                   
   release/    Fichiers requis pour la production d'une version       
               stable de FreeBSD                                      
   sbin/       Sources des fichiers de /sbin                          
   secure/     Sources de FreeSec                                     
   share/      Sources des fichiers de /sbin                          
   sys/        Fichiers source du noyau                               
   tools/      Outils utilises pour la maintenance et les tests de    
               FreeBSD                                                
   usr.bin/    Sources des fichiers de /usr/bin                       
   usr.sbin/   Sources des fichiers de /usr/sbin                      

                          II. Les fondamentaux

   Table des matieres

   5. Outils de programmation

   6. Programmation securisee

     --------------------------------------------------------------

                  Chapitre 5. Outils de programmation

   Ce chapitre a ete ecrit par James Raynard. Les modifications pour
   le livre de chevet du developpeur par Murray Stokely.

     --------------------------------------------------------------

5.1. Synopsis

   Ce document est une introduction `a l'utilisation de quelques
   outils de programmation fournis avec FreeBSD, toutefois tout sera
   applicable `a beaucoup d'autres versions d'Unix. Cette
   introduction n'essaye pas de decrire la programmation dans le
   detail. La plupart du document suppose que vous possedez peu ou
   pas de connaissances en programmation, esperant que les
   programmeurs trouveront un interet dans ce document.

     --------------------------------------------------------------

5.2. Introduction

   FreeBSD offre un excellent environnement de developpement. Des
   compilateurs pour C, C++ et Fortran ainsi qu'un assembleur sont
   fournis avec le systeme de base, sans parler de l'interpreteur
   PERL ni des outils classiques Unix comme sed et awk. Si cela n'est
   pas suffisant, il y a encore plus de compilateurs et
   d'interpreteurs dans la collection des logiciels portes. FreeBSD
   est compatible avec les standards comme POSIX et C ANSI, aussi
   bien qu'avec son propre heritage BSD, aussi il est possible
   d'ecrire des applications qui se compileront et s'executeront avec
   peu ou pas de modifications sur un grand nombre de plateformes.

   Toutefois, toute cette puissance peut etre plutot ecrasante au
   premier abord si vous n'avez jamais ecrit de programmes sur une
   plateforme Unix auparavant. Ce document a pour but de vous aider
   `a commencer, sans entrer trop loin dans des sujets plus avances.
   L'intention est que ce document devrait vous donner assez de bases
   pour etre capable de donner du sens `a la documentation.

   La majeure partie du document requiert peu ou pas de connaissance
   de la programmation, bien qu'il suppose une competence de base
   dans l'utilisation d'Unix et dans la bonne volonte d'apprendre !

     --------------------------------------------------------------

5.3. Introduction `a la programmation

   Un programme est un ensemble d'instructions qui disent `a
   l'ordinateur de faire diverses choses; quelques fois,
   l'instruction qu'il a `a executer depend de ce qui s'est passe
   lors de l'execution d'une instruction precedente. Cette section
   donne un aperc,u des deux manieres par lesquelles vous pouvez
   donner ces instructions, ou "commandes" comme elles sont
   habituellement nommees. Une fac,on utilise un interpreteur,
   l'autre un compilateur. Comme les langages humains sont trop
   difficiles `a comprendre sans ambiguite par un ordinateur, les
   commandes sont habituellement ecrites dans un langage ou un autre
   specialement conc,us pour cet usage.

     --------------------------------------------------------------

  5.3.1. Les interpreteurs

   Avec un interpreteur, le langage va avec un environnement ou vous
   entrez des commandes `a un invite de commandes et l'environnement
   les execute pour vous. Pour des programmes plus compliques, vous
   pouvez entrer les commandes dans un fichier et demander `a
   l'interpreteur de charger le fichier et d'executer les commandes
   qui sont `a l'interieur. Si quoique ce soit se passe mal, beaucoup
   d'interpreteurs vous enverrons dans un devermineur pour vous aider
   `a debusquer le probleme.

   L'avantage de cela est que vous pouvez voir les resultats de vos
   commandes immediatement, et les erreurs peuvent etre corrigees
   facilement. Le plus gros desavantage arrive quand vous voulez
   partager vos programmes avec d'autres personnes. Ils doivent avoir
   le meme interpreteur ou bien vous devez avoir un moyen de leur
   donner, et ils doivent comprendre comment l'utiliser. Par
   ailleurs, les utilisateurs pourraient ne pas apprecier d'etre
   renvoyes dans un devermineur s'ils ont appuye sur la mauvaise
   touche ! D'un point de vue performance, les interpreteurs peuvent
   utiliser beaucoup de memoire et generalement ne generent pas un
   code aussi efficace que les compilateurs.

   A mon avis, les langages interpretes sont le meilleur moyen pour
   demarrer si vous n'avez jamais programme. Ce genre d'environnement
   se trouve typiquement avec des langages comme Lisp, Smalltalk,
   Perl et Basic. Il peut aussi etre dit que l'interpreteur de
   commandes Unix (sh, csh) est lui-meme un interpreteur, et beaucoup
   de gens ecrivent en fait des "scripts" (procedures) pour
   l'interpreteur pour les aider dans diverses taches "domestiques"
   sur leur machine. En effet, une partie de la philosophie d'origine
   d'Unix etait de fournir plein de petits programmes utilitaires qui
   pouvaient etre lies ensemble dans des procedures pour effectuer
   des taches utiles.

     --------------------------------------------------------------

  5.3.2. Les interpreteurs disponibles avec FreeBSD

   Voici la liste des interpreteurs qui sont disponibles sous la
   forme de   logiciels pre-compiles pour FreeBSD, avec une breve
   description de quelques uns des langages interpretes les plus
   populaires.

   Pour obtenir un de ces logiciels pre-compiles, tout ce que vous
   avez `a faire est de cliquer sur le lien du logiciel et d'executer

 # pkg_add nom du logiciel
      

   en tant que super-utilisateur. Evidemment, vous aurez besoin d'un
   FreeBSD 2.1.0 ou plus en etat de marche pour que le logiciel
   fonctionne !

   BASIC

           Abbreviation de "Beginner's All-purpose Symbolic
           Instruction Code" (code d'instruction symbolique tout
           usage pour le debutant). Developpe dans les annees 50 pour
           apprendre aux etudiants d'universite `a programmer et
           fourni avec tout ordinateur qui se respecte dans les
           annees 80, BASIC a ete le premier langage de programmation
           pour beaucoup de programmeurs. Il est aussi le fondement
           meme du Visual Basic.

           L'interpreteur Basic Bywater et l'interpreteur Basic de
           Phil Cockroft (anciennement Rabbit Basic) sont disponibles
           pour FreeBSD sous forme de logiciels pre-compiles

   Lisp

           Un langage qui a ete developpe `a la fin des annees 50
           comme une alternative aux langages "devoreurs de calculs"
           qui etaient tres populaires `a l'epoque. Plutot qu'etre
           base sur les nombres, Lisp est base sur les listes; en
           fait le nom est l'abbreviation de "List Processing". Tres
           populaire en IA (Intelligence Artificielle).

           Lisp est un langage extremement puissant et sophistique ,
           mais peut etre assez lourd et peu maniable.

           FreeBSD a GNU Common Lisp de disponible sous la forme d'un
           logiciel pre-compile.

   Perl

           Tres populaire aupres des administrateurs systeme pour la
           redaction de procedures; aussi souvent utilise sur les
           serveurs Internet pour l'ecriture de procedures CGI.

           La derniere version (version 5) est fournie avec FreeBSD.

   Scheme

           Un derive du Lisp qui est plutot plus compact et plus
           propre que le Common Lisp. Populaire dans les universites
           etant suffisamment simple `a apprendre aux etudiants comme
           premier langage , il possede un niveau d'abstraction
           suffisamment important pour etre utilise dans le travail
           de recherche.

           On trouve pour FreeBSD les logiciels pre-compiles
           interpreteur Scheme Elk, l'interpreteur Scheme du MIT et
           l'interpreteur Scheme SCM.

   Icon

           Le langage de programmation Icon.

   Logo

           l'interpreteur Logo de Brian Harvey.

   Python

           Le langage oriente objet Python

     --------------------------------------------------------------

  5.3.3. Les compilateurs

   Les compilateurs sont plutot differents entre eux. Tout d'abord,
   vous ecrivez votre code dans un fichier (ou des fichiers) en
   utilisant un editeur de texte. Vous executez ensuite le
   compilateur et verifiez qu'il accepte votre programme. S'il ne
   compile pas, grincez des dents et retournez `a l'editeur; s'il
   compile et vous donne un programme, vous pouvez executer ce
   dernier `a l'invite de commande ou dans un devermineur pour voir
   s'il fonctionne correctement. [1]

   Evidemment, ce n'est pas aussi direct que d'utiliser un
   interpreteur. Toutefois cela vous permet de faire beaucoup de
   choses qui sont difficiles ou meme impossibles avec un
   interpreteur, comme ecrire du code qui interagit de fac,on proche
   du systeme d'exploitation ou meme d'ecrire votre propre systeme
   d'exploitation ! C'est aussi utile si vous avez besoin d'ecrire du
   code tres efficace, etant donne que le compilateur peut prendre
   son temps et optimiser le code, ce qui ne serait pas acceptable
   avec un interpreteur. Et distribuer un programme ecrit pour un
   compilateur est habituellement plus evident qu'un ecrit pour un
   interpreteur-vous pouvez juste donner une copie de l'executable,
   en supposant que l'utilisateur possede le meme systeme
   d'exploitation que vous.

   Les langages compiles incluent Pascal, C et C++. C et C++ sont des
   langages plutot impitoyables et conviennent mieux aux programmeurs
   experimentes; Pascal, d'autre part, a ete conc,u comme un langage
   educatif, et est un assez bon langage pour commencer.
   Malheureusement, FreeBSD ne possede aucun support Pascal, excepte
   pour un convertisseur Pascal vers C dans les logiciels portes.

   Le cycle edition-compilation-execution-deverminage etant
   relativement penible lors de l'utilisation de programmes separes,
   beaucoup de fabricants de compilateur ont produit des
   environnements de developpement integres (ou IDE pour Integrated
   Development Environments et EDI dans la langue de Moliere).
   FreeBSD ne possede pas d'EDI tel quel; toutefois il est possible
   d'utiliser Emacs `a cet effet. Ceci est vu dans Section 5.7.

     --------------------------------------------------------------

5.4. Compiler avec cc

   Cette section traite uniquement du compilateur GNU pour C et C++,
   celui-ci faisant partie du systeme FreeBSD de base. Il peut etre
   invoque soit par cc ou gcc. Les details de production d'un
   programme avec un interpreteur varient considerablement d'un
   interpreteur `a l'autre, et sont habituellement bien couverts par
   la documentation et l'aide en ligne de l'interpreteur.

   Une fois que vous avez ecrit votre chef d'oeuvre, la prochaine
   etape est de le convertir en quelque chose qui s'executera
   (esperons !) sur FreeBSD. Cela implique normalement plusieurs
   etapes, realisees chacune par un programme different.

    1. Pre-traiter votre code source pour retirer les commentaires et
       faire d'autres trucs comme developper (expanser) les macros en
       C.

    2. Verifier la syntaxe de votre code source pour voir si vous
       avez obei aux regles du langage. Si vous ne l'avez pas fait,
       il se plaindra !

    3. Convertir le code source en langage assembleur- cela est
       vraiment proche du code machine, mais reste comprehensible par
       des humains. Pretendument. [2]

    4. Convertir le langage assembleur en code machine -ouais, on
       parle de bits et d'octets, de uns et de zeros.

    5. Verifier que vous avez utilise des choses comme des fonctions
       et des variables globales de fac,on consistente. Par exemple,
       si vous avez appele une fonction inexistente, le compilateur
       se plaindra.

    6. Si vous essayez de produire un executable depuis plusieurs
       fichiers de code source, resoudre comment les faire
       fonctionner ensemble.

    7. Resoudre comment produire quelque chose que le chargeur au vol
       du systeme sera capable de charger en memoire et executer.

    8. Finalement, ecrire l'executable dans le systeme de fichiers.

   Le mot compilation est souvent utilise pour les etapes 1 `a 4
   seules-les autres correspondent au terme liaison. Quelquefois,
   l'etape 1 est appelee pre-traitement et les etapes 3-4 assemblage.

   Heureusement, la plupart de ces details vous sont caches, etant
   donne que cc est un frontal qui s'occupe d'appeler tous les
   programmes avec les arguments corrects pour vous; tapez simplement

 % cc foobar.c
    

   compilera foobar.c avec toutes les etapes au-dessus. Si vous avez
   plus d'un fichier `a compiler, faites simplement quelque chose
   comme

 % cc foo.c bar.c
    

   Notez que la verification de syntaxe n'est que cela-verifier la
   syntaxe. Cela ne verifiera pas les erreurs de logique que vous
   pouvez avoir faites, comme mettre le programme en boucle infinie
   ou utiliser un tri `a bulles quand vous devriez utiliser un tri
   binaire. [3]

   Il y a beaucoup d'options pour cc, qui qui se trouvent toutes dans
   les pages de manuel en ligne. Voici quelques unes des plus
   importantes, avec des exemples illustrant leur utilisation.

   -o nom_du_fichier

           Le nom de sortie du fichier. Si vous n'utilisez pas cette
           option, cc produira un executable appele a.out. [4]

 % cc foobar.c               l'executable est a.out
 % cc -o foobar foobar.c     l'executable est foobar
            

   -c

           Compile juste le fichier, ne le lie pas. Utile pour les
           programmes jouets dont vous voulez juste verifier la
           syntaxe, ou si vous utilisez un Makefile.

 % cc -c foobar.c
            

           Cela va produire un fichier objet (pas un executable)
           appele foobar.o. Celui-ci peut etre lie ensuite avec
           d'autres fichiers objets pour produire un executable.

   -g

           Cree une version de deverminage de l'executable. Cela
           oblige le compilateur `a placer des informations dans
           l'executable comme telle ligne du fichier source
           correspond `a tel appel de fonction. Un devermineur peut
           utiliser cette information pour vous montrer le code
           source au fur et `a mesure que vous avancez pas `a pas
           dans le programme, ce qui est tres utile; le desavantage
           est que toutes ces informations supplementaires rendent le
           programme plus gros. Normalement, vous compilez avec
           l'option -g quand vous etes en train de developper un
           programme et compilez ensuite une "version de production"
           sans -g quand vous etes satisfait du fonctionnement.

 % cc -g foobar.c
            

           Cela va produire une version de deverminage du programme
           foobar. [5]

   -O

           Cree une version optimisee de l'executable. Le compilateur
           effectue differents trucs malins pour essayer de produire
           un executable qui s'execute plus rapidement que normal.
           Vous pouvez ajouter un nombre apres l'option -O pour
           specifier un niveau d'optimisation plus important, mais
           cela vous expose souvent aux bogues dans l'optimiseur du
           compilateur. Par exemple, la version de cc fournit avec la
           version 2.1.0 FreeBSD est connue pour produire du mauvais
           code avec l'option -O2 dans certaines circonstances.

           L'optimisation est habituellement activee uniquement lors
           de la compilation d'une version de production.

 % cc -O -o foobar foobar.c
            

           Cela va produire une version optimisee de foobar.

   Les trois prochaines options vont forcer cc `a verifier que votre
   code est conforme au standard international en cours, se referant
   souvent `a la norme ANSI, qui pour dire precisement est un
   standard ISO.

   -Wall

           Active tous les avertissements que les auteurs de cc
           pensent valoir le coup. Malgre le nom, il n'active pas
           tous les avertissements dont cc est capable.

   -ansi

           Desactive la plupart, mais pas toutes, des
           caracteristiques du C fournies par cc qui sont non-ANSI .
           Malgre le nom, cela ne garantit pas strictement que votre
           code sera conforme au standard.

   -pedantic

           Desactive toutes les caracteristiques de cc qui ne sont
           pas ANSI .

   Sans ces options, cc vous permettrait d'utiliser quelques
   extensions au standard non-standards. Quelques unes de celles-ci
   sont tres utiles, mais ne fonctionneront pas avec d'autres
   compilateurs -en fait, un des principaux buts du standard est de
   permettre aux gens d'ecrire du code qui fonctionnera avec
   n'importe quel compilateur sur n'importe quel systeme. Cela est
   connu sous le nom de code portable.

   Generalement, vous devriez essayer de faire votre code aussi
   portable que possible, sinon vous pourriez avoir a re-ecrire
   totalement votre programme plus tard pour le faire fonctionner
   autre part-et qui sait ce que vous utiliserez dans quelques
   annees?

 % cc -Wall -ansi -pedantic -o foobar foobar.c
      

   Cela produira un executable foobar apres avoir verifie que
   foobar.c est conforme au standard.

   -llibrairie

           Specifie une librairie de fonctions `a utiliser lors de
           l'edition des liens.

           L'exemple le plus commun de cela est lors de la
           compilation d'un programme qui utilise quelques fonctions
           mathematiques en C. A l'inverse de la plupart des
           plateformes, celles-ci se trouvent dans une librairie
           standard du C et vous devez dire au compilateur de
           l'ajouter.

           La regle est que si une librairie est appelee
           libquelque_chose.a, vous donnez `a cc l'argument
           -lquelque_chose. Par exemple, la librairie des fonctions
           mathematiques est libm.a, aussi vous donnez `a cc le
           parametre -lm. Un "piege" habituel avec la librairie math
           est qu'elle doit etre la derniere sur la ligne de
           commande.

 % cc -o foobar foobar.c -lm
            

           Cela va lier les fonctions de la librairie math `a
           l'interieur de foobar.

           Si vous compilez du C++; vous devrez ajouter -lg++, ou
           -lstdc++ si vous utilisez FreeBSD 2.2 ou ulterieur, `a la
           ligne de commande de cc pour lier avec les fonctions de la
           librairie C++. Alternativement, vous pouvez utiliser c++
           plutot que cc, qui fait tout cela pour vous. c++ peut
           aussi etre invoque par g++ sur FreeBSD.

 % cc -o foobar foobar.cc -lg++     Pour FreeBSD 2.1.6 et anterieur
 % cc -o foobar foobar.cc -lstdc++  Pour FreeBSD 2.2 et ulterieur
 % c++ -o foobar foobar.cc
            

           Chacune de ces commandes va produire un executable foobar
           `a partir du fichier source C++ foobar.cc. Notez que, sur
           les systemes Unix , les fichiers source C++ se terminent
           traditionnellement en .C, .cxx ou .cc, plutot que le style
           MS-DOS .cpp (qui etait dej`a utilise pour autre chose).
           gcc a utilise cela pour trouver le type de compilateur `a
           utiliser sur le fichier source; toutefois, cette
           restriction ne s'applique plus, aussi vous pouvez
           maintenant appeler vos fichiers C++ .cpp en toute impunite
           !

     --------------------------------------------------------------

  5.4.1. Questions et problemes usuels sur cc

   5.4.1.1. J'essaye d'ecrire un programme qui utilise la fonction
   sin() et je rec,ois l'erreur suivante. Que cela signifie-t-il ?

   5.4.1.2. J'ai ecrit un programme simple pour m'exercer `a
   l'utilisation de l'option -lm. Tout ce qu'il fait est d'elever 2,1
   `a la puissance 6.

   5.4.1.3. Alors comment puis-je le reparer?

   5.4.1.4. J'ai compile un fichier appele foobar.c et je ne trouve
   pas d'executable appele foobar. Ou est-il parti?

   5.4.1.5. OK, j'ai un executable appele foobar, je peux le voir en
   executant ls, mais quand je tape foobar `a l'invite de commandes,
   la reponse est qu'il n'y a pas de tel fichier. Pourquoi le systeme
   ne le trouve pas?

   5.4.1.6. J'ai appele mon executable test, mais rien ne se passe
   quand je l'execute. Que se passe-t-il?

   5.4.1.7. J'ai compile mon programme et il semble fonctionner au
   premier abord, puis il y a une erreur et le systeme a dit quelque
   chose comme "core dumped". Que cela signifie-t-il?

   5.4.1.8. Fascinant, mais que suis-je suppose faire ?

   5.4.1.9. Quand mon programme a genere un fichier core, il a parle
   d'une erreur "segmentation fault". Qu'est-ce que c'est ?

   5.4.1.10. Des fois quand je rec,oit une erreur "core dump", il est
   precise "bus error". Il est dit dans mon livre Unix qu'il s'agit
   d'un probleme materiel mais l'ordinateur semble toujours
   fonctionner. Est-ce vrai ?

   5.4.1.11. Toute cette affaire de fichier core semble etre assez
   utile, si je peux le faire apparaitre quand je le desire. Puis-je
   faire cela, ou dois-je attendre la prochaine erreur ?

   5.4.1.1. J'essaye d'ecrire un programme qui utilise la fonction
   sin() et je rec,ois l'erreur suivante. Que cela signifie-t-il ?

 /var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment
              

   Lors de l'utilisation des fonctions mathematiques comme sin(),
   vous devez dire `a cc de lier avec la librairie math, comme :

 % cc -o foobar foobar.c -lm
              

   5.4.1.2. J'ai ecrit un programme simple pour m'exercer `a
   l'utilisation de l'option -lm. Tout ce qu'il fait est d'elever 2,1
   `a la puissance 6.

 #include <stdio.h>

 int main() {
         float f;

         f = pow(2.1, 6);
         printf("2.1 ^ 6 = %f\n", f);
         return 0;
 }
              

   j'ai effectue la compilation comme suit :

 % cc temp.c -lm
              

   et comme explique ici, mais j'obtiens ceci quand je l'execute :

 % ./a.out
 2.1 ^ 6 = 1023.000000
              

   Ce n'est pas la reponse correcte ! Que se passe-t-il ?

   Quand le compilateur voit que vous appelez une fonction, il
   verifie s'il a dej`a un prototype pour celle-ci. S'il ne l'a pas
   vu, il suppose que la fonction retourne un int, ce qui n'est
   absolument pas ce que vous voulez ici.

   5.4.1.3. Alors comment puis-je le reparer?

   Les prototypes des fonctions mathematiques sont dans math.h. Si
   vous incluez ce fichier, le compilateur sera capable de trouver le
   prototype et il arretera de faire des trucs etranges `a vos
   calculs!

 #include <math.h>
 #include <stdio.h>

 int main() {
 ...
              

   Apres avoir recompile comme precedemment, executez :

 % ./a.out
 2.1 ^ 6 = 85.766121
              

   Si vous utilisez quelques fonctions mathematiques que ce soit,
   incluez toujours math.h et n'oubliez pas de lier avec la librairie
   math.

   5.4.1.4. J'ai compile un fichier appele foobar.c et je ne trouve
   pas d'executable appele foobar. Ou est-il parti?

   Souvenez-vous, cc appellera l'executable a.out sauf si vous lui
   dites de faire autrement. Utilisez l'option -o nomfichier:

 % cc -o foobar foobar.c
              

   5.4.1.5. OK, j'ai un executable appele foobar, je peux le voir en
   executant ls, mais quand je tape foobar `a l'invite de commandes,
   la reponse est qu'il n'y a pas de tel fichier. Pourquoi le systeme
   ne le trouve pas?

   A l'inverse de MS-DOS, Unix ne regarde pas dans le repertoire
   courant lorsqu'il essaye de trouver un executable que vous voulez
   executer, sauf si vous lui avez dit de le faire. Vous pouvez soit
   taper ./foobar, ce qui signifie "execute le fichier nomme foobar
   dans le repertoire courant", soit changer votre variable
   d'environnement PATH de fac,on `a ce qu'elle ressemble `a quelque
   chose comme

 bin:/usr/bin:/usr/local/bin:.
              

   Le point `a la fin signifie "regarde dans le repertoire courant
   s'il n'est dans aucun autre".

   5.4.1.6. J'ai appele mon executable test, mais rien ne se passe
   quand je l'execute. Que se passe-t-il?

   La plupart des systemes Unix ont un programme appele test dans
   /usr/bin et l'interpreteur prend celui-ci avant de verifier dans
   le repertoire courant. Soit vous tapez

 % ./test
              

   soit vous choisissez un meilleur nom pour votre programme !!

   5.4.1.7. J'ai compile mon programme et il semble fonctionner au
   premier abord, puis il y a une erreur et le systeme a dit quelque
   chose comme "core dumped". Que cela signifie-t-il?

   Le nom core dump date des tous premiers jours d'Unix, quand les
   machines utilisaient la memoire centrale[6]pour stocker les
   donnees. Simplement, si le programme a echoue sous certaines
   conditions, le systeme va ecrire le contenu de la memoire centrale
   sur le disque dans un fichier appele core, que le programmeur peut
   ensuite examiner de pres pour trouver ce qui s'est mal passe.

   5.4.1.8. Fascinant, mais que suis-je suppose faire ?

   Utilisez gdb pour analyser le fichier core (voir Section 5.6).

   5.4.1.9. Quand mon programme a genere un fichier core, il a parle
   d'une erreur "segmentation fault". Qu'est-ce que c'est ?

   Cela signifie simplement que votre programme a essaye d'effectuer
   une operation illegale sur la memoire; Unix est conc,u pour
   proteger le systeme d'exploitation et les autres programmes des
   programmes crapuleux.

   Les causes habituelles de cela sont :

     * Essayer d'ecrire dans un pointeur NULL, par exemple

 char *foo = NULL;
 strcpy(foo, "bang!");
                

     * Utiliser un pointeur qui n'a pas ete initialise, par exemple

 char *foo;
 strcpy(foo, "bang!");
                

       Le pointeur va avoir une valeur aleatoire qui avec de la
       chance, pointera dans une zone de la memoire qui n'est pas
       disponible pour votre programme et le noyau va tuer votre
       programme avant qu'il ne fasse des dommages. Si vous etes
       malchanceux, il pointera quelque part dans votre propre
       programme et alterera une de vos structures de donnees,
       faisant planter votre programme mysterieusement.

     * Essayer d'acceder la memoire au-del`a de la fin d'un tableau,
       par exemple

 int bar[20];
 bar[27] = 6;
                

     * Essayer de stocker quelque chose dans la memoire en lecture
       seule, par exemple

 char *foo = "Ma chaine";
 strcpy(foo, "bang!");
                

       Les compilateurs Unix mettent souvent les chaines comme "Ma
       chaine" dans des zones de memoire en lecture seule.

     * Faire des trucs sales avec malloc() et free(), par exemple

 char bar[80];
 free(bar);
                

       ou

 char *foo = malloc(27);
 free(foo);
 free(foo);
                

   Faire une de ces fautes ne conduit pas toujours `a une erreur,
   mais elles sont toujours de mauvais entrainements. Certains
   systemes et compilateurs sont plus tolerants que d'autres, ce qui
   explique pourquoi des programmes qui fonctionnent bien sur un
   systeme peuvent planter si vous les essayer sur un autre.

   5.4.1.10. Des fois quand je rec,oit une erreur "core dump", il est
   precise "bus error". Il est dit dans mon livre Unix qu'il s'agit
   d'un probleme materiel mais l'ordinateur semble toujours
   fonctionner. Est-ce vrai ?

   Non, heureusement non (sauf si bien sur vous avez reellement un
   probleme materiel...). Cela est habituellement une maniere de dire
   que vous avez accede `a la memoire d'une fac,on que vous n'auriez
   pas du.

   5.4.1.11. Toute cette affaire de fichier core semble etre assez
   utile, si je peux le faire apparaitre quand je le desire. Puis-je
   faire cela, ou dois-je attendre la prochaine erreur ?

   Oui, ouvrez une autre console ou xterm, faites

 % ps
            

   pour trouver l'identifiant du processus de votre programme, et
   faites

 % kill -ABRT identifiant
            

   ou identifiant est l'identifiant du processus que vous avez
   trouve.

   Ceci est utile si votre programme est bloque dans une boucle
   infinie, par exemple. Si votre programme arrive `a bloquer le
   signal SIGABRT, il y a d'autres signaux qui ont des effets
   similaires.

   Alternativement, vous pouvez creer un fichier core depuis votre
   programme, en appelant la fonction abort(). Voir la page de manuel
   en ligne de abort(3) pour en savoir plus.

   Si vous voulez creer un fichier core depuis l'exterieur de votre
   programme, mais ne voulez pas que le processus s'arret,vous pouvez
   utiliser le programme gcore. Voir la page de manuel en ligne de
   gcore(1) pour plus d'informations.

     --------------------------------------------------------------

5.5. Make

  5.5.1. Qu'est-ce que make?

   Quand vous travaillez sur un programme simple avec seulement un ou
   deux fichiers source, taper

 % cc fichier1.c fichier2.c
      

   n'est pas si mal, mais cela devient rapidement fastidieux quand il
   y a plusieurs fichiers-et cela peut prendre du temps `a compiler
   aussi.

   Une fac,on de contourner cela est d'utiliser les fichiers objet et
   de recompiler le fichier source seulement si le code source a
   change. Aussi, nous pourrions avoir quelque chose comme c,a:

 % cc fichier1.o fichier2.o ... fichier37.c ...     

   si nous avions change le fichier fichier37.c mais aucun des autres
   depuis la dernere compilation. Cela pourrait accelerer assez bien
   la compilation mais cela ne resoud pas le probleme de la frappe au
   clavier.

   Ou nous pourrions ecrire une procedure pour resoudre ce probleme
   de frappe, mais celle-ci devrait tout re-compiler, devenant ainsi
   inefficace sur un gros projet.

   Que se passe-t-il si nous avons des centaines de fichiers source ?
   Que se passe-t-il si nous travaillons dans une equipe avec
   d'autres personnes qui oublient de nous dire quand ils ont change
   un de leurs fichiers source que nous utilisons ?

   Peut-etre pourrions nous mettre ensemble les deux solutions et
   ecrire quelque chose comme une procedure qui contiendrait quelque
   regle magique disant quand notre fichier source doit etre compile.
   Maintenant, tout ce dont nous avons besoin est un programme qui
   comprend ces regles, alors que c'est trop complique pour
   l'interpreteur.

   Ce programme s'appelle make. Il lit dans un fichier, appele un
   makefile, qui lui dit comment les differents fichiers dependent
   les uns des autres, et determine quels fichiers ont besoin d'etre
   recompiles et quels n'en ont pas besoin. Par exemple, une regle
   pourrait dire quelque chose comme "si fromboz.o est plus ancien
   que fromboz.c, cela signifie que quelqu'un a du changer fromboz.c,
   aussi il a besoin d'etre recompile." Le makefile possede aussi des
   regles pour dire `a make comment re-compiler un fichier source, en
   faisant ainsi un outil encore plus puissant.

   Les Makefiles sont typiquement stockes dans le meme repertoire que
   le source auxquels il s'appliquent, et peuvent etre appeles
   makefile, Makefile ou MAKEFILE. La plupart des programmeurs
   utilise le nom Makefile, celui-ci se trouvant proche du debut de
   la liste du contenu du repertoire ou il peut etre facilement vu.
   [7]

     --------------------------------------------------------------

  5.5.2. Exemple d'utilisation de make

   Voici un exemple tres simple de Makefile:

 foo: foo.c
         cc -o foo foo.c

   Il consiste en deux lignes, une ligne de dependance et une ligne
   de creation.

   La ligne de dependance ici consiste en le nom du programme (connu
   comme cible), suivi de deux-points puis un espace et enfin le nom
   du fichier source. Quand make lit cette ligne, il verifie si foo
   existe; s'il existe, il compare la date `a laquelle foo a ete
   modifie la derniere fois avec la date de derniere modification de
   foo.c. Si foo n'existe pas ou est plus ancien que foo.c, il
   regarde la ligne de creation pour trouver ce qu'il doit faire. En
   d'autres termes, il s'agit de la regle `a utiliser quand foo.c a
   besoin d'etre re-compile.

   La ligne de creation commence avec un tab (appuyez sur la touche
   tab) suivi de la commande que vous taperiez pour creer foo si vous
   deviez le faire `a l'invite de commandes. Si foo n'est pas `a jour
   ou n'existe pas, make execute alors cette commande pour le creer.
   En d'autres termes, il s'agit de la regle permettant `a make de
   re-compiler foo.c.

   Aussi, quand vous tapez make, il verifiera que foo est `a jour en
   respect de vos derniers changements sur foo.c. Ce principe peut
   etre etendu `a des Makefiles de plusieurs centaines de cibles-en
   fait, sur FreeBSD, il est possible de compiler un systeme
   d'exploitation entier en tapant juste make world dans le
   repertoire approprie !

   Une autre propriete utile des makefiles est que les cibles n'ont
   pas necessairement besoin d'etre des programmes. Par exemple, nous
   pourrions avoir un Makefile qui ressemble `a cela:

 foo: foo.c
         cc -o foo foo.c

 install:
         cp foo /home/moi

   Nous pouvons dire `a make quelle cible nous voulons en tapant:

 % make cible
      

   make ira seulement voir cette cible et ingorera les autres. Par
   exemple, si nous tapons make foo avec le Makefile du dessus, make
   ignorera la cible install.

   Si nous tapons juste make, make regardera toujours la premiere
   cible et s'arretera sans regarder aucune autre. Aussi, si nous
   avions tape make seul, make serait juste alle `a la cible foo,
   aurait recompile foo si necessaire et se serait arrete sans aller
   `a la cible install.

   Notez que la cible install ne depend pour l'instant de rien ! Cela
   signifie que la commande qui suit est toujours executee lorsque
   nous essayons de creer cette cible en tapant make install. Dans ce
   cas, make va copier foo dans le repertoire de l'utilisateur. Cela
   est souvent utilise par les Makefiles des applications, ainsi
   l'application peut etre installee dans le repertoire correct quand
   elle a ete correctement compilee

   Il s'agit d'un sujet legerement embrouillant `a essayer et
   expliquer. Si vous ne comprenez pas bien comment make fonctionne,
   la meilleure chose `a faire est d'ecrire un petit programme comme
   "bonjour monde" et un fichier Makefile comme le precedent et de le
   tester. Ensuite continuez en utilisant plus d'un fichier source ou
   en ayant un fichier source incluant un fichier d'en-tete. La
   commande touch est tres utile ici-elle change la date sur un
   fichier sans avoir `a l'editer.

     --------------------------------------------------------------

  5.5.3. Les Makefilesde FreeBSD

   Les Makefiles peuvent etre plutot compliques `a ecrire.
   Heureusement, les systemes BSD comme FreeBSD sont fournis avec des
   fichiers tres puissants comme partie integrante du systeme. Un
   tres bon exemple est le systeme des logiciels portes. Voici la
   partie essentielle d'un Makefile typique des logiciels portes:

 MASTER_SITES=   ftp://freefall.cdrom.com/pub/FreeBSD/LOCAL_PORTS/
 DISTFILES=      scheme-microcode+dist-7.3-freebsd.tgz

 .include <bsd.port.mk>

   Maintenant, si nous allons dans le repertoire de ce logiciel porte
   et tapons make, la chose suivante se passe :

    1. Une verification est faite pour voir si le code source de ce
       logiciel porte est dej`a dans le systeme.

    2. Si celui-ci n'y est pas, une connexion FTP `a l'URL dans
       MASTER_SITES est faite pour telecharger le source.

    3. La somme de controle (checksum) du source est calculee et
       comparee avec celle d'une bonne et connue copie du source.
       Cela est fait pour etre sur que le source n'a pas ete corrompu
       pendant le transfert.

    4. Tout changement requis pour faire fonctionner le source sur
       FreeBSD est applique- cela est connu sous le nom de
       correctif[8].

    5. Toute configuration speciale necessaire pour le source est
       faite. (Beaucoup de distributions de programmes Unix essaye de
       fonctionner quelle que soit la version d'Unix sur laquelle
       elles sont compilees et quelles que soient les
       caracteristiques optionnelles qui sont presentes-c'est ce qui
       se trouve dans le scenario des logiciels portes pour FreeBSD).

    6. Le code source pour ce programme est compile. En effet, nous
       changeons de repertoire pour le repertoire ou le source a ete
       decompresse et faisons make-le fichier Makefile du programme
       contient les informations necessaires pour construire le
       programme.

    7. Nous avons maintenant une version compilee du programme. Si
       nous le desirons, nous pouvons le tester maintenant; quand
       nous sommes confiant dans le programme, nous pouvons taper
       make install. Cela va installer le programme et ses fichiers
       de soutien necessaires au bon endroit; une entree est aussi
       creee dans la base de donnees des logiciels pre-compiles,
       ainsi le logiciel porte peut etre facilement desinstalle plus
       tard si nous changeons d'avis sur ce programme.

   Maintenant je pense que vous serez d'accord que c'est plus
   impressionnant qu'une procedure de quatre lignes !

   Le secret reside dans la derniere ligne qui dit `a make de
   regarder dans le Makefile systeme appele bsd.port.mk. Il est
   facile de fermer les yeux sur cette ligne mais c'est ici que tous
   les trucs forts se passent-quelqu'un a ecrit un Makefile qui dit
   `a make de faire tout ce qu'il y a au-dessus (plus un couple
   d'autres choses que je n'ai pas mentionnees, comme la gestion des
   erreurs) et n'importe qui peut avoir acces `a cela simplement est
   ajoutant une simple ligne dans son propre fichier Makefile !

   Si vous voulez jeter un regard sur ces Makefiles systeme, ils se
   trouvent /usr/share/mk mais il est probablement mieux d'attendre
   un moment jusqu'`a ce que vous ayez un peu d'entrainement avec les
   Makefiles car ceux-ci sont tres compliques (et si vous les lisez,
   soyez sur d'avoir un thermos de cafe fort `a portee de main !)

     --------------------------------------------------------------

  5.5.4. Utilisations plus avancees de make

   Make est un outil tres puissant et peut faire beaucoup plus que le
   simple exemple precedent ne l'a montre. Malheureusement, il y a
   differentes versions de make et elles different considerablement.
   Le meilleur moyen d'apprendre ce qu'elles peuvent faire est
   probablement de lire la documentation-heureusement cette
   introduction vous donnera la base `a partir de laquelle vous
   pourrez faire cela.

   La version de make fournies avec FreeBSD est le Berkeley make(make
   de Berkeley); il y a un cours d'instruction pour celui-ci dans
   /usr/share/doc/psd/12.make. Pour le voir, faites

 % zmore paper.ascii.gz
      

   dans ce repertoire.

   Beaucoup d'applications dans les logiciels portes utilisent GNU
   make, qui possede un tres bon ensemble de page d'"info". Si vous
   avez installe un de ces logiciels portes, GNU make aura ete
   automatiquement installe sous le nom de gmake. Il est aussi
   disponible comme logiciel porte ou logiciel pre-compile seul.

   Pour voir les pages d'info pour GNU make, vous devrez editer le
   fichier dir dans le repertoire /usr/local/info pour ajouter une
   entree pour celui-ci. Cela implique d'ajouter une ligne

  * Make: (make).                 l'utilitaire GNU Make.

   au fichier. Une fois que vous avez fait ceci, vous pouvez taper
   info et ensuite selectionner make dans le menu (ou dans Emacs,
   faites C-h i).

     --------------------------------------------------------------

5.6. Deverminer

  5.6.1. Le devermineur

   Le devermineur fourni avec FreeBSD est appele gdb (GNU debugger).
   Vous pouvez le demarrer en tapant

 % gdb nomprog
      

   bien que la plupart des gens preferent le demarrer au sein
   d'Emacs. Vous pouvez faire cela avec:

 M-x gdb RET nomprog RET
      

   Utiliser un devermineur vous permet d'executer le programme dans
   des circonstances plus controlees. Typiquement, vous pouvez
   executer le programme ligne `a ligne, inspecter la valeur des
   variables, changer cette derniere, dire au devermineur d'executer
   jusqu'`a un certain point puis de s'arreter etc... Vous pouvez
   meme vous brancher sur un programme en fonctionnement, ou charger
   un fichier core pour enqueter sur le plantage du programme. Il est
   meme possible de deverminer le noyau, quoique ce soit un peu plus
   ruse que de deverminer des applications utilisateur dont nous
   discuterons dans cette section.

   gdb dispose d'une assez bonne aide en ligne comme d'un ensemble de
   pages d'info, aussi cette section va se concentrer sur quelques
   commandes basiques.

   Finalement, si vous trouvez son interface texte non fonctionnelle,
   il y a une interface graphique pour celui-ci, xxgdb, dans la
   collection des logiciels portes.

   Cette section a pour but d'etre une introduction `a l'utilisation
   de gdb et ne couvre pas les sujets tres specialises comme le
   deverminage du noyau.

     --------------------------------------------------------------

  5.6.2. Executer un programme dans le devermineur

   Vous devrez avoir compile le programme avec l'option -g pour avoir
   la meilleure utilisation de gdb. Il fonctionnera sans mais vous ne
   verrez que le nom de la fonction dans laquelle vous vous trouvez
   plutot que son code source. Si vous voyez une ligne comme:

 ... (no debugging symbols found) ...
      

   quand gdb demarre, vous saurez que le programme n'a pas ete
   compile avec l'option -g.

   A l'invite de gdb, tapez break main. Cela dira au devermineur de
   passer le code preliminaire d'initialisation du programme et de
   demarrer au debut de votre code. Maintenant tapez run pour
   demarrer le programme-cela va demarrer au debut du code
   d'initialisation et ensuite s'arretera lors de l'appel `a main().
   (Si vous vous etes toujours demande ou main() etait appele,
   maintenant vous le savez !).

   Vous pouvez maintenant vous deplacer dans le programme ligne par
   ligne en pressant n. Si vous arrivez `a l'appel d'une fonction,
   vous pouvez entrer dans celle-ci en appuyant sur s. Une fois que
   vous etes dans l'appel de la fonction, vous pouvez retourner dans
   le code appelant en appuyant sur f. Vous pouvez aussi utiliser up
   et down pour avoir une vue rapide de l'appelant.

   Voici un exemple simple de comment detecter une erreur dans un
   programme avec gdb. Voici notre programme (avec une erreur
   deliberee):

 #include <stdio.h>

 int bazz(int anint);

 main() {
         int i;

         printf("C'est mon programme\n");
         bazz(i);
         return 0;
 }

 int bazz(int anint) {
         printf("Vous m'avez fourni %d\n", anint);
         return anint;
 }

   Le programme met i `a 5 et le passe `a une fonction bazz() qui
   imprime le nombre que nous lui avons donne.

   Puis nous compilons et executons le programme obtenu

 % cc -g -o temp temp.c
 % ./temp
 C'est mon programme
 Vous m'avez fourni 4231
      

   Ce n'etait pas ce que nous attendions ! Il est temps de voir ce
   qui se passe !

 % gdb temp
 GDB is free software and you are welcome to distribute copies of it
  under certain conditions; type "show copying" to see the conditions.
 There is absolutely no warranty for GDB; type "show warranty" for details.
 GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc.
 (gdb) break main                                passe le code d'initialisation
 Breakpoint 1 at 0x160f: file temp.c, line 9.    gdb met un point d'arret sur main()
 (gdb) run                                       Execute jusqu'`a main()
 Starting program: /home/james/tmp/temp          Le programme demarre

 Breakpoint 1, main () at temp.c:9               gdb s'arrete `a main()
 (gdb) n                                         Va `a la ligne suivante
 C'est mon programme                             Le programme ecrit
 (gdb) s                                         entre dans bazz()
 bazz (anint=4231) at temp.c:17                  gdb montre la pile
 (gdb)
      

   Arretons-nous une minute! Comment anint a eu la valeur 4231? Ne
   l'avons-nous pas mis `a 5 dans main()? Remontons dans main() et
   regardons.

 (gdb) up                                        Remonte la pile des appels
 #1  0x1625 in main () at temp.c:11              gdb montre la pile
 (gdb) p i                                       Montre la valeur de i
 $1 = 4231                                       gdb montre 4231
      

   Oh ! En regardant dans le code, nous avons oublie d'initialiser i.
   Nous aurions du mettre

 ...
 main() {
         int i;

         i = 5;
         printf("C'est mon programme\n");
 ...

   mais nous n'avions pas mis la ligne i=5;. Comme nous n'avons pas
   initialise i, il a pris le nombre se trouvant dans la zone de
   memoire quand le programme a demarre, ce qui dans ce cas etait
   4231.

     Note : gdb montre la pile chaque fois que nous entrons ou
     sortons d'une fonction, meme si nous avons utilise up et down
     pour nous deplacer dans la pile des appels. Cela montre le nom
     de la fonction et les valeurs de ses arguments, ce qui nous aide
     `a garder une trace d'ou nous sommes et de ce qui se passe. (La
     pile est une zone de stockage ou le programme stocke les
     informations sur les arguments passes aux fonctions et ou il
     doit aller quand il revient d'une fonction).

     --------------------------------------------------------------

  5.6.3. Examiner un fichier core

   Un fichier core est basiquement un fichier qui contient l'etat
   complet du processus quand il s'est plante. Dans "le bon vieux
   temps", les programmeurs devait imprimer des listings en
   hexadecimal de fichiers core et transpirer sur leur manuels de
   code machine, mais la vie est maintenant un peu plus facile. Par
   chance, sous FreeBSD et les autres systemes 4.4BSD, un fichier
   core est appele nomprog.core plutot que juste core, pour mieux
   savoir `a quel programme appartient un fichier core.

   Pour examiner un fichier core, demarrez gdb de fac,on habituel.
   Plutot que de taper break ou run, tapez

 (gdb) core nomprog.core
      

   Si vous n'etes pas dans le meme repertoire que le fichier core,
   vous devrez faire dir /path/to/core/file d'abord.

   Vous devriez voir quelque chose comme cela:

 % gdb a.out
 GDB is free software and you are welcome to distribute copies of it
  under certain conditions; type "show copying" to see the conditions.
 There is absolutely no warranty for GDB; type "show warranty" for details.
 GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc.
 (gdb) core a.out.core
 Core was generated by `a.out'.
 Program terminated with signal 11, Segmentation fault.
 Cannot access memory at address 0x7020796d.
 #0  0x164a in bazz (anint=0x5) at temp.c:17
 (gdb)
      

   Dans ce cas, le programme a ete appele a.out, aussi le fichier
   core s'appelle a.out.core. Nous pouvons voir que le programme
   s'est plante car il a essaye d'acceder `a une zone dans la memoire
   qui n'etait pas disponible dans la fonction appelee bazz.

   Quelquefois il est utile de pouvoir voir comment une fonction a
   ete appelee car le probleme peut avoir eu lieu bien avant dans la
   pile des appels dans un programme complexe. La commande bt demande
   `a gdb d'afficher une trace inverse de la pile des appels:

 (gdb) bt
 #0  0x164a in bazz (anint=0x5) at temp.c:17
 #1  0xefbfd888 in end ()
 #2  0x162c in main () at temp.c:11
 (gdb)
      

   La fonction end() est appelee lorsque le programme se plante; dans
   ce cas, la fonction bazz() a ete appelee main().

     --------------------------------------------------------------

  5.6.4. Se brancher sur un programme en cours d'execution

   Une des plus belles caracteristiques de gdb est qu'il peut se
   brancher sur un programme qui s'execute dej`a. Bien sur, cela
   suppose que vous ayez les privileges suffisants pour le faire. Un
   probleme habituel est quand vous vous deplacez dans un programme
   qui se dedouble et que vous voulez tracer le programme fils
   cependant le devermineur ne vous laissera seulement tracer le
   pere.

   Ce que vous devez faire est de demarrer un autre gdb, utiliser ps
   pour trouver l'ID du processus fils et faire

 (gdb) attach identifiant_processus
      

   dans gdb, et deverminer ensuite comme d'habitude.

   "C'est tout simple," pensez-vous certainement," mais pendant le
   temps que je faisais c,a, le processus fils sera dej`a parti
   loin". Ne vous en faites pas, noble lecteur, voici comment faire
   (avec l'appui des pages d'info de gdb):

 ...
 if ((pid = fork()) < 0)         /* _Toujours_ verifier cela */
         error();
 else if (pid == 0) {            /* le fils */
         int PauseMode = 1;

         while (PauseMode)
                 sleep(10);      /* Attendre jusqu'a ce que quelqu'un se brache sur nous */
         ...
 } else {                        /* le pere */
         ...
      

   Maintenant tout ce que nous avons `a faire est de nous brancher
   sur le processus fils, de mettre PauseMode `a 0 et d'attendre que
   l'appel `a la fonction sleep() retourne !

     --------------------------------------------------------------

5.7. Utiliser Emacs comme environnement de developpement

  5.7.1. Emacs

   Malheureusement, les systemes Unix ne sont pas fournis avec des
   sortes d'environnements de developpement integres
   tout-ce-que-vous-avez-toujours-voulu-et-beaucoup-plus-dans-un-ensemble-gigantesque
   que d'autres sytemes ont. [9] Toutefois, il est possible de se
   faire son propre environnement. Cela n'est pas forcement aussi
   joli et il peut ne pas etre autant integre mais vous pouvez le
   personnaliser comme vous voulez. Et c'est gratuit. Et vous en avez
   les sources.

   La cle de tout cela est Emacs. Maintenant il y a des gens qui le
   detestent, mais beaucoup l'aiment. Si vous etes un du premier
   groupe, j'ai peur que cette section ait peu d'interet pour vous.
   Vous aurez besoin d'une quantite moyenne de memoire pour le faire
   fonctionner-Je recommenderai 8Mo en mode texte et 16Mo dans X pour
   avoir un minimum de performances.

   Emacs est basiquement un editeur hautement personnalisable -en
   effet, il a ete personnalise au point de ressembler plus `a un
   systeme d'exploitation qu'`a un editeur! Beaucoup de developpeurs
   et d'administrateurs systeme passent en fait pratiquement tout
   leur temps `a travailler dans Emacs, en ne le quittant qu'`a leur
   deconnexion.

   Il est impossible de dire tout ce qu'Emacs peut faire ici, mais
   voici quelques unes des caracteristiques d'interet pour les
   developpeurs:

     * Un tres puissant editeur, permettant le chercher-remplacer sur
       les chaines et les expressions regulieres (motifs), sauter `a
       la fin ou au debut d'un bloc, etc, etc.

     * Menus deroulants et aide en ligne.

     * Colorisation syntaxique en fonction du langage et indentation.

     * Totalement personnalisable.

     * Vous pouvez compiler et deverminer des programmes dans Emacs.

     * Sur erreur de compilation, vous pouvez aller directement `a la
       ligne de code source fautive.

     * Une interface amicale au programme info utilise pour lire la
       documentation hypertexte GNU, incluant la documentation sur
       Emacs elle-meme.

     * Une interface agreable `a gdb, vous permettant de voir le code
       source au fur et `a mesure que vous vous deplacez dans votre
       programme.

     * Vous pouvez lire les nouvelles Usenet et envoyer des e-mails
       pendant que votre programme est en compilation.

   Et sans doute beaucoup plus que je n'ai survole.

   Emacs peut etre installe sur FreeBSD en utilisant Emacs le
   logiciel porte Emacs.

   Une fois installe, demarrez-le et faites C-h t pour lire un cours
   sur Emacs-cela signifie maintenir la touche control, presser h,
   relacher la touche control et presser t. (Alternativement, vous
   pouvez utiliser la souris pour selectionner Emacs Tutorial dans le
   menu Help).

   Bien que Emacs possede des menus, il est valable d'apprendre les
   raccourcis clavier, etant plus rapide quand vous editez quelque
   chose d'appuyer sur un couple de touches que de reprendre la
   souris et de cliquer au bon endroit. Et, quand vous discutez avec
   des utilisateurs experimentes d'Emacs, vous trouverez qu'ils
   parlent souvent de choses comme "M-x replace-s RET foo RET bar
   RET" aussi il est utile de savoir ce que cela veut dire. Et dans
   tous les cas, Emacs possede beaucoup trop de fonctions pour
   qu'elles soient dans les barres de menus.

   Heureusement, il est assez simple de recuperer les raccourcis
   clavier car ils sont affiches `a cote des elements des menus
   deroulants. Mon conseil est d'utiliser un element de menu pour,
   disons, ouvrir un fichier jusqu'`a ce que vous sachiez comment
   cela fonctionne et que quand vous vous sentez `a l'aise avec,
   essayez C-x C-f. Quand vous serez content avec c,a, passez `a une
   autre commande du menu.

   Si vous ne pouvez pas vous rappeler de ce qu'une combinaison de
   touches particulieres fait, selectionnez Describe Key dans le menu
   Help et tapez-la-Emacs vous dira ce qu'elle fait. Vous pouvez
   aussi utiliser l'element de menu Command Apropos pour trouver
   toutes les commandes qui contiennent un mot particulier, avec leur
   raccourci clavier.

   De cette maniere, l'expression ci-dessus signifie maintenir la
   touche Meta, taper x, relacher la touche Meta, taper replace-s
   (raccourci pour replace-string- une autre caracteristique d'Emacs
   est que vous pouvez abreger les commandes), appuyer sur la touche
   Entree, taper foo (la chaine que vous voulez remplacer), presser
   la touche Entree, taper bar (la chaine que vous voulez substituer
   `a foo) puis appuyer sur Entree une derniere fois. Emacs va alors
   faire l'operation chercher-remplacer que vous avez demande.

   Si vous vous demandez ce qu'est cette touche Meta, il s'agit d'une
   touche speciale que beaucoup de stations de travail Unix
   possedent. Malheureusement, les PC n'en ont pas, aussi c'est
   habituellement la touche alt (ou si vous n'avez pas de chance, la
   touche echap).

   Oh, et pour sortir d'Emacs, faites C-x C-c (ce qui signifie
   maintenir la touche control appuyee, appuyer c et relacher la
   touche control. Si vous avez des fichiers non sauvegardes ouverts,
   Emacs vous demandera si vous voulez les sauvegarder. (Ignorez le
   bout de documentation ou il est dit que C-z est la maniere
   habituelle de quitter Emacs- qui quitte Emacs en le laissant
   tourner en tache de fond et qui n'est vraiment utile que si vous
   avez un systeme sans terminal virtuel).

     --------------------------------------------------------------

  5.7.2. Configurer Emacs

   Emacs fait des choses merveilleuses; une partie est integree
   directement, une autre doit etre configuree.

   Plutot que d'utiliser un macro langage proprietaire pour la
   configuration, Emacs utilise une version du Lisp specialement
   adaptee pour les editeurs, connue sous le nom d'Emacs Lisp.
   Celui-ci peut etre assez utile si vous voulez poursuivre et
   apprendre quelque chose comme le Common Lisp, car il est
   considerablement plus petit que le Common Lisp (bien que dej`a
   assez gros!).

   La meilleure fac,on d'apprendre l'Emacs Lisp est de telecharger le
   cours d'Emacs

   Toutefois, il n'y a pas besoin de connaitre le Lisp pour commencer
   la configuration d'Emacs, car j'ai inclus un exemple de fichier
   .emacs qui devrait etre suffisant pour commencer. Copiez juste
   celui-ci dans votre repertoire utilisateur et redemarrez Emacs si
   celui-ci s'execute, il lira les commandes du fichier et (si tout
   va bien!) vous donnera une configuration basique utile.

     --------------------------------------------------------------

  5.7.3. Un fichier exemple .emacs

   Malheureusement, il y a beaucoup trop de choses ici pour les
   expliquer en detail; toutefois, il y a un ou deux points qui
   valent d'etre mentionnes.

     * Tout ce qui commence avec un ; est un commentaire et est
       ignore par Emacs.

     * A la premiere ligne, le -*- Emacs-Lisp -*- est tel que vous
       pouvez editer le fichier .emacs lui-meme `a l'interieur
       d'Emacs et d'obtenir tous les fantaisistes dispositifs pour
       l'edition en Emacs Lisp. Emacs essaye habituellement de
       deviner cela en se basant sur le nom du fichier, et ne
       trouvera peut-etre pas pour .emacs.

     * La touche tab est liee `a la fonction d'indentation dans
       certains modes, aussi quand vous l'enfoncez, cela va indenter
       la ligne courante de code. Si vous voulez mettre un caractere
       tab dans quoique ce soit que vous tapiez, maintenez la touche
       control enfoncee pendant que vous appuyez sur tab.

     * Ce fichier supporte la colorisation de syntaxe pour les
       langages C, C++, Perl, Lisp et Scheme en devinant le langage
       par leur nom.

     * Emacs possede dej`a une fonction pre-definie appelee
       next-error. Dans la fenetre de sortie d'une compilation, cela
       vous permet de vous deplacer d'une erreur de compilation `a la
       suivante en faisant M-n; nous definissons une fonction
       complementaire previous-error, qui vous permet d'aller `a
       l'erreur precedente en faisant M-p. Le plus beau dispositif de
       tous est que C-c C-c va ouvrir le fichier source dans lequel
       l'erreur a eu lieu et sautera `a la ligne appropriee.

     * Nous autorisons la capacite d'Emacs `a agir comme un serveur
       ainsi si vous faites quelque chose en dehors d'Emacs et voulez
       editer un fichier, tapez juste

 % emacsclient nomfichier
          

       et alors vous pouvez editer le fichier dans votre Emacs! [10]

   Exemple 5-1. Un fichier exemple .emacs

 ;; -*-Emacs-Lisp-*-

 ;; Ce fichier est concu pour etre reevalue, utiliser la variable first-time
 ;; pour eviter tout probleme.
 (defvar first-time t
   "Valeur signifiant que c'est la premiere fois que .emacs a ete evalue"
   )

 ;; Meta
 (global-set-key "\M- " 'set-mark-command)
 (global-set-key "\M-\C-h" 'backward-kill-word)
 (global-set-key "\M-\C-r" 'query-replace)
 (global-set-key "\M-r" 'replace-string)
 (global-set-key "\M-g" 'goto-line)
 (global-set-key "\M-h" 'help-command)

 ;; Function keys
 (global-set-key [f1] 'manual-entry)
 (global-set-key [f2] 'info)
 (global-set-key [f3] 'repeat-complex-command)
 (global-set-key [f4] 'advertised-undo)
 (global-set-key [f5] 'eval-current-buffer)
 (global-set-key [f6] 'buffer-menu)
 (global-set-key [f7] 'other-window)
 (global-set-key [f8] 'find-file)
 (global-set-key [f9] 'save-buffer)
 (global-set-key [f10] 'next-error)
 (global-set-key [f11] 'compile)
 (global-set-key [f12] 'grep)
 (global-set-key [C-f1] 'compile)
 (global-set-key [C-f2] 'grep)
 (global-set-key [C-f3] 'next-error)
 (global-set-key [C-f4] 'previous-error)
 (global-set-key [C-f5] 'display-faces)
 (global-set-key [C-f8] 'dired)
 (global-set-key [C-f10] 'kill-compilation)

 ;; Keypad bindings
 (global-set-key [up] "\C-p")
 (global-set-key [down] "\C-n")
 (global-set-key [left] "\C-b")
 (global-set-key [right] "\C-f")
 (global-set-key [home] "\C-a")
 (global-set-key [end] "\C-e")
 (global-set-key [prior] "\M-v")
 (global-set-key [next] "\C-v")
 (global-set-key [C-up] "\M-\C-b")
 (global-set-key [C-down] "\M-\C-f")
 (global-set-key [C-left] "\M-b")
 (global-set-key [C-right] "\M-f")
 (global-set-key [C-home] "\M-<")
 (global-set-key [C-end] "\M->")
 (global-set-key [C-prior] "\M-<")
 (global-set-key [C-next] "\M->")

 ;; Souris
 (global-set-key [mouse-3] 'imenu)

 ;; Divers
 (global-set-key [C-tab] "\C-q\t")       ; Control tab quotes a tab.
 (setq backup-by-copying-when-mismatch t)

 ;; Traite 'y' ou <CR> comme yes, 'n' comme no.
 (fset 'yes-or-no-p 'y-or-n-p)
     (define-key query-replace-map [return] 'act)
     (define-key query-replace-map [?\C-m] 'act)

 ;; Charge les ajouts
 (require 'desktop)
 (require 'tar-mode)

 ;; Diff mode sympa
 (autoload 'ediff-buffers "ediff" "Intelligent Emacs interface to diff" t)
 (autoload 'ediff-files "ediff" "Intelligent Emacs interface to diff" t)
 (autoload 'ediff-files-remote "ediff"
   "Intelligent Emacs interface to diff")

 (if first-time
     (setq auto-mode-alist
           (append '(("\\.cpp$" . c++-mode)
                     ("\\.hpp$" . c++-mode)
                     ("\\.lsp$" . lisp-mode)
                     ("\\.scm$" . scheme-mode)
                     ("\\.pl$" . perl-mode)
                     ) auto-mode-alist)))

 ;; Mode de verrouillage automatique de la police de caracteres
 (defvar font-lock-auto-mode-list
   (list 'c-mode 'c++-mode 'c++-c-mode 'emacs-lisp-mode 'lisp-mode 'perl-mode 'scheme-mode)
   "List of modes to always start in font-lock-mode")

 (defvar font-lock-mode-keyword-alist
   '((c++-c-mode . c-font-lock-keywords)
     (perl-mode . perl-font-lock-keywords))
   "Associations between modes and keywords")

 (defun font-lock-auto-mode-select ()
   "Automatically select font-lock-mode if the current major mode is
 in font-lock-auto-mode-list"
   (if (memq major-mode font-lock-auto-mode-list)
       (progn
         (font-lock-mode t))
     )
   )

 (global-set-key [M-f1] 'font-lock-fontify-buffer)

 ;; New dabbrev stuff
 ;(require 'new-dabbrev)
 (setq dabbrev-always-check-other-buffers t)
 (setq dabbrev-abbrev-char-regexp "\\sw\\|\\s_")
 (add-hook 'emacs-lisp-mode-hook
           '(lambda ()
              (set (make-local-variable 'dabbrev-case-fold-search) nil)
              (set (make-local-variable 'dabbrev-case-replace) nil)))
 (add-hook 'c-mode-hook
           '(lambda ()
              (set (make-local-variable 'dabbrev-case-fold-search) nil)
              (set (make-local-variable 'dabbrev-case-replace) nil)))
 (add-hook 'text-mode-hook
           '(lambda ()
              (set (make-local-variable 'dabbrev-case-fold-search) t)
              (set (make-local-variable 'dabbrev-case-replace) t)))

 ;; mode C++ et C...
 (defun my-c++-mode-hook ()
   (setq tab-width 4)
   (define-key c++-mode-map "\C-m" 'reindent-then-newline-and-indent)
   (define-key c++-mode-map "\C-ce" 'c-comment-edit)
   (setq c++-auto-hungry-initial-state 'none)
   (setq c++-delete-function 'backward-delete-char)
   (setq c++-tab-always-indent t)
   (setq c-indent-level 4)
   (setq c-continued-statement-offset 4)
   (setq c++-empty-arglist-indent 4))

 (defun my-c-mode-hook ()
   (setq tab-width 4)
   (define-key c-mode-map "\C-m" 'reindent-then-newline-and-indent)
   (define-key c-mode-map "\C-ce" 'c-comment-edit)
   (setq c-auto-hungry-initial-state 'none)
   (setq c-delete-function 'backward-delete-char)
   (setq c-tab-always-indent t)
 ;; Style d'indentation BSD
   (setq c-indent-level 4)
   (setq c-continued-statement-offset 4)
   (setq c-brace-offset -4)
   (setq c-argdecl-indent 0)
   (setq c-label-offset -4))

 ;; mode Perl
 (defun my-perl-mode-hook ()
   (setq tab-width 4)
   (define-key c++-mode-map "\C-m" 'reindent-then-newline-and-indent)
   (setq perl-indent-level 4)
   (setq perl-continued-statement-offset 4))

 ;; mode Scheme...
 (defun my-scheme-mode-hook ()
   (define-key scheme-mode-map "\C-m" 'reindent-then-newline-and-indent))

 ;; mode Emacs-Lisp...
 (defun my-lisp-mode-hook ()
   (define-key lisp-mode-map "\C-m" 'reindent-then-newline-and-indent)
   (define-key lisp-mode-map "\C-i" 'lisp-indent-line)
   (define-key lisp-mode-map "\C-j" 'eval-print-last-sexp))

 ;; Ajoute tout le reste...
 (add-hook 'c++-mode-hook 'my-c++-mode-hook)
 (add-hook 'c-mode-hook 'my-c-mode-hook)
 (add-hook 'scheme-mode-hook 'my-scheme-mode-hook)
 (add-hook 'emacs-lisp-mode-hook 'my-lisp-mode-hook)
 (add-hook 'lisp-mode-hook 'my-lisp-mode-hook)
 (add-hook 'perl-mode-hook 'my-perl-mode-hook)

 ;; Le complement a next-error
 (defun previous-error (n)
   "Visit previous compilation error message and corresponding source code."
   (interactive "p")
   (next-error (- n)))

 ;; Divers...
 (transient-mark-mode 1)
 (setq mark-even-if-inactive t)
 (setq visible-bell nil)
 (setq next-line-add-newlines nil)
 (setq compile-command "make")
 (setq suggest-key-bindings nil)
 (put 'eval-expression 'disabled nil)
 (put 'narrow-to-region 'disabled nil)
 (put 'set-goal-column 'disabled nil)

 ;; Recherche des archives Elisp
 (autoload 'format-lisp-code-directory "lispdir" nil t)
 (autoload 'lisp-dir-apropos "lispdir" nil t)
 (autoload 'lisp-dir-retrieve "lispdir" nil t)
 (autoload 'lisp-dir-verify "lispdir" nil t)

 ;; Mode de verrouillage de police
 (defun my-make-face (face colour &optional bold)
   "Create a face from a colour and optionally make it bold"
   (make-face face)
   (copy-face 'default face)
   (set-face-foreground face colour)
   (if bold (make-face-bold face))
   )

 (if (eq window-system 'x)
     (progn
       (my-make-face 'blue "blue")
       (my-make-face 'red "red")
       (my-make-face 'green "dark green")
       (setq font-lock-comment-face 'blue)
       (setq font-lock-string-face 'bold)
       (setq font-lock-type-face 'bold)
       (setq font-lock-keyword-face 'bold)
       (setq font-lock-function-name-face 'red)
       (setq font-lock-doc-string-face 'green)
       (add-hook 'find-file-hooks 'font-lock-auto-mode-select)

       (setq baud-rate 1000000)
       (global-set-key "\C-cmm" 'menu-bar-mode)
       (global-set-key "\C-cms" 'scroll-bar-mode)
       (global-set-key [backspace] 'backward-delete-char)
                                         ;      (global-set-key [delete] 'delete-char)
       (standard-display-european t)
       (load-library "iso-transl")))

 ;; X11 ou PC utilisant les ecritures directes a l'ecran
 (if window-system
     (progn
       ;;      (global-set-key [M-f1] 'hilit-repaint-command)
       ;;      (global-set-key [M-f2] [?\C-u M-f1])
       (setq hilit-mode-enable-list
             '(not text-mode c-mode c++-mode emacs-lisp-mode lisp-mode
                   scheme-mode)
             hilit-auto-highlight nil
             hilit-auto-rehighlight 'visible
             hilit-inhibit-hooks nil
             hilit-inhibit-rebinding t)
       (require 'hilit19)
       (require 'paren))
   (setq baud-rate 2400)                 ; For slow serial connections
   )

 ;; Terminal de type TTY
 (if (and (not window-system)
          (not (equal system-type 'ms-dos)))
     (progn
       (if first-time
           (progn
             (keyboard-translate ?\C-h ?\C-?)
             (keyboard-translate ?\C-? ?\C-h)))))

 ;; Sous Unix
 (if (not (equal system-type 'ms-dos))
     (progn
       (if first-time
           (server-start))))

 ;; Add any face changes here
 (add-hook 'term-setup-hook 'my-term-setup-hook)
 (defun my-term-setup-hook ()
   (if (eq window-system 'pc)
       (progn
 ;;      (set-face-background 'default "red")
         )))

 ;; Restaure le  "desktop" - faire cela le plus tard possible
 (if first-time
     (progn
       (desktop-load-default)
       (desktop-read)))

 ;; Indique que ce fichier a ete lu au moins une fois
 (setq first-time nil)

 ;; Pas besoin de deverminer quoique ce soit maintenant

 (setq debug-on-error nil)

 ;; Tout est fait
 (message "All done, %s%s" (user-login-name) ".")
        

     --------------------------------------------------------------

  5.7.4. Etendre la palette de langages qu'Emacs comprend

   Maintenant, Emacs est tres bien si vous voulez seulement
   programmer dans des langages dej`a fournis dans le fichier .emacs
   (C, C++, Perl, Lisp et Scheme), mais qu'arrive-t-il si un nouveau
   langage appele "whizbang" sort, plein d'excitantes fonctionnalites
   ?

   La premiere chose `a faire est de savoir si whizbang est fourni
   avec des fichiers de configuration pour Emacs. Ceux-ci se
   terminent habituellement par .el, raccourci pour "Emacs Lisp". Par
   exemple, si whizbang est un logiciel porte FreeBSD, nous pouvons
   localiser ces fichiers en faisant

 % find /usr/ports/lang/whizbang -name "*.el" -print
      

   et les installer en les copiant dans le repertoire Lisp d'Emacs.
   Sur FreeBSD 2.1.0-RELEASE, il s'agit de
   /usr/local/share/emacs/site-lisp [11].

   Aisni par exemple, si la sortie de la commande find etait

 /usr/ports/lang/whizbang/work/misc/whizbang.el
      

   nous ferions

 # cp /usr/ports/lang/whizbang/work/misc/whizbang.el /usr/local/share/emacs/site-lisp
      

   Ensuite, nous devons decider quel extension les fichiers source
   whizbang ont. Disons qu'il s'agit de fichiers se terminant par
   .wiz. Nous devons ajouter une entree dans notre fichier .emacs
   pour etre sur qu'Emacs sera capable d'utiliser les informations
   dans whizbang.el.

   Trouvez l'entree auto-mode-alist dans .emacs et ajoutez une ligne
   pour whizbang, comme :

 ...
 ("\\.lsp$" . lisp-mode)
 ("\\.wiz$" . whizbang-mode)
 ("\\.scm$" . scheme-mode)
 ...

   Cela signifie qu'Emacs ira automatiquement dans la fonction
   whizbang-mode quand vous editerez un fichier se terminant par
   .wiz.

   Juste en-dessous, vous trouverez l'entree
   font-lock-auto-mode-list. Ajoutez whizbang-mode `a celle-ci comme
   ceci :

 ;; Auto font lock mode
 (defvar font-lock-auto-mode-list
   (list 'c-mode 'c++-mode 'c++-c-mode 'emacs-lisp-mode 'whizbang-mode 'lisp-mode 'perl-mode 'scheme-mode)
   "List of modes to always start in font-lock-mode")

   Cela signifie qu'Emacs autorisera toujours font-lock-mode (ie
   colorisation de la syntaxe) pendant l'edition d'un fichier .wiz.

   Et c'est tout ce qui est necessaire. S'il y a quoique ce soit que
   vous voulez de fait automatiquement quand vous ouvrez un fichier
   .wiz, vous pouvez ajouter un whizbang-mode hook (voir
   my-scheme-mode-hook pour un exemple simple qui ajoute auto-indent,
   l'auto-indentation).

     --------------------------------------------------------------

5.8. Pour aller plus loin

     * Brian Harvey and Matthew Wright Simply Scheme MIT 1994. ISBN
       0-262-08226-8

     * Randall Schwartz Learning Perl O'Reilly 1993 ISBN
       1-56592-042-2

     * Patrick Henry Winston and Berthold Klaus Paul Horn Lisp (3rd
       Edition) Addison-Wesley 1989 ISBN 0-201-08319-1

     * Brian W. Kernighan and Rob Pike The Unix Programming
       Environment Prentice-Hall 1984 ISBN 0-13-937681-X

     * Brian W. Kernighan and Dennis M. Ritchie The C Programming
       Language (2nd Edition) Prentice-Hall 1988 ISBN 0-13-110362-8

     * Bjarne Stroustrup The C++ Programming Language Addison-Wesley
       1991 ISBN 0-201-53992-6

     * W. Richard Stevens Advanced Programming in the Unix
       Environment Addison-Wesley 1992 ISBN 0-201-56317-7

     * W. Richard Stevens Unix Network Programming Prentice-Hall 1990
       ISBN 0-13-949876-1

     --------------------------------------------------------------

                  Chapitre 6. Programmation securisee

   Ce chapitre a ete ecrit par Murray Stokely.

     --------------------------------------------------------------

6.1. Synopsis

   Ce chapitre decrit quelques problemes de securite qui ont
   tourmente les programmeurs Unix depuis des dizaines d'annees et
   quelques uns des nouveaux outils disponibles pour aider les
   programmeurs `a eviter l'ecriture de code non securise.

     --------------------------------------------------------------

6.2. Methodologie de developpement securise

   Ecrire des applications securisees demande une tres minutieuse et
   pessimiste vision de la vie. Les applications devrait fonctionner
   avec le principe du "privilege moindre" de fac,on `a ce qu'aucun
   processus ne fonctionne avec plus que le strict minimum dont il a
   besoin pour accomplir sa tache. Le code pre-teste devrait etre
   reutilise autant que possible pour eviter les erreurs communes que
   d'autres peuvent dej`a avoir reparees.

   Un des pieges de l'environnement Unix est qu'il est facile
   d'affecter la stabilite de l'environnement. Les applications ne
   devraient jamais avoir confiance dans la saisie de l'utilisateur
   (sous toutes ses formes), les ressources systeme, la communication
   inter-processus, ou l'enchainement des evenements. Les processus
   Unix n'executent pas de maniere synchrone aussi, logiquement, les
   operations sont rarement atomiques.

     --------------------------------------------------------------

6.3. Depassement de capacite

   Les depassements de capacite ("Buffer Overflows") existent depuis
   les debuts de l'architecture de Von-Neuman 1. Ils gagnerent une
   grande notoriete en 1988 avec le ver pour Internet de Morris.
   Malheureusement, la meme attaque basique reste effective
   aujourd'hui. Des 17 rapports de securite du CERT de 1999, 10
   furent causes directement des bogues logiciels de depassement de
   capacite. De loin la plus commune de types d'attaques par
   depassement de capacite est basee sur la corruption de la pile.

   La plupart des systemes informatiques modernes utilise une pile
   pour passer les arguments aux procedures et stocker les variables
   locales Une pile est une zone memoire dernier entre-premier sorti
   (Last In-First Out : LIFO) dans la zone de memoire haute de
   l'image d'un processus. Quand un programme invoque une fonction
   une nouvelle structure pile est creee. Cette structure pile
   consiste dans les arguments passes `a la fonction aussi bien que
   dans une quantite dynamique d'espace pour la variable locale. Le
   pointeur de pile est un registre qui reference la position
   courante du sommet de la pile. Etant donne que cette valeur change
   constamment au fur et `a mesure que de nouvelles valeurs sont
   ajoutees au sommet de la pile, beaucoup d'implementations
   fournissent aussi un pointeur de structure qui est positionne dans
   le voisinage du debut de la structure pile de fac,on `a ce que les
   variables locales soient plus facilement adressables relativement
   `a cette valeur. 1 L'adresse de retour des appels de fonction est
   aussi stocke dans la pile, et cela est la cause des decouvertes
   des depassements de pile puisque faire deborder une variable
   locale dans une fonction peut ecraser l'adresse de retour de cette
   fonction, permettant potentiellement `a un utilisateur malveillant
   d'executer le code qu'il ou elle desire.

   Bien que les attaques basees sur les depassements de pile soient
   de loin les plus communes, il serait aussi possible de faire
   exploser la pile avec une attaque du tas (malloc/free).

   Le langage de programmation C ne realise pas de verifications
   automatiques des limites sur les tableaux ou pointeurs comme
   d'autres langages le font. De plus, la librairie standard du C est
   remplie d'une poignee de fonctions tres dangereuses.

   +----------------------------------------------------------------+
   | strcpy(char *dest, const char *src)  | Peut faire deborder le  |
   |                                      | tampon dest             |
   |--------------------------------------+-------------------------|
   | strcat(char *dest, const char *src)  | Peut faire deborder le  |
   |                                      | tampon dest             |
   |--------------------------------------+-------------------------|
   | getwd(char *buf)                     | Peut faire deborder le  |
   |                                      | tampon buf              |
   |--------------------------------------+-------------------------|
   | gets(char *s)                        | Peut faire deborder le  |
   |                                      | tampon s                |
   |--------------------------------------+-------------------------|
   | [vf]scanf(const char *format, ...)   | Peut faire deborder ses |
   |                                      | arguments.              |
   |--------------------------------------+-------------------------|
   | realpath(char *path, char            | Peut faire deborder le  |
   | resolved_path[])                     | tampon path             |
   |--------------------------------------+-------------------------|
   | [v]sprintf(char *str, const char     | Peut faire deborder le  |
   | *format, ...)                        | tampon str.             |
   +----------------------------------------------------------------+

     --------------------------------------------------------------

  6.3.1. Exemple de depassement de capacite

   L'exemple de code suivant contient un depassement de capacite
   conc,u pour ecraser l'adresse de retour et "sauter" l'instruction
   suivant immediatement l'appel de la fonction. (Inspire par 4)

 #include <stdio.h>

 void manipulate(char *buffer) {
   char newbuffer[80];
   strcpy(newbuffer,buffer);
 }

 int main() {
   char ch,buffer[4096];
   int i=0;

   while ((buffer[i++] = getchar()) != '\n') {};

   i=1;
   manipulate(buffer);
   i=2;
   printf("La valeur de i est : %d\n",i);
   return 0;
 }

   Examinons quel serait l'aspect de l'image memoire de ce processus
   si nous avions entre 160 espaces dans notre petit programme avant
   d'appuyer sur Entree.

   [XXX Schema ici!]

   Evidemment une entree plus malveillante pourrait etre imaginee
   pour executer des instructions dej`a compilees (comme
   exec(/bin/sh)).

     --------------------------------------------------------------

  6.3.2. Eviter les depassements de capacite

   La solution la plus simple au probleme de debordement de pile est
   de toujours utiliser de la memoire restreinte en taille et les
   fonctions de copie de chaine de caracteres. strncpy et strncat
   font parties de la libraire standard du C. Ces fonctions acceptent
   une valeur de longueur comme parametre qui qui ne devrait pas etre
   plus grande que la taille du tampon de destination. Ces fonctions
   vont ensuite copier `taille' octets de la source vers la
   destination. Toutefois, il y a un certain nombre de problemes avec
   ces fonctions. Aucune fonction ne garantit une terminaison par le
   caractere NULL si la taille du tampon d'entree est aussi grand que
   celui de destination. Le parametre taille est aussi utilise de
   fac,on illogique entre strncpy et strncat aussi il est facile pour
   les programmeurs d'etre deroutes sur leur utilisation convenable.
   Il y a aussi une perte significative des performances compare `a
   strcpy lorsque l'on copie une courte chaine dans un grand tampon
   puisque strncpy remplit de caracteres NULL jusqu'`a la taille
   specifiee.

   Dans OpenBSD, une autre implementation de la copie de memoire a
   ete creee pour contourner ces problemes. Les fonctions strlcpy et
   strlcat garantissent qu'elles termineront toujours le tampon de
   destination par un caractere NULL losque l'argument de taille est
   different de zero. Pour plus d'informations sur ces fonctions,
   voir 6. Les fonctions strlcpy et strlcat d'OpenBSD ont ete inclues
   dans FreeBSD depuis la version 3.5.

     --------------------------------------------------------------

    6.3.2.1. V#233;rifications des limites en fonctionnement basees sur
    le compilateur

   Malheureusement il y a toujours un tres important assortiment de
   code en utilisation publique qui copie aveuglement la memoire sans
   utiliser une des routines de copie limitee dont nous venons juste
   de discuter. Heureusement, il y a une autre solution. Plusieurs
   produits complementaires pour compilateur et librairies existent
   pour faire de la verification de limites pendant le fonctionnement
   en C/C++.

   StackGuard est un de ces produits qui est implemente comme un
   petit correctif ("patch") pour le generateur de code gcc. Extrait
   du site Internet de StackGuard, http://immunix.org/stackguard.html
   :

     "StackGuard detecte et fait echouer les attaques par debordement
     de pile en empechant l'adresse de retour sur la pile d'etre
     alteree. StackGuard place un mot "canari" [12] `a cote de
     l'adresse de retour quand la fontion est appelee. Si le mot
     "canari" a ete altere au retour de la fonction, alors une
     attaque par debordement de pile a ete tentee et le programme
     repond en envoyant une alerte d'intrusion dans la trace systeme
     (syslog) et s'arrete alors."

     "StackGuard est implemente comme un petit correctif au
     generateur de code gcc, specifiquement sur les routines
     function_prolog() et function_epilog(). function_prolog() a ete
     ameliore pour laisser des "canaris" sur la pile quand les
     fonctions demarrent, et function_epilog verifie l'integrite des
     "canaris" quand la fonction se termine. Tout essai pour
     corrompre l'adresse de retour est alors detectee avant que la
     fonction ne retourne."

   Recompiler votre application avec StackGuard est un moyen efficace
   pour stopper la plupart des attques par depassement de capacite,
   mais cela peut toujours etre compromis.

     --------------------------------------------------------------

    6.3.2.2. Verifications des limites en fonctionnement basees sur les
    librairies

   Les mecanismes bases sur le compilateur sont totalement inutiles
   pour logiciel seulement binaire que vous ne pouvez recompiler.
   Pour ces situations, il existe un nombre de librairies qui
   re-implemente les fonctions peu sures de la librairie C (strcpy,
   fscanf, getwd, etc..) et assurent que ces fonctions ne peuvent pas
   ecrire plus loin que le pointeur de pile.

     * libsafe

     * libverify

     * libparnoia

   Malheureusement ces defenses basees sur les librairies possedent
   un certain nombre de defauts. Ces librairies protegent seulement
   d'un tres petit ensemble de problemes lies `a la securite et
   oublient de reparer le probleme actuel. Ces defenses peuvent
   echouer si l'application a ete compilee avec -fomit-frame-pointer.
   De meme, les variables d'environnement LD_PRELOAD et
   LD_LIBRARY_PATH peuvent etre reecrites/non definies par
   l'utilisateur.

     --------------------------------------------------------------

6.4. Les problemes lies `a SetUID

   Il y a au moins 6 differents ID (identifiants) associes `a un
   processus donne. A cause de cela, vous devez etre tres attentif
   avec l'acces que votre processus possede `a un instant donne. En
   particulier, toutes les applications ayant rec,u des privileges
   par seteuid doivent les abandonnes des qu'ils ne sont plus
   necessaires.

   L'identifiant de l'utilisateur reel (real user ID) peut seulement
   etre change par un processus super-utilisateur. Le programme login
   met celui `a jour quand un utilisateur se connecte et il est
   rarement change.

   L'identifiant de l'utilisateur effectif (effective user ID) est
   mis `a jour par les fonctions exec() si un programme possede son
   bit seteuid place. Une application peut appeler seteuid() `a
   n'importe quel moment pour regler l'identifiant de l'utilisateur
   effectif sur l'identifiant d'un utilisateur reel ou sur le
   "set-user-ID" sauve. Quand l'identifiant de l'utilisateur effectif
   est place par les fonctions exec(), la valeur precedente est
   sauvee dans le "set-user-ID" sauve.

     --------------------------------------------------------------

6.5. Limiter l'environnement de votre programme

   La methode traditionnelle pour restreindre l'acces d'un processus
   se fait avec l'appel systeme chroot(). Cet appel systeme change le
   repertoire racine depuis lequel tous les autres chemins sont
   references pour un processus et ses fils. Pour que cet appel
   reussisse, le processus doit avoir execute (recherche) la
   permission dans le repertoire reference. Le nouvel environnement
   environment ne prend pas effet que lorsque vous appelez chdir()
   dans celui-ci. Il doit etre aussi note qu'un processus peut
   facilement s'echapper d'un environnement chroot s'il a les
   privileges du super-utilisateur. Cela devrait etre accompli en
   creant des fichiers speciaux de peripherique pour la memoire du
   noyau, en attachant un devermineur `a un processus depuis
   l'exterieur de sa "prison", ou par d'autres manieres creatrices.

   Le comportement de l'appel systeme chroot() peut etre un peu
   controle avec la commande sysctl et la variable
   kern.chroot_allow_open_directories. Quand cette valeur est reglee
   `a 0, chroot() echouera avec EPERM s'il y a un repertoire
   d'ouvert. Si la variable est reglee sur la valeur par defaut 1,
   alors chroot() echouera avec EPERM s'il y a un repertoire d'ouvert
   et que le processus est dej`a sujet `a un appel chroot(). Pour
   toute autre valeur, la verification des repertoires ouverts sera
   totalement court-circuitee.

     --------------------------------------------------------------

  6.5.1. La fonctionnalite "prison" de FreeBSD

   Le concept de Prison ("Jail") etend chroot() en limitant les
   droits du super-utilisateur pour creer un veritable `serveur
   virtuel'. Une fois qu'une prison est mise en place, toute
   communication reseau doit avoir lieu au travers de l'adresse IP
   specifiee, et le droit du "privilege super-utilisateur" dans cette
   prison est severement gene.

   Tant qu'il se trouve en prison, tout test avec les droits du
   super-utilisateur dans le noyau au travers d'un appel `a suser()
   echouera. Toutefois, quelques appels `a suser() ont ete changes
   par la nouvelle interface suser_xxx(). Cette fonction est
   responsable de fournir ou de retirer les acces aux droits du
   super-utilisateur pour les processus emprisonnes.

   Un processus super-utilisateur dans un environnement emprisonne a
   le pouvoir de :

     * Manipuler les identitifications avec setuid, seteuid, setgid,
       setegid, setgroups, setreuid, setregid, setlogin

     * Regler les limites en ressources avec setrlimit

     * Modifier quelques variables du noyau par sysctl
       (kern.hostname)

     * chroot()

     * Regler les parametres d'un noeud virtuel (vnode): chflags,
       fchflags

     * Regler les attributs d'un noeud virtuel comme les permissions
       d'un fichier, le proprietaire, le groupe, la taille, la date
       d'acces, et la date de modification.

     * Se lier `a des ports privilegies sur Internet (ports < 1024)

   Jail est un outil tres utile pour executer des applications dans
   un environnement securise mais il a des imperfections.
   Actuellement, les mecanismes IPC (Inter-Process Communications)
   n'ont pas ete convertis pour utiliser suser_xxx aussi des
   applications comme MySQL ne peuvent etre executee dans une prison.
   L'acces super-utilisateur peut avoir un sens tres limite dans une
   prison, mais il n'y aucune fac,on de specifier exactement ce que
   tres limite veut dire.

     --------------------------------------------------------------

  6.5.2. Les capacites des processus POSIX.1e

   Posix a realise un document de travail qui ajoute l'audit
   d'evenement, les listes de controle d'acces, les privileges fins,
   l'etiquetage d'information, et le controle d'acces mandate.

   Il s'agit d'un travail en cours et c'est l'objectif du projet
   TrustedBSD. Une partie du travail initial a ete integre dans
   FreeBSD-current (cap_set_proc(3)).

     --------------------------------------------------------------

6.6. La confiance

   Une application ne devrait jamais supposer que tout est sain dans
   l'environnement des utilisateurs. Cela inclut (mais n'est
   certainement pas limite `a) : la saisie de l'utilisateur, les
   signaux, les variables d'environnement, les ressources, les
   communication inter-processus, les mmaps, le repertoire de travail
   du systeme de fichiers, les descripteurs de fichier, le nombre de
   fichiers ouverts, etc.

   Vous ne devriez jamais supposer que vous pouvez gerer toutes les
   formes de saisie invalide qu'un utilisateur peut entrer. Votre
   application devrait plutot utiliser un filtrage positif pour
   seulement permettre un sous-ensemble specifique que vous jugez
   sain. Une mauvaise validation des entrees a ete la cause de
   beaucoup decouvertes de bogues, specialement avec les scripts CGI
   sur le web. Pour les noms de fichier, vous devez etre tout
   particulierement attentif aux chemins ("../", "/"), liens
   symboliques et caracteres d'echappement de l'interpreteur de
   commandes.

   Perl possede une caracteristique tes sympathique appelee mode
   "Taint" qui peut etre utilisee pour empecher les scripts
   d'utiliser des donnees externes au programme par un moyen non sur.
   Ce mode verifiera les arguments de la ligne de commandes, les
   variables d'environnement, les informations localisees (propres
   aux pays), les resultats de certains appels systeme (readdir(),
   readlink(), getpwxxx()) et toute entree de fichier.

     --------------------------------------------------------------

6.7. Les conditions de course

   Une condition de course est un comportement anormal cause par une
   dependance inattendue sur le sequencement relatif des evenements.
   En d'autres mots, un programmeur a suppose `a tort qu'un evenement
   particulier se passerait avant un autre.

   Quelques causes habituelles de conditions de course sont les
   signaux, les verifications d'acces et les fichiers ouverts. Les
   signaux sont des evenements asynchrones par nature aussi un soin
   particulier doit etre pris pour les utiliser. Verifier les acces
   avec access(2) puis open(2) n'est clairement pas atomique. Les
   utilisateurs peuvent deplacer des fichiers entre les deux appels.
   Les applications privilegiees devraient plutot faire un appel `a
   seteuid() puis appeler open() directement. Dans le meme esprit,
   une application devrait toujours regler un umask correct avant un
   appel `a open() pour prevenir le besoin d'appels non valides `a
   chmod().

                             III. Le noyau

   Table des matieres

   7. Histoire du noyau Unix

   8. Notes sur le verrouillage

     --------------------------------------------------------------

                   Chapitre 7. Histoire du noyau Unix

   Un peu d'histoire sur le noyau Unix/BSD, les appels systeme,
   comment fonctionnent les processus, bloquer, planifier, les
   threads (noyau), le basculement de contexte, les signaux, les
   interruptions, les modules, etc.

     --------------------------------------------------------------

                 Chapitre 8. Notes sur le verrouillage

   Ce chapitre est maintenu par The FreeBSD SMP Next Generation
   Project. Envoyez leur directement les commentaires et les
   suggestions `a liste de diffusion concernant le traitement
   symetrique multiprocesseurs (SMP) sous FreeBSD.

   Ce document souligne le verrouillage utilise dans le noyau FreeBSD
   pour permettre d'utiliser du vrai multi-processeur `a l'interieur
   du noyau. Le verrouillage peut etre realise par differents moyens.
   Les structures de donnees puvent etre protegees par des mutex ou
   lockmgr(9) verrous. Quelques variables sont protegees simplement
   par l'utilisation continuelle d'operations atomiques pour y
   acceder.

     --------------------------------------------------------------

8.1. Les mutex

   Un mutex est simplement un verrou utilise pour garantir exclusion
   mutuelle. Specifiquement, un mutex ne peut appartenir qu'`a une
   entite `a la fois. Si une autre entite desire obtenir un mutex
   dej`a pris , elle doit attendre jusqu'`a ce que le mutex soit
   relache. Dans le noyau FreeBSD, les mutex appartiennent aux
   processus.

   Les mutex peuvent etre acquis recursivement, mais ils sont conc,us
   pour n'etre pris que pendant une courte periode. Specifiquement,
   le detenteur ne doit pas se suspendre pendant qu'il retient un
   mutex. Si vous avez besoin de maintenir un verrouillage pendant
   une suspension, utilisez un lockmgr(9) verrou ("lock").

   Chaque mutex a plusieurs interets :

   Nom de la variable

           Nom de la variable struct mtx dans le code source du
           noyau.

   Nom logique

           Le nom du mutex lui est assigne par mtx_init. Ce nom est
           affiche dans les messages de trace KTR, temoigne des
           erreurs et avertissements et est utilise pour distinguer
           les mutex dans les traces.

   Type

           Le type du mutex en termes de constantes nommees MTX_*. La
           signification de chaque constante nommee est documentee
           dans mutex(9).

                MTX_DEF

                        Un mutex endormi

                MTX_SPIN

                        Un mutex tournant

                MTX_COLD

                        Ce mutex est initialise tres tard. Toutefois,
                        il doit etre declare via MUTEX_DECLARE, et la
                        constante nommee MTX_COLD doit etre passee `a
                        mtx_init.

                MTX_TOPHALF

                        Ce mutex tournant ne desactive pas les
                        interruptions.

                MTX_NORECURSE

                        Ce mutex n'a pas la permission d'etre
                        recursif.

   Proteges

           Une liste de structures de donnees ou des membres de
           structure de donnees que cette entree protege. Pour les
           membres de structures de donnees, le nom sera de la forme
           structure name.member name.

   Fonctions dependantes

           Les fonctions qui peuvent seulement etre appelees si ce
           mutex est pris.

   Tableau 8-1. Liste du mutex

   +-------------------------------------------------------------------+
   | Nom de la  |  Nom   |  Type  |      Proteges       |  Fonctions   |
   |  variable  |logique |        |                     | dependantes  |
   |------------+--------+--------+---------------------+--------------|
   |            |        |        |_gmonparam,          |              |
   |            |        |        |cnt.v_swtch, cp_time,|              |
   |            |        |        |curpriority,         |              |
   |            |        |        |mtx.mtx_blocked,     |              |
   |            |        |        |mtx.mtx_contested,   |              |
   |            |        |        |proc.p_contested,    |              |
   |            |        |        |proc.p_blocked,      |              |
   |            |        |        |proc.p_flag (P_PROFIL|              |
   |            |        |        |XXX, P_INMEM,        |              |
   |            |        |        |P_SINTR, P_TIMEOUT,  |              |
   |            |        |        |P_SWAPINREQ XXX,     |              |
   |            |        |        |P_INMEN XXX),        |              |
   |            |        |        |proc.p_nice,         |              |
   |            |        |        |proc.p_procq,        |              |
   |            |        |        |proc.p_blocked,      |              |
   |            |        |        |proc.p_estcpu,       |              |
   |            |        |        |proc.p_nativepri,    |              |
   |            |        |        |proc.p_priority,     |setrunqueue,  |
   |            |        |        |proc.p_usrpri,       |remrunqueue,  |
   |            |        |        |proc.p_rtprio,       |mi_switch,    |
   |            |        |        |proc.p_rqindex,      |chooseproc,   |
   |            |"sched  |MTX_SPIN|proc.p_stats->p_prof,|schedclock,   |
   |sched_lock  |lock"   ||       |proc.p_stats->p_ru,  |resetpriority,|
   |            |        |MTX_COLD|proc.p_stat,         |updatepri,    |
   |            |        |        |proc.p_cpticks,      |maybe_resched,|
   |            |        |        |proc.p_iticks,       |cpu_switch,   |
   |            |        |        |proc.p_uticks,       |cpu_throw     |
   |            |        |        |proc.p_sticks,       |              |
   |            |        |        |proc.p_swtime,       |              |
   |            |        |        |proc.p_slptime,      |              |
   |            |        |        |proc.p_runtime,      |              |
   |            |        |        |proc.p_pctcpu,       |              |
   |            |        |        |proc.p_oncpu,        |              |
   |            |        |        |proc.p_asleep,       |              |
   |            |        |        |proc.p_wchan,        |              |
   |            |        |        |proc.p_wmesg,        |              |
   |            |        |        |proc.p_slpq,         |              |
   |            |        |        |proc.p_vmspace (XXX -|              |
   |            |        |        |in statclock), pscnt,|              |
   |            |        |        |slpque, itqueuebits, |              |
   |            |        |        |itqueues,            |              |
   |            |        |        |rtqueuebits,         |              |
   |            |        |        |rtqueues, queuebits, |              |
   |            |        |        |queues, idqueuebits, |              |
   |            |        |        |idqueues, switchtime,|              |
   |------------+--------+--------+---------------------+--------------|
   |            |"vm86pcb|MTX_DEF |                     |              |
   |vm86pcb_lock|lock"   ||       |vm86pcb              |vm86_bioscall |
   |            |        |MTX_COLD|                     |              |
   |------------+--------+--------+---------------------+--------------|
   |            |        |MTX_DEF |                     |              |
   |Giant       |"Giant" ||       |nearly everything    |lots          |
   |            |        |MTX_COLD|                     |              |
   |------------+--------+--------+---------------------+--------------|
   |            |        |        |callfree, callwheel, |              |
   |            |"callout|        |nextsoftcheck,       |              |
   |callout_lock|lock"   |MTX_SPIN|proc.p_itcallout,    |              |
   |            |        |        |proc.p_slpcallout,   |              |
   |            |        |        |softticks, ticks     |              |
   +-------------------------------------------------------------------+

     --------------------------------------------------------------

8.2. Les verrous du gestionnaire de verrous (Lock Manager)

   Les verrous qui sont fournis par l'interface lockmgr(9) sont les
   verrous du gestionnaire de verrous. Ces verrous sont des verrous
   lecture-ecriture et peuvent etre retenus par un process suspendu.

   Tableau 8-2. lockmgr(9) List de verrou

   +----------------------------------------------------------------+
   |  Nom de la   |   Proteges    |                                 |
   |   variable   |               |                                 |
   |--------------+---------------+---------------------------------|
   |              | allproc       |               |                 |
   |              | zombproc      |               |                 |
   | allproc_lock | pidhashtbl    | proctree_lock | proc.p_children |
   |              | proc.p_list   |               | proc.p_sibling  |
   |              | proc.p_hash   |               |                 |
   |              | nextpid       |               |                 |
   +----------------------------------------------------------------+

     --------------------------------------------------------------

8.3. Variables protegees atomiquement

   Une variable protegee atomiquement est une variable speciale qui
   n'est pas protege par un verrou explicite. Toutefois, tous les
   acces de donnees aux variables utilisent des operations atomiques
   speciales comme decrit dans atomic(9). Tres peu de variables sont
   traitees de cette fac,on, bien que les autres primitives de
   synchronisation comme les mutex soient implementees avec des
   variables protegees atomiquement.

     * astpending

     * mtx.mtx_lock

                    IV. Memoire et memoire virtuelle

   Table des matieres

   9. La memoire virtuelle

     --------------------------------------------------------------

                    Chapitre 9. La memoire virtuelle

   MV, gestion par page, gestion sur disque, allouer de la memoire,
   tester les fuites de memoires, mmap, vnodes, etc.

                    V. Systeme E/S (Entrees/Sorties)

   Table des matieres

   10. UFS

     --------------------------------------------------------------

                            Chapitre 10. UFS

   UFS, FFS, Ext2FS, JFS, inodes, memoire tampon, mettre `a jour les
   donnees d'un disque, verrouillage, metadata, soft-updates, LFS,
   portalfs, procfs, vnodes, partage de memoire, objets en memoire,
   TLBs, mettre en cache

                 VI. Communication InterProcessus (IPC)

   Table des matieres

   11. Les signaux

     --------------------------------------------------------------

                        Chapitre 11. Les signaux

   Signaux, tubes, semaphores, files de message, segments de memoire
   partagee, ports, prises, portes

                             VII. Le reseau

   Table des matieres

   12. Les prises

     --------------------------------------------------------------

                        Chapitre 12. Les prises

   Prises, bpf, IP, TCP, UDP, ICMP, OSI, ponts, pare-feux,
   translation d'adresses (NAT), separation de reseaux, etc

                  VIII. Systemes de fichiers en reseau

   Table des matieres

   13. AFS

     --------------------------------------------------------------

                            Chapitre 13. AFS

   AFS, NFS, SANs etc]

                        IX. Gestion du terminal

   Table des matieres

   14. Syscons

     --------------------------------------------------------------

                          Chapitre 14. Syscons

   Syscons, tty, PCVT, console en liaison serie, economiseurs
   d'ecran, etc

                               X. Le son

   Table des matieres

   15. OSS

     --------------------------------------------------------------

                            Chapitre 15. OSS

   OSS, formes d'ondes, etc

                      XI. Pilotes de peripherique

   Table des matieres

   16. Ecrire des pilotes de peripheriques pour FreeBSD

   17. Les peripheriques PCI

   18. Controleurs SCSI Common Access Method (CAM) **

   19. Peripheriques USB ***

   20. NewBus

     --------------------------------------------------------------

     Chapitre 16. Ecrire des pilotes de peripheriques pour FreeBSD

   Ce chapitre a ete ecrit par Murray Stokely <murray@FreeBSD.org>
   avec des selections depuis une variete de codes source inclus dans
   la page de manuel d'intro(4) de Joerg Wunsch.

     --------------------------------------------------------------

16.1. Introduction

   Ce chapitre fournit une breve introduction sur l'ecriture de
   pilotes de peripheriques pour FreeBSD. Un peripherique, dans ce
   contexte, est un terme utilise le plus souvent pour tout ce qui
   est lie au materiel et qui depend du systeme, comme les disques,
   imprimantes, ou un ecran avec son clavier. Un pilote de
   peripherique est un composant logiciel du systeme d'exploitation
   qui controle un peripherique specifique. Il y a aussi ce que l'on
   apelle les pseudo-peripheriques ("pseudo-devices") ou un pilote de
   peripherique emule le comportement d'un peripherique dans un
   logiciel sans materiel particulier sous-jacent. Les pilotes de
   peripheriques peuvent etre compiles dans le ysteme statiquement ou
   charge `a la demande via l'editeur de liens dynamique du noyau
   "kld".

   La plupart des peripheriques dans un systeme d'exploitation de
   type Unix sont accessibles au travers de fichiers speciaux de
   peripherique (device-nodes), appeles parfois fichiers speciaux.
   Ces fichiers sont habituellement stockes dans le repertoire /dev
   de la hierarchie du systeme de fichiers. Jusqu'`a ce que devfs
   soit totalement integre dans FreeBSD, chaque fichier special de
   peripherique doit etre cree statiquement et independamment de
   l'existence du pilote de peripherique associe. La plupart des
   fichiers speciaux de peripherique du systeme sont crees en
   executant MAKEDEV.

   Les pilotes de peripherique peuvent etre en gros separes en deux
   categories; les pilotes de peripherique en mode caractere et les
   pilotes de peripheriques reseau.

     --------------------------------------------------------------

16.2. L'editeur de liens dynamiques du noyau - KLD

   L'interface kld permet aux administrateurs systeme d'ajouter et
   d'enlever dynamiquement une fonctionnalite `a un systeme en
   marche. Cela permet aux developpeurs de pilote de peripherique de
   charger leurs nouveaux changements dans le noyau en fonctionnement
   sans redemarrer constamment pour tester ces derniers.

   L'interface kld est utilise au travers des commandes
   d'administrateur suivantes :

     * kldload - charge un nouveau module dans le noyau

     * kldunload - decharge un module du noyau

     * kldstat - liste les modules charges dans le noyau

   Structure squelettique d'un module de noyau

 /*
  * Squelette KLD
  * Inspire de l'article d'Andrew Reiter paru sur Daemonnews
  */

 #include <sys/types.h>
 #include <sys/module.h>
 #include <sys/systm.h>  /* uprintf */
 #include <sys/errno.h>
 #include <sys/param.h>  /* defines utilise dans kernel.h */
 #include <sys/kernel.h> /* types utilise dans le module d'initialisation */

 /*
  * charge le gestionnaire quit traite du chargement et dechargement d'un KLD.
  */

 static int
 skel_loader(struct module *m, int what, void *arg)
 {
   int err = 0;

   switch (what) {
   case MOD_LOAD:                /* kldload */
    
     uprintf("Skeleton KLD charge.\n");
     break;
   case MOD_UNLOAD:
     uprintf("Skeleton KLD decharge.\n");
     break;
   default:
     err = EINVAL;
     break;
   }
   return(err);
 }

 /* Declare ce module au reste du noyau */

 DECLARE_MODULE(skeleton, skel_loader, SI_SUB_KLD, SI_ORDER_ANY);

     --------------------------------------------------------------

  16.2.1. Makefile

   FreeBSD fournit un fichier d'inclusion "makefile" que vous pouvez
   utiliser pour compiler rapidement votre ajout au noyau.

 SRCS=skeleton.c
 KMOD=skeleton

 .include <bsd.kmod.mk>

   Lancer simplement la commande make avec ce fichier Makefile creera
   un fichier skeleton.ko qui peut etre charge dans votre systeme en
   tapant :

  #        kldload -v ./skeleton.ko

     --------------------------------------------------------------

16.3. Acceder au pilote d'un peripherique

   Unix fournit un ensemble d'appels syteme communs utilisable par
   les applications de l'utilisateur. Les couches superieures du
   noyau renvoient ces appels au pilote de peripherique correspondant
   quand un utilisateur accede au fichier special de peripherique. Le
   script /dev/MAKEDEV cree la plupart des fichiers speciaux de
   peripherique pour votre systeme mais si vous faites votre propre
   developpement de pilote, il peut etre necessaire de creer vos
   propres fichiers speciaux de peripherique avec la commande mknod

     --------------------------------------------------------------

  16.3.1. Creer des fichiers speciaux de peripheriques statiques

   La commande mknod necessite quatre arguments pou creer un fichier
   special de peripherique. Vous devez specifier le nom de ce fichier
   special de peripherique, le type de peripherique, le numero majeur
   et le numero mineur du peripherique.

     --------------------------------------------------------------

  16.3.2. Les fichiers speciaux de peripherique dynamiques

   Le peripherique systeme de fichiers, ou devfs, fournit l'acces `a
   l'espace des noms des peripheriques du noyau dans l'espace du
   systeme de fichiers global. Ceci elimine les problemes de pilote
   sans fichier special statique, ou de fichier special sans pilote
   installe. Devfs est toujours un travail en cours mais il
   fonctionne dej`a assez bien.

     --------------------------------------------------------------

16.4. Les peripheriques caracteres

   Un pilote de peripherique caractere est un pilote qui tranfere les
   donnees directement au processus utilisateur ou vers celui-ci. Il
   s'agit du plus commun des types de pilote de peripherique et il y
   en a plein d'exemples simples dans l'arbre des sources.

   Cet exemple simple de pseudo-peripherique enregistre toutes les
   valeurs que vous lui avez ecrites et peut vous les renvoyer quand
   vous les lui demandez.

 /*
  * un simple pseudo-peripherique `echo' KLD
  *
  * Murray Stokely
  */

 #define MIN(a,b) (((a) < (b)) ? (a) : (b))

 #include <sys/types.h>
 #include <sys/module.h>
 #include <sys/systm.h> /* uprintf */
 #include <sys/errno.h>
 #include <sys/param.h>  /* defines utilises dans kernel.h */
 #include <sys/kernel.h> /* types utilises dans me module d'initialisation */
 #include <sys/conf.h>   /* cdevsw struct */
 #include <sys/uio.h>    /* uio struct */
 #include <sys/malloc.h>

 #define BUFFERSIZE 256

 /* Prototypes des fonctions */
 d_open_t      echo_open;
 d_close_t     echo_close;
 d_read_t      echo_read;
 d_write_t     echo_write;

 /* Points d'entree du peripherique Caractere */
 static struct cdevsw echo_cdevsw = {
   echo_open,
   echo_close,
   echo_read,
   echo_write,
   noioctl,
   nopoll,
   nommap,
   nostrategy,
   "echo",
   33,                   /* reserve pour lkms - /usr/src/sys/conf/majors */
   nodump,
   nopsize,
   D_TTY,
   -1
 };

 typedef struct s_echo {
   char msg[BUFFERSIZE];
   int len;
 } t_echo;

 /* variables */
 static dev_t sdev;
 static int len;
 static int count;
 static t_echo *echomsg;

 MALLOC_DECLARE(M_ECHOBUF);
 MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "cache pour le module echo");

 /*
  * Cette fonction est appele par les appels systeme kld[un]load(2) pour
  * determiner quelles actions doivent etre faites quand le
  * module est charge ou decharge
  */

 static int
 echo_loader(struct module *m, int what, void *arg)
 {
   int err = 0;

   switch (what) {
   case MOD_LOAD:                /* kldload */
     sdev = make_dev(&echo_cdevsw,
                     0,
                     UID_ROOT,
                     GID_WHEEL,
                     0600,
                     "echo");
     /* aloocation de memoire noyau pour l'utilisation de ce module */
     /*    malloc(256,M_ECHOBUF,M_WAITOK); */
     MALLOC(echomsg, t_echo *, sizeof(t_echo), M_ECHOBUF, M_WAITOK);
     printf("Peripherique Echo charge.\n");
     break;
   case MOD_UNLOAD:
     destroy_dev(sdev);
     FREE(echomsg,M_ECHOBUF);
     printf("Peripherique Echo decharge.\n");
     break;
   default:
     err = EINVAL;
     break;
   }
   return(err);
 }

 int
 echo_open(dev_t dev, int oflags, int devtype, struct proc *p)
 {
   int err = 0;

   uprintf("Peripherique \"echo\" ouvert avec succes.\n");
   return(err);
 }

 int
 echo_close(dev_t dev, int fflag, int devtype, struct proc *p)
 {
   uprintf("Fermeture du peripherique \"echo.\"\n");
   return(0);
 }

 /*
  * La fonction read prend juste comme parametre
  * le cache qui a ete sauve par l'appel `a echo_write()
  * et le retourne a l'utilisateur pour acces.
  * uio(9)
  */

 int
 echo_read(dev_t dev, struct uio *uio, int ioflag)
 {
   int err = 0;
   int amt;

   /* De quelle taille est cette operation read ?  Aussi grande que l'utilisateur le veut,
      ou aussi grande que les donnees restantes */
   amt = MIN(uio->uio_resid, (echomsg->len - uio->uio_offset > 0) ? echomsg->len - uio->uio_offset : 0);
   if ((err = uiomove(echomsg->msg + uio->uio_offset,amt,uio)) != 0) {
     uprintf("uiomove echoue!\n");
   }

   return err;
 }

 /*
  * echo_write prend un caractere en entree et le sauve
  * dans le cache pour une utilisation ulterieure.
  */

 int
 echo_write(dev_t dev, struct uio *uio, int ioflag)
 {
   int err = 0;

   /* Copie la chaine d'entree de la memoire de l'utilisateur a la memoire du noyau*/
   err = copyin(uio->uio_iov->iov_base, echomsg->msg, MIN(uio->uio_iov->iov_len,BUFFERSIZE));

   /* Maintenant nous avons besoin de terminer la chaine par NULL */
   *(echomsg->msg + MIN(uio->uio_iov->iov_len,BUFFERSIZE)) = 0;
   /* Enregistre la taille */
   echomsg->len = MIN(uio->uio_iov->iov_len,BUFFERSIZE);

   if (err != 0) {
     uprintf("Ecriture echouee: mauvaise adresse!\n");
   }

   count++;
   return(err);
 }

 DEV_MODULE(echo,echo_loader,NULL);

   Pour installer ce pilote, vous devrez d'abord creer un fichier
   special dans votre systeme de fichiers avec une commande comme :

         # mknod /dev/echo c 33 0

   Avec ce pilote charge, vous devriez maintenant etr capable de
   taper quelque chose comme :

         # echo -n "Test Donnees" > /dev/echo
         # cat /dev/echo
         Test Donnees

   Peripheriques reels dans le chapitre suivant.

   Informations additionnelles

     * Dynamic Kernel Linker (KLD) Facility Programming Tutorial -
       Daemonnews October 2000

     * How to Write Kernel Drivers with NEWBUS - Daemonnews July 2000

     --------------------------------------------------------------

16.5. Pilotes Reseau

   Les pilotes pour peripherique reseau n'utilisent pas les fichiers
   speciaux pour pouvoir etre acessibles. Leur selection est basee
   sur d'autres decisions faites `a l'interieur du noyau et plutot
   que d'appeler open(), l'utilisation d'un peripherique reseau se
   fait generalement en se servant de l'appel systeme socket(2).

   man ifnet(), peripherique "en boucle", drivers de Bill Paul, etc..

     --------------------------------------------------------------

                   Chapitre 17. Les peripheriques PCI

   Ce chapitre traitera des mecanismes de FreeBSD pour ecrire un
   pilote de peripherique pour un peripherique sur bus PCI.

     --------------------------------------------------------------

17.1. Rechercher et rattacher

   Informations ici sur comment le code du bus PCI fait un cycle sur
   les peripheriques non rattaches et voir si le nouvellement charge
   pilote de peripherique chargeable dans le noyau (kld) sera
   rattache `a l'un d'eux.

 /*
  * Simple KLD pour jouer avec les fonctions PCI.
  *
  * Murray Stokely
  */

 #define MIN(a,b) (((a) < (b)) ? (a) : (b))

 #include <sys/types.h>
 #include <sys/module.h>
 #include <sys/systm.h>  /* uprintf */
 #include <sys/errno.h>
 #include <sys/param.h>  /* defines used in kernel.h */
 #include <sys/kernel.h> /* types used in module initialization */
 #include <sys/conf.h>   /* cdevsw struct */
 #include <sys/uio.h>    /* uio struct */
 #include <sys/malloc.h>
 #include <sys/bus.h>    /* structs, prototypes for pci bus stuff */

 #include <pci/pcivar.h> /* For get_pci macros! */

 /* Prototypes des fonctions */
 d_open_t      mypci_open;
 d_close_t     mypci_close;
 d_read_t      mypci_read;
 d_write_t     mypci_write;

 /* Points d'entree du pilote de peripherique caractere */

 static struct cdevsw mypci_cdevsw = {
   mypci_open,
   mypci_close,
   mypci_read,
   mypci_write,
   noioctl,
   nopoll,
   nommap,
   nostrategy,
   "mypci",
   36,                   /* reserved for lkms - /usr/src/sys/conf/majors */
   nodump,
   nopsize,
   D_TTY,
   -1
 };

 /* variables */
 static dev_t sdev;

 /* Nous sommes plus interresses dans la recherche/attachement
 que dans l'ouverture/fermeture/lecture/ecriture a ce point */

 int
 mypci_open(dev_t dev, int oflags, int devtype, struct proc *p)
 {
   int err = 0;

   uprintf("Peripherique \"monpci\" ouvert avec succes.\n");
   return(err);
 }

 int
 mypci_close(dev_t dev, int fflag, int devtype, struct proc *p)
 {
   int err=0;

   uprintf("Peripherique \"monpci.\ "ferme\n");
   return(err);
 }

 int
 mypci_read(dev_t dev, struct uio *uio, int ioflag)
 {
   int err = 0;

   uprintf("lecture dans monpci!\n");
   return err;
 }

 int
 mypci_write(dev_t dev, struct uio *uio, int ioflag)
 {
   int err = 0;

   uprintf("Ecriture dans monpci!\n");
   return(err);
 }

 /* PCI Support Functions */

 /*
  * Retourne la chaine d'identification si ce peripherique est le notre
  */
 static int
 mypci_probe(device_t dev)
 {
   uprintf("MonPCI Probe\n"
           "ID Fabricant: 0x%x\n"
           "ID Peripherique : 0x%x\n",pci_get_vendor(dev),pci_get_device(dev));

   if (pci_get_vendor(dev) == 0x11c1) {
     uprintf("Nous avons le WinModem, recherche reussi!\n");
     return 0;
   }

   return ENXIO;
 }

 /* La fonction Attach n'est appelee que si
 la recherche est reussie*/

 static int
 mypci_attach(device_t dev)
 {
   uprintf("Rattachement de MonPCI pour: ID Peripherique: 0x%x\n",pci_get_vendor(dev));
   sdev = make_dev(&mypci_cdevsw,
                   0,
                   UID_ROOT,
                   GID_WHEEL,
                   0600,
                   "monpci");
   uprintf("Peripherique Monpci charge.\n");
   return ENXIO;
 }

 /* Detach le peripherique. */

 static int
 mypci_detach(device_t dev)
 {
   uprintf("Monpci detache!\n");
   return 0;
 }

 /* Appele lors de l'arret du systeme apres sync. */

 static int
 mypci_shutdown(device_t dev)
 {
   uprintf("Monpci arrete!\n");
   return 0;
 }

 /*
  * routine de suspension du peripherique
  */
 static int
 mypci_suspend(device_t dev)
 {
   uprintf("Monpci suspendu!\n");
   return 0;
 }

 /*
  * routine de reprise du peripherique
  */

 static int
 mypci_resume(device_t dev)
 {
   uprintf("Monpci resume!\n");
   return 0;
 }

 static device_method_t mypci_methods[] = {
         /* Interface Peripherique*/
         DEVMETHOD(device_probe,         mypci_probe),
         DEVMETHOD(device_attach,        mypci_attach),
         DEVMETHOD(device_detach,        mypci_detach),
         DEVMETHOD(device_shutdown,      mypci_shutdown),
         DEVMETHOD(device_suspend,       mypci_suspend),
         DEVMETHOD(device_resume,        mypci_resume),

         { 0, 0 }
 };

 static driver_t mypci_driver = {
         "monpci",
         mypci_methods,
         0,
         /*      sizeof(struct mypci_softc), */
 };

 static devclass_t mypci_devclass;

 DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0);

   Informations complementaires

     * PCI Special Interest Group

     * PCI System Architecture, Fourth Edition by Tom Shanley, et al.

     --------------------------------------------------------------

17.2. Les ressources du bus

   FreeBSD fournit un mecanisme oriente objet pour demander des
   ressources du bus parent. Pratiquement tous les peripheriques
   seront un fils membre d'un type de bus (PCI, ISA, USB, SCSI, etc)
   et ces peripheriques necessite des ressources issues de leur bus
   parent (comme des segments de memoire, des interruptions or des
   canaux DMA).

     --------------------------------------------------------------

  17.2.1. Registres d'adresse de base

   Pour faire de particulierement utile avec un peripherique PCI,
   vous aurez besoin d'obtenir les registres d'adresse de base (Base
   Address Registers ou BARs) de l'espace de configuration PCI. Les
   details specifiques au PCI sur l'obtention du registre d'adresse
   de base sont masques dans la fonction bus_alloc_resource().

   Par exemple, un pilote typique aura sa fonction attach() similaire
   `a ceci :

     sc->bar0id = 0x10;
     sc->bar0res = bus_alloc_resource(dev, SYS_RES_MEMORY, &(sc->bar0id),
                                   0, ~0, 1, RF_ACTIVE);
     if (sc->bar0res == NULL) {
         uprintf("Allocation memoire du registre PCI de base 0 echouee!\n");
         error = ENXIO;
         goto fail1;
     }

     sc->bar1id = 0x14;
     sc->bar1res = bus_alloc_resource(dev, SYS_RES_MEMORY, &(sc->bar1id),
                                   0, ~0, 1, RF_ACTIVE);
     if (sc->bar1res == NULL) {
         uprintf("Allocation memoire du registre PCI de base 1 echouee!\n");
         error =  ENXIO;
         goto fail2;
     }
     sc->bar0_bt = rman_get_bustag(sc->bar0res);
     sc->bar0_bh = rman_get_bushandle(sc->bar0res);
     sc->bar1_bt = rman_get_bustag(sc->bar1res);
     sc->bar1_bh = rman_get_bushandle(sc->bar1res);


   Des references pour chaque registre d'adresse de base sont gardees
   dans la structure softc afin qu'elle puisse etre utilisee pour
   ecrire dans le peripherique plus tard.

   Ces references peuvent alors etre utilisees pour lire ou ecrire
   dans les registres du peripherique avec les fonctions bus_space_*.
   Par exemple, un pilote peut contenir une fonction raccourci pour
   lire dans un registre specifique `a une carte comme cela :

 uint16_t
 board_read(struct ni_softc *sc, uint16_t address) {
     return bus_space_read_2(sc->bar1_bt, sc->bar1_bh, address);
 }

   De fac,on similaire, une autre peut ecrire dans les registres avec
   :

 void
 board_write(struct ni_softc *sc, uint16_t address, uint16_t value) {
     bus_space_write_2(sc->bar1_bt, sc->bar1_bh, address, value);
 }

   Ces fonctions existent en versions 8bit, 16bit et 32bit et vous
   devriez utiliser bus_space_{read|write}_{1|2|4} en consequence.

     --------------------------------------------------------------

  17.2.2. Les interruptions

   Les interruptions sont alloues `a partir du code oriente objet du
   bus de fac,on similaire aux ressources memoire. D'abord une
   ressource IRQ doit etre allouee `a partir du bus parent, et alors
   le gestionnaire d'interruption doit etre regle pour traiter cet
   IRQ.

   A nouveau, un exemple de fonction attach() en dit plusqu'un long
   discours.

 /* Recupere la ressource IRQ */

     sc->irqid = 0x0;
     sc->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &(sc->irqid),
                                   0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
     if (sc->irqres == NULL) {
         uprintf("Allocation IRQ echouee!\n");
         error = ENXIO;
         goto fail3;
     }

     /* Maitnenant nous choisissons notre gestionnaire d'interruption */

     error = bus_setup_intr(dev, sc->irqres, INTR_TYPE_MISC,
                            my_handler, sc, &(sc->handler));
     if (error) {
         printf("Ne peut regler l'IRQ\n");
         goto fail4;
     }

     sc->irq_bt = rman_get_bustag(sc->irqres);
     sc->irq_bh = rman_get_bushandle(sc->irqres);

     --------------------------------------------------------------

  17.2.3. DMA

   Sur les PC, les peripheriques qui veulent utiliser la gestion de
   bus DMA doivent travailler avec des adresses physiques. C'est un
   probleme puisque FreeBSD utilise une memoire virtuelle et
   travaille presque exclusivement avec des adresses virtuelles.
   Heureusement, il y a une fonction vtophys() pour nous aider.

 #include <vm/vm.h>
 #include <vm/pmap.h>

 #define vtophys(virtual_address) (...)

   La solution est toutefois un peu differente sur Alpha, et ce que
   nous voulons reellement est une fonction appelee vtobus().

 #if defined(__alpha__)
 #define vtobus(va)      alpha_XXX_dmamap((vm_offset_t)va)
 #else
 #define vtobus(va)      vtophys(va)
 #endif

     --------------------------------------------------------------

  17.2.4. Desallouer les resources

   Il est tres important de desallouer toutes les ressources qui
   furent allouees pendant attach(). Unsoin tout particulier doit
   etre pris pour desallouer les bonnes choses meme lors d'un echec
   afin que le systeme reste utilisable lorsque votre driver meurt.

     --------------------------------------------------------------

      Chapitre 18. Controleurs SCSI Common Access Method (CAM) **

18.1. En cours de traduction

   En cours de traduction

     --------------------------------------------------------------

                   Chapitre 19. Peripheriques USB ***

   Ce chapitre a ete ecrit par Nick Hibma <n_hibma@FreeBSD.org>. Les
   modifications pour le manuel par Murray Stokely
   <murray@FreeBSD.org>.

     --------------------------------------------------------------

19.1. Introduction

   Chapitre `a traduire.

     --------------------------------------------------------------

                          Chapitre 20. NewBus

   Ce chapitre traitera de l'architecture NewBus de FreeBSD.

                           XII. Architectures

   Table des matieres

   21. IA-32

   22. Alpha

   23. IA-64

     --------------------------------------------------------------

                           Chapitre 21. IA-32

   Traite des specificites de l'architecture x86 sous FreeBSD.

     --------------------------------------------------------------

                           Chapitre 22. Alpha

   Traite des specificites de l'architecture Alpha sous FreeBSD.

   Explication des erreurs d'alignements, comment les reparer,
   comment les ignorer.

   Exemple de code assembleur pour FreeBSD/alpha.

     --------------------------------------------------------------

                           Chapitre 23. IA-64

   Traite des specificites de l'architecture IA-64 sous FreeBSD.

                           XIII. Deverminage

   Table des matieres

   24. Truss

     --------------------------------------------------------------

                           Chapitre 24. Truss

   diverses descriptions sur les methodes de deverminage de certains
   aspects du systeme utilisant truss, ktrace, gdb, kgdb, etc

                   XIV. Les couches de compatibilite

   Table des matieres

   25. Linux

     --------------------------------------------------------------

                           Chapitre 25. Linux

   Linux, SVR4, etc

                            XV. Bibligraphie

   Table des matieres

   Bibliographie

  Bibliographie

   [1] Dave A Patterson et John L Hennessy, 1998, 1-55860-428-6,
   Morgan Kaufmann Publishers, Inc., Computer Organization and
   Design: The Hardware / Software Interface, 1-2.

   [2] W. Richard Stevens, 1993, 0-201-56317-7, Addison Wesley
   Longman, Inc., Advanced Programming in the Unix Environment, 1-2.

   [3] Marshall Kirk McKusick, Keith Bostic, Michael J Karels, et
   John S Quarterman, 1996, 0-201-54979-4, Addison-Wesley Publishing
   Company, Inc., The Design and Implementation of the 4.4 BSD
   Operating System, 1-2.

   [4] Aleph One, Phrack 49; "Smashing the Stack for Fun and Profit".

   [5] Chrispin Cowan, Calton Pu, et Dave Maier, StackGuard;
   Automatic Adaptive Detection and Prevention of Buffer-Overflow
   Attacks.

   [6] Todd Miller et Theo de Raadt, strlcpy and strlcat --
   consistent, safe string copy and concatenation..

  Notes

   [1]  Si vous l'executer `a l'invite de commande, vous pouvez       
        recevoir un fichier d'image memoire (NDT: le desormais        
        celebre "core dump").                                         
   [2]  Pour etre vraiment precis, cc convertit `a ce niveau le code  
        source dans son propre p-code independant de la machine       
        plutot qu'en langage assembleur.                              
   [3]  Au cas ou vous ne le sauriez pas, un tri binaire est un       
        maniere efficace de trier les elements et le tri `a bulles    
        n'en est pas une.                                             
   [4]  Les raisons de ceci sont enterrees dans les brumes de         
        l'histoire.                                                   
   [5]  Notez, nous n'avons pas utilise l'option -o pour specifier le 
        nom de l'executable, aussi nous obtiendrons un executable du  
        nom de a.out. Produire une version de deverminage du nom de   
        foobar est laisse en exercice pour le lecteur!                
   [6]  NDT: je n'ai pas trouve de meilleure traduction pour core     
        memory                                                        
   [7]  Ils n'utilisent pas la forme MAKEFILE car les bloques de      
        majuscules sont souvent utilises pour les fichiers de         
        documentation comme README.                                   
   [8]  NDT: On entendra plus souvent parler de patch.                
   [9]  Sauf si vous payez des sommes importantes.                    
   [10] Beaucoup d'utilisateurs d'Emacs mettent leur variable         
        d'environnement EDITOR `a emacsclient ainsi cela se passe `a  
        chaque fois qu'ils ont besoin d'editer un fichier.            
   [11] NDT : Sur FreeBSD 4.2-RELEASE aussi.                          
   [12] NDT : Jaune de preference pour etre bien visible              

     --------------------------------------------------------------

        Ce document, ainsi que d'autres peut etre telecharge sur
                   ftp.FreeBSD.org/pub/FreeBSD/doc/.

Pour toutes questions `a propos de FreeBSD, lisez la documentation avant
                 de contacter <questions@FreeBSD.org>.
Pour les questions sur cette documentation, contactez <doc@FreeBSD.org>.
