[ précédent ] [ Table des matières ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ 13 ] [ 14 ] [ 15 ] [ A ] [ suivant ]


Guide de référence pour Debian
Chapitre 13 - Programmation


N'utilisez pas « test » comme nom d'exécutable pour un fichier de test. test est une commande du shell.


13.1 Où commencer

Références :

Beaucoup de longs documents informatifs peuvent être obtenus sur papier par GNU.

Les quatres sections suivantes contiennent quelques scripts d'exemple dans différents langages pour créer un fichier texte d'information sur les comptes utilisateur qui peut être ajouté à /etc/passwd, avec par exemple le programme newusers. Chaque script prend en entrée un fichier contenant des lignes de la forme prénom nom mot_de_passe. (Les répertoires « home » des utilisateurs ne seront pas créés avec ces scripts.)


13.2 Shell

Lire des scripts shell est le meilleur moyen de comprendre comment un système Unix fonctionne. Ici, je donne quelques pointeurs et rappels sur la programmation du shell.


13.2.1 Bash – le shell intéractif standard de GNU

Références pour Bash :

Court exemple de programme (crée des entrées de compte pour newusers à partir de l'entrée standard) :

     #!/bin/bash
     # (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain
     pid=1000;
     while read n1 n2 n3 ; do
     if [ ${n1:0:1} != "#" ]; then
     let pid=$pid+1
     echo ${n1}_${n2}:password:${pid}:${pid}:,,,/home/${n1}_${n2}:/bin/bash
     fi
     done

13.2.2 Shells POSIX

Plusieurs paquets fournissent un shell POSIX dans Debian :

Si vous écrivez des scripts shell portables, il vaut mieux les écrire comme scripts shell POSIX. Utilisez /bin/sh lié vers ash ou (dash) pour tester sa conformité POSIX. Évitez d'écrire des scripts avec des bashismes.


13.2.3 Paramètres du shell

Plusieurs paramètres spéciaux à se rappeler :

     $0      = nom du shell ou du script shell
     $1      = premier argument
      ...
     $9      = neuvième argument
     $#      = nombre de paramètres
     "$*"    = "$1 $2 $3 $4 ... $n"
     "$@"    = "$1" "$2" "$3" "$4" ... "$n"
     $?      = état de sortie de la commande la plus récente
     $$      = PID du script shell
     $!      = PID du processus en arrière-plan le plus récent

Expansions des paramètres de base à se rappeler :

         Forme        Si var est positionné(*)    Si var n'est pas positionné(*)
     ${var:-string}  $var                string
     ${var:+string}  string              null
     ${var:=string}  $var                string
                                         (et lance var=string)
     ${var:?string}  $var                (affiche string et sort)

Ici, les deux points « : » dans tous ces opérateurs est optionnel.

Substitutions de paramètres de base à se rappeler :

         Forme        Résultat
     ${var%suffix}   Supprime le plus petit motif suffix
     ${var%%suffix}  Supprime le plus grand motif suffix
     ${var#prefix}   Supprime le plus petit motif prefix
     ${var##prefix}  Supprime le plus grand motif prefix

13.2.4 Redirection du shell

Redirection de base à se rappeler (ici le [n] est un nombre optionnel) :

     [n]> file     Redirige la sortie standard (ou n) vers file.
     [n]>> file    Ajoute la sortie standard (ou n) à file.
     [n]< file     Redirige l'entrée standard (ou n) depuis file.
     [n1]>&n2      Redirige la sortie standard (ou n1) vers n2
     > file >&2    Redirige l'entrée et l'erreur standards vers file.
     | command     Crée un tuyau (pipe) de l'entrée standard (ou n) vers command.
     >&2 | command Crée un tuyau (pipe) de l'entrée et l'erreur standards
                      vers command.

13.2.5 Opérateurs conditionnels du shell

Toutes les commandes retournent un état de sortie qui peut être utilisé par les expressions conditionnelles :

Notez que l'utilisation de la valeur 0 signifie « vrai » contrairement à d'autres domaines de l'informatique. De même, `[' est l'équivalent de la commande test, qui évalue ses arguments jusqu'à `]' comme expression conditionnelle.

Expressions conditionnelles de base à se rappeler :

     command && si_succès_lance_cette_commande_aussi
     command || si_échec_lance_cette_commande_aussi
     
     if [ expression_conditionnelle ]; then
      si_succès_lance_cette_commande
     else
      si_échec_lance_cette_commande
     fi

Les opérateurs de comparaison de fichiers dans les expressions conditionnelles sont :

     -e file         Vrai si file existe.
     -d file         Vrai si file existe et est un répertoire.
     -f file         Vrai si file existe et est un fichier normal.
     -w file         Vrai si file existe et est en écriture.
     -x file         Vrai si file existe et est exécutable.
     file1 -nt file2 Vrai si file1 est plus récent que file2. (modification)
     file1 -ot file2 Vrai si file1 est plus vieux que file2. (modification)
     file1 -ef file2 Vrai si ce sont les numéros de périphérique et d'inode.

Les opérateurs de comparaison de chaînes dans les expressions conditionnelles sont :

          -z str    Vrai si la longueur de str est zéro.
          -n str    Vrai si la longueur de str est différente de zéro.
     str1 == str2   Vrai si les chaînes sont égales.
     str1 = str2    Vrai si les chaînes sont égales.
                    ( = peut être utilisé à la place de == )
     str1 != str2   Vrai si les chaînes ne sont pas égales.
     str1 <  str2   Vrai si str1 est classée avant str2 (dépend de la locale).
     str1 >  str2   Vrai si str1 est classée après str2 (dépend de la locale).

Les opérateurs de comparaison arithmétique entière dans les expressions conditionnelles sont -eq, -ne, -lt, -le, -gt, ou -ge.


13.2.6 Traitement de la ligne de commande

Le shell traite un script de la façon suivante :

Des guillemets simples dans des guillemets doubles n'ont pas d'effet.


13.3 Awk

Références pour Awk :

Court exemple de programme (crée des entrées de compte pour newusers) :

     #!/usr/bin/awk -f
     # Script pour créer un fichier utilisable avec la commande 'newusers'
     # à partir d'un fichier contenant des IDs utilisateur et des mots de
     # passe sous la forme :
     # Prénom Nom Mot_de_passe
     # Copyright (c) KMSelf Sat Aug 25 20:47:38 PDT 2001
     # Distributed under GNU GPL v 2, or at your option, any later version.
     # This program is distributed WITHOUT ANY WARRANTY.
     
     BEGIN {
         # Assign starting UID, GID
         if ( ARGC > 2 ) {
             startuid = ARGV[1]
             delete ARGV[1]
         }
         else {
             printf( "Usage:  newusers startUID file\n" \
               "...where startUID is the starting userid " \
               "to add, and file is \n" \
               "an input file in form firstname last name password\n" \
             )
             exit
         }
     
         infile = ARGV[1]
         printf( "Starting UID: %s\n\n", startuid )
     }
     
     /^#/ { next }
     
     {
         ++record
         first = $1
         last = $2
         passwd = $3
         user= substr( tolower( first ), 1, 1 ) tolower( last )
         uid = startuid + record - 1
         gid = uid
         printf( "%s:%s:%d:%d:%s %s,,/home/%s:/bin/bash\n",  \
             user, passwd, uid, gid, first, last, user \
             )
     }

Deux paquets fournissent un awk POSIX dans Debian :


13.4 Perl

C'est l'interpréteur sur un système Unix.

Références pour Perl :

Court exemple de programme (crée une entrée newusers) :

     #!/usr/bin/perl
     # (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain
     $pid=1000;
     while (<STDIN>) {
             if (/^#/) { next;}
             chop;
             $pid++;
             ($n1, $n2, $n3) = split / /;
             print $n1,"_",$n2,":", $n3, ":",$pid,
                       ":",$pid,",,,/home/",$n1,"_",$n2,":/bin/bash\n"
     }

Installer le module Perl modulename :

     # perl -MCPAN -e 'install modulename'

13.5 Python

C'est un interpréteur orienté objet sympa.

Références pour Python :

Court exemple de programme (crée une entrée newusers) :

     #! /usr/bin/env python
     import sys, string
     
     # (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain
     # Ported from awk script by KMSelf Sat Aug 25 20:47:38 PDT 2001
     # This program is distributed WITHOUT ANY WARRANTY.
     
     def usages():
         print \
     "Usage:  ", sys.argv[0], " start_UID [filename]\n" \
     "\tstartUID is the starting userid to add.\n" \
     "\tfilename is input file name. If not specified, standard input.\n\n" \
     "Input file format:\n"\
     "\tfirstname lastname password\n"
                     return 1
     
     def parsefile(startuid):
         #
         # main filtering
         #
         uid = startuid
         while 1:
             line = infile.readline()
             if not line:
                 break
             if line[0] == '#':
                 continue
             (first, last, passwd) = string.split(string.lower(line))
             # crashe si le nombre de paramètres est mauvais :-)
             user = first[0] + last
             gid = uid
             lineout = "%s:%s:%d:%d:%s %s,,/home/%s:/bin/bash\n" %  \
                 (user, passwd, uid, gid, first, last, user)
             sys.stdout.write(lineout)
             +uid
     
     if __name__ == '__main__':
         if len(sys.argv) == 1:
             usages()
         else:
             uid = int(sys.argv[1])
             #print "# UID start from: %d\n" % uid
             if len(sys.argv) > 1:
                 infilename   = string.join(sys.argv[2:])
                 infile = open(infilename, 'r')
                 #print "# Read file from: %s\n\n" % infilename
             else:
                 infile = sys.stdin
             parsefile(uid)

13.6 Make

Références pour Make :

Variables automatiques simples :

Syntaxe des règles :

     Target: [ Prerequisite ... ]
      [TAB]  command1
      [TAB]  -command2 # ignore les erreurs
      [TAB]  @command3 # supprime l'écho

Ici, [TAB] est un code TAB. Chaque ligne est interprétée par le shell après la substitution des variables par make. Utiliser \ à la fin d'une ligne pour continuer le script. Utiliser $$ pour entrer $ pour les variables d'environnement du script shell.

Equivalents des règles implicites :

     .c:   header.h == %  : %.c header.h
     .o.c: header.h == %.c: %.o header.h

Variables automatiques pour les règles ci-dessus :

     foo.o: new1.c new2.c.c old1.c new3.c
     $@ == foo.o                         (cible)
     $< == new1.c                        (premier)
     $? == new1.c new2.c new3.c          (plus récent)
     $^ == new1.c new2.c.c old1.c new3.c (tout)
     $* == `%' motif correspondant dans le motif cible.

Référence des variables :

     foo1 := bar    # expansion unique
     foo2  = bar    # expansion récursive
     foo3 += bar    # ajoute
     SRCS := $(wildcard *.c)
     OBJS := $(foo:c=o)
     OBJS := $(foo:%.c=%.o) 
     OBJS := $(patsubst %.c,%.o,$(foo)) 
     DIRS  = $(dir directory/filename.ext) # Extrait "directory"
     $(notdir NAMES...), $(basename NAMES...), $(suffix NAMES...) ...

Exécuter make -p -f/dev/null pour voir les règles automatiques internes.


13.7 C

Préparation :

     # apt-get install glibc6-doc manpages-dev

Références pour le C :


13.7.1 Programme simple en C (gcc)

Un exemple simple pour compiler example.c avec la bibliothèque libm dans l'exécutable run_example :

     $ cat > example.c  << EOF
     #include <stdio.h>
     #include <math.h>
     #include <string.h>
     
     int main(int argc, char **argv, char **envp){
             double x;
             char y[11];
             x=sqrt(argc+7.5);
             strncpy(y, argv[0], 10); /* empêche un dépassement de tampon */
             y[10] = '\0'; /* remplissage pour être sûr que la chaîne finit
     	                 par '\0' */
             printf("%5i, %5.3f, %10s, %10s\n", argc, x, y, argv[1]);
             return 0;
     }
     EOF
     $ gcc -Wall -g -o run_example exmple.c -lm
     $ ./run_example
             1, 2.915, ./run_exam,     (null)
     $ ./run_example 1234567890qwerty
             2, 3.082, ./run_exam, 1234567890qwerty

Ici, -lm est nécessaire pour lier la bibliothèque libm, pour utiliser sqrt(). La bibliothèque est en fait dans /lib sous le nom libm.so.6 qui est un lien symbolique vers libm-2.1.3.so.

Regardez le dernier paramètre dans le texte affiché. Il y a plus de 10 caractères affichés alors que %10s est spécifié.

L'utilisation de fonctions effectuant des opérations sur des pointeurs sans vérifier la limite, comme sprintf et strcpy, est dépréciée pour prévenir les exploits de dépassement de tampon, annulant les effets ci-dessus. Utilisez snprintf et strncpy à la place.


13.7.2 Déboguer


13.7.2.1 Deboguer avec gdb

Préparation :

     # apt-get install gdb

Références pour gdb :

Utilisez gdb pour déboguer des programmes compilés avec l'option -g. Beaucoup de commandes peuvent être abbréviées. L'expansion par tab marche comme avec le shell.

     $ gdb program
     (gdb) b 1                # positionne un point d'arrêt à la ligne 1
     (gdb) run arg1 arg2 arg3 # exécute le programme
     (gdb) next               # ligne suivante
     ...
     (gdb) step               # pas en avant
     ...
     (gdb) p parm             # affiche parm
     ...
     (gdb) p parm=12          # met la valeur de parm à 12

Pour déboguer depuis Emacs, référez-vous à Résumé des commandes de l'éditeur (Emacs, Vim), Section 11.3.4.


13.7.2.2 Vérifier les dépendances sur des bibliothèques

Utilisez ldd pour trouver les dépendances d'un programme sur des bibliothèques :

     $ ldd /bin/ls
             librt.so.1 => /lib/librt.so.1 (0x4001e000)
             libc.so.6 => /lib/libc.so.6 (0x40030000)
             libpthread.so.0 => /lib/libpthread.so.0 (0x40153000)
             /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

Pour que ls marche dans un environnement chrooté, les bibliothèques suivantes doivent être disponibles dans votre environnement chrooté.

Les commandes suivantes sont aussi utiles :


13.7.2.3 Déboguer avec des outils de détection des fuites de mémoire

Il y a plusieurs outils de détection des fuites de mémoire disponibles dans Debian.

Consultez aussi Debugging Tools for Dynamic Storage Allocation and Memory Management.


13.7.3 Flex – un meilleur Lex

flex est un générateur rapide d'analyseur lexical.

Références pour flex :

Vous devez fournir vos propres main() et yywrap(), ou votre program.l devrait ressembler à ce qui suit pour compiler sans bibliothèque. (yywrap est une macro ; %option mainactive %option noyywrap implicitement) :

     %option main
     %%
     .|\n    ECHO ;
     %%

Autrement, vous pouvez compiler avec l'option de l'éditeur de liens -lfl à la fin de la ligne de commande de cc (comme ATT-Lex avec -ll). %option n'est pas nécessaire dans ce cas.


13.7.4 Bison – un meilleur Yacc

Quelques paquets fournissent un générateur d'analyseur LALR compatible avec Yacc dans Debian :

Références pour bison :

Vous devez fournir vos propres main() et yyerror(). main() appelle yyparse() qui appelle yylex(), habituellement créé avec Flex.

     %%
     
     %%

13.7.5 Autoconf

autoconf est un otil pour produire des scripts shell qui configurent automatiquement les paquets de code source pour s'adapter aux nombreux systèmes Unix qui utilisent le système de compilation GNU entier.

autoconf produit le script de configuration configure. configure crée automatiquement un Makefile personnalisé et Makefile.am.


13.7.5.1 Compiler et installer un programme

Debian ne touche pas aux fichiers de /usr/local (voir Support de la diversité, Section 2.5). Donc si vous compilez un programme depuis le source, installez le dans /usr/local pour qu'il n'interfère pas avec Debian.

     $ cd src
     $ ./configure --prefix=/usr/loca
     $ make
     $ make install # cela met les fichiers dans le système

13.7.5.2 Désinstaller un programme

SI vous avez toujours les sources et si elles utilisent autoconf/automake et si vous vous souvenez comment vous avez configuré la compilation :

     $ ./configure les-options-de-configuration
     # make uninstall

Autrement, si vous êtes absolument sûr que le processus d'installation n'a mis des fichiers que sous /usr/local et qu'il n'y a rien d'important là, vous pouvez supprimer tout son contenu avec :

     # find /usr/local -type f -print0 | xargs -0 rm -f

Si vous n'êtes pas sûr de l'emplacement des fichiers installés, vous devriez considérer l'utilisation de checkinstall qui fournit un moyen de désinstallation propre.


13.8 Préparation de documents


13.8.1 Traitement de texte roff

Traditionnellement, roff est le système de traitement de texte principal d'Unix.

Voir roff(7), groff(7), groff(1), grotty(1), troff(1), groff_mdoc(7), groff_man(7), groff_ms(7), groff_me(7), groff_mm(7), et « info groff ».

Un bon didacticiel sur les macros -me existe. Si vous avez groff (1.18 ou plus récent), cherchez le fichier /usr/share/doc/groff/meintro.me.gz et faites ce qui suit :

     $ zcat /usr/share/doc/groff/meintro.me.gz | \
          groff -Tascii -me - | less -R

Ce qui suit construira un fichier texte :

     $ zcat /usr/share/doc/groff/meintro.me.gz | \
         GROFF_NO_SGR=1 groff -Tascii -me - | col -b -x > meintro.txt

Pour imprimer, utilisez la sortie PostScript.

     $ groff -Tps meintro.txt | lpr
     $ groff -Tps meintro.txt | mpage -2 | lpr

13.8.2 SGML

Préparation :

     # apt-get install debiandoc-sgml debiandoc-sgml-doc

Références pour debiandoc-sgml :

SGML permet de gérer plusieurs formats pour un document. Un système SGML facile est Debiandoc, qui est utilisé ici. Cela requiert des conversions mineurs dans le fichier texte original, pour les caractères suivants :

     <   &lt;
     >   &gt;
     " " "&nbsp;"  (espace non séquable)
     &   &amp;
     %   &percnt;
     ©   &copy;
     –   &ndash;
     —   &mdash;

Pour marquer une section en tant que commentaire non imprimable, faites :

     <!-- Indiquez le problème ici ... -->

Pour marquer une section en tant que commentaire ou pas à l'impression, faites :

     <![ %FIXME; [ Indiquez le problème ici ... ]]>

En SGML, la première définition d'une entité l'emporte. Par exemple :

     <!entity % qref "INCLUDE">
     <![ %qref; [ <!entity param "Data 1"> ]]>
     <!entity param "Data 2">
     &param;

Cela termine en tant que « Data 1 ». Si la première ligne inclut « IGNORE » au lieu de « INCLUDE », cela termine en tant que « Data 2 » (la deuxième ligne est une expression conditionnelle). De plus, les phrases souvent répétées peuvent être définies à l'avance séparément du contexte.

     <!entity whoisthis "my">
     Hello &whoisthis; friend.
     This is &whoisthis; book.

Le résultat est :

     Hello my friend.
     This is my book.

Voir le court exemple de SGML sample.sgml dans les exemples.

Lorsque des documents SGML deviennent plus gros, TeX cause parfois des erreurs. Il faut augmenter la taille du bassin dans /etc/texmf/texmf.cnf (ou mieux éditez /etc/texmf/texmf.d/95NonPath et lancez update-texmf) pour réparer cela.


13.9 Paquetage

Préparation :

     # apt-get install debian-policy developers-reference \
             maint-guide dh-make debhelper
     # apt-get install packaging-manual # dans le cas de Potato

Références pour le paquetage :


13.9.1 Paqueter un binaire seul

Méthode rapide et sale pour paqueter un binaire seul par Joey Hess.

     # mkdir -p mypkg/usr/bin mypkg/DEBIAN
     # cp binary mypkg/usr/bin
     # cat > mypkg/DEBIAN/control
     Package: mypackage
     Version: 1
     Architecture: i386
     Maintainer: Joey Hess <joeyh@debian.org>
     Description: my little package
     Don't expect much.
     ^D
     # dpkg-deb -b mypkg

13.9.2 Paqueter avec des outils

Utilisez dh_make du paquet dh-make pour créer l'architecture du paquet. Ensuite, suivez les instructions de dh-make(1), qui utilise debhelper dans debian/rules.

Une approche plus ancienne est d'utiliser deb-make du paquet debmake. Cela n'utilise aucun script debhelper et dépend seulement du shell.

Pour plusieurs paquets source, voir « mc » (dpkg-source -x mc_4.5.54.dsc) qui utilise « sys-build.mk » par Adam Heath (doogie@debian.org) et « glibc » (dpkg-source -x glibc_2.2.4-1.dsc) qui utilise un autre système par feu Joel Klecker (espy@debian.org).


[ précédent ] [ Table des matières ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ 13 ] [ 14 ] [ 15 ] [ A ] [ suivant ]


Guide de référence pour Debian

CVS, jeu 18 jan 2007 11:52:23 UTC

Osamu Aoki osamu#at#debian.org
Traduction en Français : Guillaume Erbs gerbs#at#free.fr
Auteurs, Section A.1