Table des matières

La dernière version de cette bibliothèque devrait se trouver sur http://schplurtz.free.fr/schplurtziel/bibsh/

 

 


  • table des matières
  • Introduction
  • conditions à remplire par le shell
  • Testez votre shell favori
  • petit rappel sur les variables locales
  • petit rappel sur les tableaux
  • commandes externes indispensables.
  • installation
  • Installation proprement dite
  • Vérification des shells
  • installation simple, sur un seul poste
  • installation simple, sur un seul poste, utilisant stow
  • installation sur serveur nfs ou dans un dossier temporaire pour faire un paquet.
  • Si ./Configure ne fonctionne pas.
  • Utilisation
  • « sourcer » ou « compiler »
  • Contraintes techniques
  • Utilisation des boites de dialogue
  • exemples d'utilisation
  • modules et dépendances
  • fichier par fichier
  • liblocal.scl
  • setv
  • setp
  • printp
  • printpn
  • tmpfilename
  • getp (obsolète)
  • libkwubst.scl
  • gsubst val recherche nouveau
  • vargsubst variable recherche nouveau
  • backslashslash val
  • varbackslashslash variable
  • kwote val
  • kwotenokwote val
  • varkwote var
  • varkwotenokwote var
  • libkwote.scl (obsolète, utiliser maintenant libkwubst)
  • libgsubst.scl (obsolète, utiliser maintenant libkwubst)
  • libm.scl
  • __DATA__
  • data
  • warn
  • warnf
  • fatal
  • fatalf
  • libdialog.scl
  • whichdialog
  • whichdialog options obsoletes
  • DIerrbox "message" ["titre de fond"]
  • DImsgbox "message" ["titre de fond"]
  • DIouinon [def=oui|non|yes|no] "message" ["titre" ["titre de fond"]]
  • DItagmenu "message" "titre de fond" [deftag] tag1 article1 tag2 article2...
  • DIcheckbox3 "message" "titre de fond" tag1 article1 etat1 tag2 article2 etat2...
  • libstddial.scl
  • STonefromfile
  • STonefromtagfile
  • SToneof
  • DIcheckbox2 "message" "titre de fond" [etat] tag1 article1 tag2 article2...
  • DIcheckbox1 "message" "titre de fond" article1 article2...
  • libeset.scl
  • eset
  • esetlen
  • esetlist
  • eset_valid
  • libbrowse.scl
  • BRbrowsedir
  • BRbrowsefile
  • libipv4.scl
  • IPsplitip
  • IPiptonum
  • IPnumtoip
  • IPpfxtonum
  • IPpfxtoip
  • IPmaxaddr
  • IPminaddr
  • IPnetwork
  • IPnumbit
  • IPguessnetmask
  • IPnextip
  • libnetchoice.scl
  • GRgetip
  • libethernet.scl
  • ETvalidemacp
  • ETcanonmac
  • ETvendeur
  • ETvendeur_nawk
  • ETget_new_iaboui
  • libdiethernet.scl
  • ETdi_validemac_ou_vide
  • ETdi_validemac
  • ETeset_mac_valide
  • libmaniptab.scl
  • tableau tableau [valeur...]
  • tablong tableau
  • tabaffiche tableau
  • tabcopie dest src
  • tabajoute taleau [valeur] [valeur...]
  • tabdepile tableau variable
  • tabsommet tableau [variable]
  • tabdefile tableau variable
  • tabinsere tableau [valeur] [valeur...]
  • tabintercale tableau indice [valeur] [valeur...]
  • tabplace tableau indice [valeur] [valeur...]
  • tabconcatene tabdst tabsrc1 [tabsrc2...]
  • tabdetruit tableau indice longueur
  • tabdetruit tableau tout
  • tabindicede tableau valeur
  • tabcontient tableau valeur
  • tabtousindicede tableau valeur
  • tabforeach tableau commande
  • tabforeach tableau indice_debut commande
  • tabforeach tableau indice_debut incr commande
  • tabboucle tableau variable commande
  • tabboucle tableau variable indice_debut commande
  • tabboucle tableau variable indice_debut incr commande
  • tabpourn tableau min max commande
  • tabpourn tableau min max incr commande
  • tabmix tabdst tabsrc1 [tabsrc2...]
  • tabsep tabsrc tabdst1 [tabdst2...]
  • tabsauve tableau
  • liboption.scl
  • OCaccepte_option
  • OCaccepte_option_t
  • OCgetopt
  • OCraz
  • OCchange_option
  • Un exemple complet de OCgetopt
  • libexoption.scl
  • OClongue_vers_courte
  • OCchange_option
  • OCobtient_co
  • OCplace_co
  • OCdetruit_co
  • libsystem.scl
  • filemode
  • fileowner
  • get_directory_dev
  • get_directory_mountpoint
  • libquota.scl
  • get_user_block_quota
  • get_user_used_block_quota
  • set_user_block_quota
  • set_dev_user_block_quota
  • Annexes
  • Remarques sur dialog

  • Retour table des matières

    Introduction

    Voici une petite bibliothèque pour script en sh. Comme toute bibliothèque elle est née du besoin de ne plus avoir à coder encore et encore les mêmes actions dans chaque nouveau script. La difficulté consiste à rendre cette bibliothèque aussi portable que possible. Car n'oublions pas que les scripts sont interprétés et qu'autant de shells vont réagir de (presque) autant de manière différentes. Les environnements auquels j'ai accès ont tendance à se restreindre de plus en plus. Au premiers temps de développement, j'étais un homme heureux et je pouvais tester mes routines sur plus de 6 UNIX différents, aujourd'hui je n'ai plus accès qu'à deux type d'unix. La qualité s'en ressentira donc sans doute.

    L'objectif à toujours été la portabilité. Ainsi les spécificités d'un shell ne sont utilisées que si elles peuvent être détectées automatiquement, simplement et à peu de frais.

    Néammoins, on trouvera une vaste gamme de routines, allant de la manipulation de tableau au quoting de chaine arbitraires, en passant par la manipulation de la logique IP v4 et la génération facile de boîtes de dialogue (avec au choix, la commande «dialog», «whiptail» ou «Xdialog»)

    Au cours du temps, mes techniques de programmations ont évolué et les logiciels tierces (tel dialog) également. Je n'ai pas tenté de réécrire les parties les plus anciennes, même pour tirer profit des améliorations des logiciels.

    Avant de commencer à utiliser cette bibliothèque, veuillez vérifier que le shell que vous pensez utiliser est suffisement évolué, que vous avez bien tous les outils nécessaires installés sur votre ordinateur. Il y en a peu, mais il sont indispensables (sed pour la majeure partie). Ne ratez donc pas les sections conditions à remplire par le shell, Testez votre shell favori, petit rappel sur les variables locales et commandes externes indispensables.

    Si vous trouvez un bug, merci de me le signaler. précisez alors le shell, sa version, l'OS, et sa version. Vous contribuerez alors à l'amélioration de cette bibliothèque.


    conditions à remplire par le shell

    Le shell doit être un shell évolué. pas un shell sh préhistorique. bash et ksh (ksh88, pas ksh93) sont suffisement évolués.

    zsh et ksh93 sont sans doute trop évolués et ne peuvent être utilisés pour des tas de raisons variées.

    tout autre shell avec syntaxe à la bourne shell et suffisement évolué devrait convenir. Notament, il doit supporter les fonctionnalités suivantes :


    Retour table des matières

    Testez votre shell favori

    N'EFFECTUEZ JAMAIS AUCUN TEST SOUS LE COMPTE ROOT (sauf si c'est nécessaire ;-)

    Avec cette petitte bibliothèque est distribué un réperoire nommé test. Pour évaluer votre shell et cette bibliothèque, il vous suffit de vous placer dans ce répertoire et de lancer la commande de test. La commande est 000_TOUS_LES_TESTS. par défaut, elle recherche tous les shells dans un certain nombre de chemin prédéfinis et les teste. Pour tester un shell particulier, il suffit de lui passer le nom du shell en argument.
    exemple:

    ./000_TOUS_LES_TESTS
    ./000_TOUS_LES_TESTS /bin/MonShellPréféré
    ...
    

    Par ailleurs, cette même commande recherche et vérifie le fonctionnement de quelques commandes externes indispensables.


    Retour table des matières


    petit rappel sur les variables locales

    Premièrement, pour des raisons historiques, il existe deux manières de déclarer des fonctions :

    1. toto() {
              code
      }
    2. function toto {
              code
      }

    La plupart des shells, considèrent que ces deux formes sont équivallentes et déclarent des objets de même nature.
    D'autres, tel ksh93, ne permettent l'utilisation de variables locales que pour les fonctions déclarées avec le second type de déclaration.
    Aussi, la majeure partie des fonctions de cette bibliothèque sont déclarées avec la seconde forme. (bien que ksh93 ne puisse pas encore être utilisé avec cette bibliothèque)

    Deuxièmement, suivant le shell utilisé, on déclare une variable locale à une fonction avec le motclef «local» ou avec le motclef «typeset».
    C'est pourquoi cette bibliothèque autodétecte le motclef à utiliser, le stocke dans la variable globale «typeset» et utilise toujours cette variable pour effectuer les déclarations, comme le montre l'exemple suivant :

    # fonction toto, déclare la variable locale x
    function toto {
    	$typeset x
    }
    

    Troisièmement, en ce qui concerne la portée,
    Si vous êtes habitués à perl, sachez que les variables locales dans les fonctions en bourn shell et dérivés, sont de la même veine ques les variables perl de type «local» . elle ne sont pas du type «my». (sauf pour ksh93)
    Maintenant, retournez à perl qui est bien supérieur au bourn shell.

    pour les autres, comprenez bien qu'une variable de type «local» dans une fonction a une portée qui s'étend à toutes les autres fonctions appelées à partir de cette fonction. (sauf pour ksh93)
    ainsi dans le code suivant:

    function f1 {
    	typeset a=$RANDOM
    
    	printf 'fonction 1, avant appel à fonction 2, valeur de a=%s\n' "$a"
    	f2
    	printf 'fonction 1, après appel a fonction 2, valeur de a=%s\n' "$a"
    }
    
    function f2 {
    	printf '\tfonction 2, changement de la valeur de a (+4)\n'
    	a=$(( a + 4 ))
    }
    
    La variable locale a définie dans la fonction f1 est connue et modifiable dans la fonction f2. Si sa valeur est modifiée par la fonction f2 alors elle sera aussi modifiée dans la fonction f1 (après l'appel à f2 bien sûr).

    Si vous exectuez ce code dans un bourn shell, vous obtiendrez un résulat semblable à celui ci :

    fonction 1, valeur de a=7103
            fonction 2, changement de la valeur de a (+4)
    fonction 1, après appel a fonction 2, valeur de a=7107
    

    Retour table des matières

    petit rappel sur les tableaux

    Les tableaux ont des indices numériques qui commencent à 0

    En bourn shell, toute variable est tableau. Si var est une variable du shell, alors, la notation var est simplement un racourci pour {var[0]}. Cela est vrai pour l'affectation et pour l'utilisation des valeurs :

    var=4
    est exactement équivallent (en apparence au moins, je ne sais pas ce que font les shells en interne) à
    var[0]=4
    et
    echo "$var"
    est équivallent à
    echo "${var[0]}"

    La notation

    ${#var[@]}
    est le nombre d'éléments contenus dans le tableau. mais attention, si on a sauté des indices lors des affectations alors cette valeur peut ne pas refléter le nombre d'éléments que l'on a mis dans le tableau ou l'indice le plus grand du tableau. par exemple
    a[10]=oui
    a[27]=bleu
    a[15]=non
    echo ${#a[@]}
    

    pourra afficher, suivant le shell,

  • soit 3, ce qui ne reflète pas l'indice le plus grand du tableau
  • soit 28, ce qui ne reflète pas le nombre d'indice du tableau
  • La notation

    "${var[@]}"
    est étendu en l'ensemble des éléments du tableau. Cette notation est la seule qui permette d'obtenir de manière certaine tous les éléments du tableau tel quel. Elle est totalement différente de ${var[@]}, ${var[*]} et "${var[*]}", (tout comme $@, "$@", $* et "$*", sont totalement différents)
    Retour table des matières

    commandes externes indispensables

    Voilà, je pense, les programmes qui peuvent être appelés par tout un tas de fonctions définies dans cette bibliothèque, leur utilisation est toujours (ou presque) minime, sans utiliser d'extensions particulières de telle ou telle version. Il vous faudra vous assurer qu'elles sont bien présentes sur votre ordinateur et qu'elles se trouvent bien dans le PATH du script. Il est en effet imposible de prédire avec certitude ou va se trouver telle ou telle commande.

    Toutes ces commandes sont recherchées et vérifiées lors du test de shell

  • sed
    commande sed quelconque
  • dd
    utilitaire classique
  • df
    utilitaire classique
  • ed
    éditeur classique
  • ls
    La commande «ls -l» doit donner le propriétaire et le groupe. La commande «ls -ld /» doit donner le propriétaire et le groupe de / mais ne doit pas lister son contenu.
  • Si un nawk existe sur votre système, alors il sera possible de construire une suite d'outil s'apparentant à des compilateurs de script. Sinon, on ne poura pas construire cette suite d'outil. Cela n'a strictement aucune importance en ce qui concerne l'utilisation de la bibliothèque (Ces outils sont drôles et pratiques mais pas indispensables).
    Aucune fonction de la bibliothèque ne dépend de l'existence d'un nawk.



    Retour table des matières

    Installation

    À première vue, il peut paraitre étrange de devoir installer une bibliothèque pour script en bourn shell. On se dit qu'il suffit de «sourcer» les divers fichiers qui la composent. Seulement, certaines fonctions font appel à des scripts d'aide et il est nécéssaire que ces scripts soient installés dans un chemin où les autres composants les retouveront. (Tous ces lieu sont définis de manière relative, donc aucun problème...). D'autre part, de nombreuses fonctions fournissent des diagnostiques en différentes langues. Pour l'instant les messages pour toutes les langues sont inclus dans chaque fichier, mais cela pourrait bien changer, surtout si le nombre de langues augmente. Enfin, l'étape d'installation enlève tous les commentaires, parfaitement inutiles, des fichiers sources.

    Une fois installée, cette bibliothèque peut être partagée sans problème par différent système via NFS ou tout autre système de fichier distant. Le préfixe d'installation n'a d'importance QUE lors de la phase d'installation, et les parties spécifiques à tous les systèmes d'exploitation sont installées.

    Installation proprement dite

    L'installation se fait en plusieurs temps.
    Premièrement, Rechercher quels shells peuvent utiliser cette bibliothèque
    Ensuite, c'est presque classique. utiliser ./Configure

  • installation simple, sur un seul poste
  • installation simple, sur un seul poste, utilisant stow
  • installation sur serveur nfs ou dans un dossier temporaire pour faire un paquet.
  • En cas de problème avec ./Configure, lisez la section Si ./Configure ne fonctionne pas.

    Vérification des shells

    premièrement, placez vous dans le répertoire test et exécutez la commande

    ./000_TOUS_LES_TESTS
    
    Cette commande recherche teste divers shell de votre PATH et de certains emplacements standards. Elle fourni un diagnostique qui doit ressembler à cela :
    failing shells : 
            /bin/ash
    succesful shells : 
            /bin/sh
            /bin/ksh
            /usr/bin/ksh
            /bin/bash
    

    Si aucun shell ne figure sous la ligne successful shells, c'est mal parti. Si vous soupçonner un shell d'être convenable, et que ce shell est installé dans un chemin ne faisant pas partie de votre PATH et n'étant pas non plus un emplacement «standard», vous pouvez tenter la commande suivante :

    ./000_TOUS_LES_TESTS /un/chemin/caché/unsh
    

    Si la réponse est du style

    /un/chemin/caché/unsh succeded test
    
    alors il est possible d'instaler cette bibliothèque et il sera même possible de l'utiliser ensuite.
    Si par contre la réponse est du genre
    /un/chemin/caché/unsh failed test
    

    alors, inutile de continuer. ça ne marchera pas avec les shells instalés sur votre système.

    installation simple, sur un seul poste

    La méthode de configuration la plus simple est d'exécuter ./Configure sans aucune option. Cela prépare pour une installation dans /usr. Les options possibles sont :

  • -p prefix
    prefix est le chemin absolu désignant le répertoire de base de l'installation. (valeur par défaut : /usr)
  • -b rep-bin
    rep-bin est le chemin relatif au répertoire de base où installer les exécutables. (valeur par défaut : bin)
  • -l rep-lib
    rep-lib est le chemin relatif au répertoire de base où installer les fichiers de bibliothèque. (valeur par défaut : lib)
  • -m rep-man
    rep-man est le chemin relatif au répertoire de base où installer les page de manuel. Dans le répertoire indiqué, seront créés les répertoires des différentes section de manuel. (valeur par défaut : share/man)
  • -d rep-doc
    rep-doc est le chemin relatif au répertoire de base où installer les autres documentations (comme ce fichier html par exemple)
  • -D répertoire-des-demos
    répertoire où installer les démos.
  • -S /un/shell
    chemin vers un shell par défaut qui sera utilisé par les compilateurs et lieur de script en l'abscence de toute autre précision (Si vous ne comprenez pas, ça n'a aucune importance) (valeur par défaut : variable selon système)
  • -n /un/newawk
    chemin complet vers une commande nawk. Si aucun nawk n'existe, on peut ne pas utiliser l'option -n ou utiliser -n /bin/false. (valeur par défaut : variable selon système)
  • -s stowdir
    installer sous stowdir/libsh-<VERSION>
    stowdir doit être un chemin absolu
    stowdir doit être un sous répertoire direct de prefix
    (Si vous ne connaissez pas stow, n'utilisez pas -s)
  • Une fois configuré selon vos désir, utiliser la commande
    make
    pour compiler les outils et la bibliothèque, puis les commandes
    make install
    et
    make install_man

    pour installer les divers composants.

    installation simple, sur un seul poste, utilisant stow

    Faites comme pour l'installation simple ci-dessus, mais utilisez en plus l'option
    -s rep-stow
    de ./Configure où rep-stow désigne votre répertoire stow. Le nom du répertoire de paquet stow sera choisi et indiqué par le script ./Configure. Il sera nécessairement dans le répertoire stow.

    installation sur serveur nfs ou dans un dossier temporaire pour faire un paquet

    Faites comme pour l'installation simple ci-dessus, mais au moment d'installer, utiliser les commandes :
    make install DESTDIR=/repertoire/ou/commencer
    make install_man DESTDIR=/repertoire/ou/commencer

    où la /repertoire/ou/commencer représente le répertoire de base pour l'export NFS ou bien le répertoire que vous voulez utiliser pour construire un paquet.
    exemple :

    $ ./Configure -p /usr/local
    $ make
    $ make install DESTDIR=/tmp/base
    $ make install_man DESTDIR=/tmp/base
    
    Cela installe tout dans
    /tmp/base/usr/local/bin
    /tmp/base/usr/local/lib
    /tmp/base/usr/local/share/man
    /tmp/base/usr/local/doc/html/libsh-1.0-5
    

    Il est alors facile soit d'exporter cette arborescence, soit de faire:
    cd /tmp/base && tar cf /tmp/libsh.tar .
    ou
    cd /tmp/base && make_paquet ......

    Si ./Configure ne fonctionne pas

    Si ./Configure ne fonctionne pas, reportez vous à la section Vérification des shells et notez les shells convenables que 000_TOUS_LES_TESTS a trouvé. choisissez en un puis essayez la commande suivante :
    env RERUNNING=1 SH=/un/shell/convenable ./Configure ...
    ou la chaine /un/shell/convenable est le shell que vous avez choisi et ... représente toute option que vous souhaitez utiliser.

    Si cela ne fonctionne pas, essayez de vous faire aider par quelqu'un

    Si cela ne fonctionne pas, essayez de vous faire aider par quelqu'un d'autre.

    Si cela ne fonctionne pas, sachez que j'en suis désolé, mais qu'il n'y a malheureusement plus rien à faire. Cet ensemble ne fonctionnera pas sur votre système...


    Retour table des matières

    utilisation

    « sourcer » ou « compiler »

    On peut utiliser cette bibliothèque de plusieurs manières différentes. L'une d'entre elles, consiste à ne pas installer quoi que ce soit et à « piocher » à coup de copier coller dans les fichiers de la bibliothèque ce dont on a besoin pour son script. Mais c'est justement cela qui fit naitre l'idée de cette bibliothèque...

    Une autre technique, déja plus intéressante est d'utiliser la bibliothèque installée en « sourçant » les fichier au début du script, comme montré dans l'exemple suivant :

    LIBSHDIR=/usr/lib
    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libkwubst.scl
    . $LIBSHDIR/libmaniptab.scl
    . $LIBSHDIR/liboption.scl
    unset LIBSHDIR
    
    #
    # Le programme commence ici
    #
    ....
    
    C'est cette méthode que j'ai retenu pour tous les exemples de ce document. C'est simple et efficace.

    On peut aussi utiliser un compilateur de script ( sc(1) ) qui fait appel à un préprocesseur ( spp(1) ) et à un relieur ( ld.sh(1) ). Une bonne part de moquerie et d'ironie a guidé le choix du nom de ces outils, mais, en gros leur utilisation est similaire à celle d'un compilateur C, même s'ils n'accomplissent qu'un bien moindre travail.
    Toujours est il, qu'on peut utiliser des constructions de la forme :

    sc -o monprog -L/usr/lib -llocal -lkwubst -lmaniptab -loption util.sh principal.sh
    

    Ces trois outils ont leur documentation sous la forme d'une page de manuel.


    Retour table des matières

    contraintes techniques

  • Les différentes parties de la bibliothèque utilisent des variables globales pour leur usage interne. Ces variables commencent toutes par 2 lettres majuscules et se terminent par des lettres minuscules.
    Conclusion. Ne pas utiliser de variables de cette forme dans vos script.
    Voila un exemple de ce qu'il ne faut pas faire
    MAvar=43
  • Utiliser un shell évolué :
    bash, ksh, d'autres ????
  • Toutes les routines graphiques (dialog) utilisent le file descriptor 3 qui doit être une copie de 1. La bibliothèque libdialog.scl execute la commande suivante lors de son chargement :
    exec 3>&1
    Pour les version de libsh, inférieures à 1.3.9.0, cette initia lisation devait être faite par le programme avant d'utiliser une boite de dialogue.
  • Les descripteurs de fichiers 3 et 4 sont utilisés par cette bibliothèque.
    Conclusion : Utilisez les file descriptors au dessus de 4 dans votre script.
  • Cette bibliothèque compte sur un certain nombre de variables globales dont les noms ne peuvent être utilisés à d'autres fins :
  • typeset :
    le shell supporte "typeset" ou "local" pour déclarer les variables locales des fonctions.
    sourcer liblocal.scl
    On déclare alors les variables locales aux fonctions en utilisant cette variable :
    $typeset mavar1 varlocale2=toto varloc3=$1
    Pour des aisons de portabilité de vos scripts, et assez étrangement d'ailleurs, il faut utiliser systématiquement des guillemets autour des valeurs lors des déclarations de variables locales. L'exemple ci dessous est préférable à celui ci-dessus.
    $typeset mavar1 varlocale2=toto varloc3="$1"
  • whiptail :
    programme du type "dialog". peut être "dialog" ou "whiptail" ou "Xdialog"
    sourcer libdialog.scl exécuter la fonction whichdialog [exit errcode]
    On utilise alors son contenu pour appeler le programme de boite de dialogue :
    $whiptail --msgbox "Salut (merveilleux) monde" 0 0 2
  • LIBSHDIR :
    Certains composants peuvent avoir besoin de savoir où ils sont installés. La variable d'environnement LIBSHDIR doit avoir comme valeur le répertoire où est installée la bibliothèque.
    Les personnes utilisant le compilateur de script sc et/ou le relieur de script ld.sh n'ont pas à se soucier de fixer cette variable, le relieur s'en charge. Ces outils sont documentés au moyen d'une page de manuel.
  • La variable d'environnement CMLANG peut être définie. Elle conditionne la langue utilisée pour les messages. Le langage choisi n'est pas forcement disponible. Les fonctions ont toujours une solution de repli (qui n'est pas forcement l'anglais) Les valeurs possibles pour l'instant sont :
  • fr
  • en
  • Pour eviter les boucles, et les sources multiples de composants de cette bibliothèque, les composants ayant besoin d'autres composants, ne sourcent pas automatiquement ces autres composants. Par exemple, pour pouvoir utiliser «eset», dans «libeset.scl», il faut aussi sourcer «libkwubst.scl». C'est de votre responsabilité ; libeset.scl ne le fera pas pour vous. Voir le chapitre modules et dependances pour avoir une liste complète.

  • Retour table des matières

    Utilisation des boites de dialogue

    Sans options particulières, dialog, Xdialog ou whiptail affichent leur résultat sur l'erreur standard, ce qui exige souvent du code ressemblant à cela :

    dialog --menu blablabla 0 0 0 a choix_a b choix_b 2>/tmp/fich_reponse
    reponse=$(</tmp/fich_reponse)
    

    Cette technique est assez lourde et de surcroît ne fonctionne pas si on a un disque en lecture seule. (Ceux qui ont essayé de faire des boîtes de dialogue très tôt dans une phase de boot savent de quoi je parle)...

    Il existe bien sur des options à passer aux commandes pour faire afficher les résultats sur la sortie standard, mais ces options diffèrent entre dialog et whiptail par exemple.

    Il existe une méthode plus générale, qui permet de gagner à tous les coups et sans voir à utiliser d'options particulières à tel ou tel programme. il suffit de dupliquer le descripteur de sortie standard une fois au début du script et de rediriger convenablement les sorties des programmes par la suite, comme montré dans l'exemple ci-dessous :

    exec 3>&1
    reponse=$($whiptail --menu blabla 0 0 0 a choix_a b choix_b 2>&1 >&3)
    

    De cette manière, on capture l'erreur standard qui est redirigée ver la sortie standard. La sortie standard, pour ne pas se mélanger avec le résultat qu'on veut capturer est dirigée vers le descripteur de fichier 3 qui est une copie de la sortie standard... (la boucle est bouclée).

    En fait, cette commande

    exec 3>&1
    
    est exécutée automatiquement lors du chargement de la bibliothèque libdialog.scl (depuis la version 1.3.9.0)

    Pour des raisons expliquées dans la Note 3 du chapitre des boites de dialogue, il est encore plus judicieux d'utiliser la construction suivante :

    eval 'reponse=$('"$whiptail"' --menu blabla 0 0 0 a choix_a b choix_b 2>&1 >&3)'
    

    Retour table des matières

    exemples d'utilisations

    De nombreux exemples détaillés émaillent cette documentation, aussi ce qui suit n'est qu'un avant goût, pas vraiment passionnant. Il faut noter qu'on ne peut pas utiliser

    set -e
    dans les script utilisant des boîtes de dialogues. En effet le code d'erreur renvoyé par whiptail(1) ou dialog(1) peut simplement indiquer que l'opérateur a annulé (touche escape ou bouton annuler) l'action en cours.

    Voila ce que devrait faire au minimum un script qui veut utiliser tout ou partie de cette lib :

    #!/bin/ksh
    LIBSHDIR=/la/ou/vous/l_avez/installe
    . $LIBSHDIR/liblocal.scl
    unset LIBSHDIR
    
    Pour utiliser les routines graphiques il faudrait faire au minimum ça :
    #!/bin/ksh
    set +e
    LIBSHDIR=/la/ou/vous/l_avez/installe
    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libdialog.scl
    whichdialog exit 1
    unset LIBSHDIR
    
    Pour utiliser vraiment le gourbi il faudrait faire ça :
    #!/bin/ksh
    set +e
    export CMLANG
    CMLANG=fr
    LIBSHDIR=/la/ou/vous/l_avez/installe
    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libbrowse.scl
    . $LIBSHDIR/libkwubst.scl
    . $LIBSHDIR/libeset.scl
    . $LIBSHDIR/libdialog.scl
    . $LIBSHDIR/libipv4.scl
    . $LIBSHDIR/libnetchoice.scl
    . $LIBSHDIR/libmaniptab.scl
    
    whichdialog exit 1
    unset LIBSHDIR
    


    Retour table des matières

    modules et dépendances

    Liste des modules et de leurs dépendances
    FichierDépendancesutilisevariables
    en sortie
    liblocal.scl  typeset
    libkwubst.sclliblocal.scltypeset 
    libdialog.sclliblocal.sclLIBSHDIR
    dialog
    whiptail
    DIALOG
    WHIPTAIL
    CMLANG
    exec 3>&1
    typeset
    whiptail
    libstddial.sclliblocal.scl
    libkwubst.scl
    libdialog.scl
    libmaniptab.scl
    typeset
    exec 3>&1
    whiptail
     
    libeset.sclliblocal.scl
    libkwubst.scl
    libdialog.scl
    typeset
    exec 3>&1
    whiptail
     
    libbrowse.sclliblocal.scl
    libdialog.scl
    CMLANG
    typeset
    exec 3>&1
    whiptail
     
    libipv4.sclliblocal.scltypeset 
    libnetchoice.sclliblocal.scl
    libipv4.scl
    libkwubst.scl
    libdialog.scl
    libeset.scl
    CMLANG
    typeset
    exec 3>&1
    whiptail
     
    libethernet.sclliblocal.scl
    libkwubst.scl
    typeset
    LIBSHDIR
    NAWK
     
    libdiethernet.sclliblocal.scl
    libkwubst.scl
    libethernet.scl
    typeset
    LIBSHDIR
    CMLANG
    exec 3>&1
    whiptail
    NAWK
     
    libmaniptab.sclliblocal.scl
    libkwubst.scl
    typesetTAindice
    liboption.sclliblocal.scl
    libkwubst.scl
    libmaniptab.scl
    typesetOCarg
    OCargsused
    OCmsg_err
    libexoption.sclliblocal.scl
    libkwubst.scl
    libmaniptab.scl
    liboption.scl
    typesetOCarg
    OCargsused
    OCmsg_err
    libsystem.sclliblocal.scltypeset 
    libquota.sclliblocal.scl
    libkwubst.scl
    libsystem.scl
    LIBSHDIR
    typeset
     
    Bibliothèques obsolètes
    libkwote.sclliblocal.scltypesetKWote
    libgsubst.sclliblocal.scltypeset 
    Comment lire ce tableau ?

    Dans la colonne de gauche, se trouve le noms des différents modules. Dans la colonne suivante se trouve le nom des modules qui doivent être chargés avant de pouvoir utiliser le module de la première colonne. Dans la colonne suivante, les variables ou autre choses à faire AVANT de sourcer le module, et dans la dernière colonne les variables ou autres choses qui sont fixées, utilisée par les différentes parties du module.


    Retour table des matières

    Fichier par fichier

    Utilité de chaque fichier.


    Retour table des matières

    liblocal.scl

    teste comment déclarer les variables locales au fonctions. utilisation de pointeurs (ou variables variables).

    utilisation et initialisation :

    . $LIBSHDIR/liblocal.scl
    

    utilise :

    définit :

  • globale:
  • typeset
  • NL contient un newline
  • DIFS l'IFS par defaut : espace tab newline
  • fonctions
  • setv
  • setp
  • printp
  • printpn
  • tmpfilename
  • getp (obsolète)
  • newifs
  • oldif
  • description

    Pour déclarer des variable locales dans une fonction, certains shells acceptent «typeset», d'autres «local», et d'autres les deux. Après avoir sourcé ce script, la variable typeset est initialisée de telle sorte à pouvoir déclarer des variables locales facilement dans tous les shells. On utilise alors :
    function toto {
    	$typeset i j k
    }
    

    ATTENTION
    Pour des raisons de portabilité entre les différentes implémentations de bourn shell, il est impératif d'utiliser des " lorsqu'on fait une affectation en même temps que la déclaration.
    L'exemple suivant est portable :

    function toto {
    	$typeset val="$1" i j nom="$2"
    
    
    	i=$val
    	: ....
    }
    
    Celui la ne l'est pas :
    function toto {
    	$typeset val=$1 i j nom=$2
    
    
    	i=$val
    	: ....
    }
    

    Ce fichier est la base de tout les autres fichiers de cette bibliothèque. À l'origine, il ne servait qu'à trouver la manière de déclarer les variables locales.

    J'ai ajouté trois fonctions très pratiques qui n'ont pas trouvé leur place ailleurs. Ces fonctions sont setp et setv, qui permettent des affectations à des variable dont le nom est contenu dans une autre variable, ainsi que getp, qui retourne la valeur d'une variable dont le nom est passé en paramètre.(bash permet d'utiliser la notation ${!nomvar} pour cela, mais pas ksh)

    setv nomvar valeur

    Affecte à la variable dont le nom est passé en premier paramètre, le second paramètre.

    effectue
    nomvar=valeur

    exemple :

    a=1
    b=2
    c=3
    printf "Donnez une valeur quelconque "
    read valeur
    printf  "donnez un nom de variable (a, b, ou c) "
    read variable
    setv $variable "$valeur"
    printf "La variable $variable a été changée\n"
    
    autre exemple dans le cas ou une fonction recoit un paramètre contenant le nom d'une variable :
    function calcul {
    	$typeset nomvar="$1" resultat
    	resultat="$(un_calcul_complique "$2")"
    	setv $nomvar "$resulat"
    }
    
    

    setp nomvar1 nomvar2

    Affecte à la variable dont le nom est passé en premier paramètre, la valeur de la variable dont le nom est passé en second paramètre.

    effectue
    nomvar1="$nomvar2"

    exemple :

    a=1
    b=2
    c=3
    printf  "donnez le nom de variable (a, b, ou c) "
    read reponse
    setp resultat $reponse
    echo $resultat
    
    autre exemple dans le cas ou une fonction recoit un paramètre contenant le nom d'une variable :
    
    #
    # doublevar varname
    # affiche deuxfois le contenu de la variable dont le NOM est passé en paramètre
    function doublevar {
    	$typeset nomvar
    	setp nomvar $1
    	echo "$nomvar$nomvar"
    }
    k=abcd
    j=bkbk
    doublevar k
    doublevar j
    

    printp nomvar et printpn nomvar

    Affiche le contenu de la variable dont le nom est passé en paramètre.

    printp effectue
    printf %s "$nomvar"

    alors que printpn ajoute un retour chariot et effectue
    printf '%s\n' "$nomvar"

    exemples :
    1

    for i in PATH HOME PWD ; do 
    	printf '%5s ' $i 
    	printpn $i
    done
    
     PATH /home/moi/bin:/usr/bin:/bin:/usr/bin/X11:/sbin:/usr/sbin:/usr/games
     HOME /home/moi
      PWD /tmp
    
    

    2
    trim() {
    	# enleve les espaces de debut et de fin de chaine.
    	setv "$1" "$( printpn "$1" | sed -e 's/^ *//' -e 's/ *$//' )"
    }
    
    
    a='      aaaaaaaa  bbbbbbbbbbbb             '
    trim a
    printf ' -->%s<--\n' "$a"
    
     -->aaaaaaaa  bbbbbbbbbbbb<--
    

    Code de retour

    NA

    Effets secondaires

    La valeur de la variable est affichee sur la sortie standard.

    Avec printpn, la valeur de la variable est suivie d'un saut de ligne.

    notes

    Si vous pensez utiliser printp pour récupérer la valeur d'une variable et la stocker dans une autre, comme dans l'exemple suivant :

    a=1 b=2 c=3
    printf "Donnez le nom de variable (a, b ou c) "
    read nom_de_var
    z="$(printp $nom_de_var)"
    printf 'valeur de $nom_de_var == %s\n' "$z"
    #
    # pire encore :
    #
    echo "la valeur de $nom_de_var est $(printp $nom_de_var)"
    

    Sachez qu'il est préférable d'utiliser setp car ça évite un fork(2)/clone(2) attendu qu'il n'y a pas de $( ) dans ce cas :

    a=1 b=2 c=3
    printf "Donnez le nom de variable (a, b ou c) "
    read nom_de_var
    setp z $nom_de_var
    printf 'valeur de $nom_de_var == %s\n' "$z"
    

    La seule utilisation raisonnable est l'affichage d'une variable. Si on ré-écrit l'exemple précédent, on peut se passer de la variable z

    a=1 b=2 c=3
    printf  "donnez le nom de variable (a, b, ou c) "
    read nom_de_var
    printf "la valeur de $nom_de_var est "
    printp $nom_de_var
    

    tmpfilename

    Crée un nom de fichier temporaire. Le nom se trouve dans un répertoire protégé de telle sorte que seul l'utilistateur exécutant le programme puisse y accéder.

    Cette fonction DOIT doit être appelée UNE fois sans aucun argument pour s'initialiser. Par la suite, il faut l'appeler avec une nom de variable en argment. la variable reçoit la valuer du nom de fichier temporaire.

    Le nom du répertoire servant de base au fichiers temporaires est calculé en fonction du nom du script, du PID du script d'une valeur aléatoire et de la variable d'environnement TEMP selon cette formule :
    LOtmpdir="${TEMP:-/tmp}/nom_du_script.$$.$RANDOM"

    exemples :

    
    # initialisation
    tmpfilename
    trap 'rm -rf "$LOtmpdir"' EXIT
    ...
    ..
    tmpfilename fictemp
    ls -l >"$fictemp
    ...
    rm -f "$fictemp"
    

    Code de retour

    NA

    Effets secondaires

    La variable dont le nom est donné reçoit le nom du fichgier temporaire.

    getp nomvar

    Cette fonction est obsolète. Elle est toujours dans la bibliothèque, pour raison de compatibilité avec de vieux scripts liés dynamiquement.

    newifs 'un car'; oldifs

    quand on change l'IFS pour découper une chaine ou une entree, on est toujours de mémoriser l'IFS courant puis de le restaurer. Cette paire de fonctions permet de le faire simplement.

    les chaines suivantes sont reconnues et sont donc spéciales

    NL
    un passage à la ligne
    DEF
    l'IFS par défaut : un espace, un tab, un passage à la ligne
    TAB
    un tab
    SP
    un espace
    PIPE
    un pipe (|)

    exemple :

    a='un:deux:trois|trois   deux|trois   trois:quatre'
    newifs :
    n=1
    for i in $a
    do
    	newifs PIPE
    	for j in $i
    	do
    		echo ligne $n : $j
    	done
    	oldifs
    	n=$(( n + 1 ))
    done
    oldifs
    
    produit l'affichage suivant
    ligne 1 : un
    ligne 2 : deux
    ligne 3 : trois
    ligne 3 : trois   deux
    ligne 3 : trois   trois
    ligne 4 : quatre
    

    Retour table des matières

    libkwubst.scl

    Cette bibliothèque est la réunion de deux anciennes bibliothèques. Elle permet donc :

  • D'effectuer des remplacement globaux dans des chaines de caractères, à la sed -e s/toto/tata/g sans appel à des programmes externes
  • De protéger (quoter) des chaines de manière à les rendre évaluables sans craintes et sans interprétation par les shells.
  • Les bibliothèques kwote et gsubst partageaient (et dupliquaient) tellement de code, que j'ai décidé de les regrouper en une seule. Surtout depuis que la fonction vargsubst permet de réécrire en une ligne ou deux la plupart des fonctions de ces deux bibliothèques.

    utilisation et initialisation :

    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libkwubst.scl
    

    utilise :

    globale: typeset

    définit :

  • globale: Aucune variable globale définie
  • fonctions:
  • gsubst val recherche nouveau
  • vargsubst variable recherche nouveau
  • backslashslash val
  • varbackslashslash variable
  • kwote val
  • kwotenokwote val
  • varkwote var
  • varkwotenokwote var
  • description

    Avec la commande interne eval, il faut prendre certaines précautions, sinon on obtient pas ce qu'on croit. libkwubst.scl définit une fonction appelée kwote dont le but est justement de prendre ces précautions. elle retourne une chaine protégée au moyen d'apostrophes ou d'antislash. Des variantes de cette fonction sont définies dans ce fichier.

    Le quoting étant réalisé au moyen de substitution (la plupart du temps), on trouve naturellement dans cette bibliothèque des fonctions de remplacement de chaine à l'intérieur de chaine.

    Toutes les fonction dont le nom commence par le préfixe var prennent en paramètre un nom de variable et modifient le contenu de la variable. Ces fonctions ne nécessitent normalement pas de clone/fork et sont donc particulièrement intéressantes en terme de performances.

    gsubst val recherche nouveau

    gsubst affiche la chaine val apres avoir remplacé toutes les occurences de la chaine recherche par nouveau
    Aucun retour chariot supplémentaire n'est affiché.
    On peut sans probleme utiliser recherche dans nouveau (voir exemple).
    gsubst fonctionne avec les modeles de chaine interne au shell. Il faut donc faire des essais avant d'utiliser les caracteres *, ?, [, {, | et (. leur signification dans les substitutions variant grandement en fonction des shells et des options des shells. l'utilisation de ces caractères n'est pas portable.
    Enfin gsubst n'est certainement pas performantes pour des textes longs. Son utilisation devrait se cantonner à des remplacements sur des chaines de quelques dizaines de caractères au maximum.

    exemples :

    chaine="abcd efgh bcd ijkl bcd"
    a="$(gsubst  "$chaine" bcd coucou)"
    echo "$a"
    	acoucou efgh coucou ijkl coucou
    a="$(gsubst "$a" coucou 'coucou les amis')"
    echo $a
    	acoucou les amis efgh coucou les amis ijkl coucou les amis
    

    Code de retour

    NA

    Effets secondaires

    La chaine modifiée est affichee sur la sortie standard.

    vargsubst variable recherche nouveau

    vargsubst fonctionne comme gsubst, avec les même limitations, mais travaille sur une variable (et sa valeur) et non sur une chaine.

    En fait une bonne partie des utilisations de gsubst ressemble à ça :

    a="$(resultat d une commande)"
    a="$(gsubst "$a" toto tata)"
    

    Dans ces conditions, il est plus efficace d'utiliser vargsubst car cela evite un fork/clone. Le code précédent est plus efficace s'il est écrit comme ça :

    a="$(resultat d une commande)"
    vargsubst a toto tata
    

    Exemple :

    v="une chaine de caractere"
    vargsubst v a --aHAHAa--
    echo $v
    
    une ch--aHAHAa--ine de c--aHAHAa--r--aHAHAa--ctere
    

    Code de retour

    NA

    Effets secondaires

    La variable est modifiée

    backslashslash val

    appelle

    gsubst val / '\/'
    
    pour remplacer tous les / en \/
    Aucun retour chariot supplémentaire n'est affiché.

    exemples :

    prefix="/usr/local"
    prefix="$(backslashslash "$prefix")"
    sed -e "s/PREFIX/$prefix/" fichier.conf.in >fichier.conf
    	effectue :
    	sed -e 's/PREFIX/\/usr\/local/' fichier.conf.in >fichier.conf
    

    Code de retour

    NA

    Effets secondaires

    La chaine modifiée est affichee sur la sortie standard.

    varbackslashslash variable

    Comme backslashslash mais avec une variable. Voir gsubst et vargsubst.

    Pour éviter un clone/fork, et rendre le script plus efficace, on peut réécrire l'exemple précédent comme ça :

    prefix="/usr/local"
    varbackslashslash prefix
    sed -e "s/PREFIX/$prefix/" fichier.conf.in >fichier.conf
    	effectue :
    	sed -e 's/PREFIX/\/usr\/local/' fichier.conf.in >fichier.conf
    

    Code de retour

    NA

    Effets secondaires

    La variable est modifiée.

    kwote val

    rend la valeur val sure pour une évaluation.

    La chaine produite est une chaine completement délimitée, qui doit être utilisée seule (On ne peut pas l'utiliser à l'intérieur d'une autre chaine). Si on désire utiliser une chaine protégée à l'intérieur d'une autre chaine, il faut utiliser kwotenokwote.

    La chaine affichée par kwote n'est jamais terminée par un retour chariot.

    Si kwote est appelée sans argument, alors elle retourne immédiatement sans rien afficher.

    Dans tous les autres cas, kwote affiche l'argument passé en paramètre entre '', même si l'argument est null.

    Voilà un exemple simple d'utilisation de kwote (voir aussi le deuxième exemple d'utilisation plus bas.)

    read a
    # Voulant tester un peu, j'ai répondu : toto ; `ls` ;
    commande="
    	echo $(kwote "$a")
    	b=$(kwote "$a")
    	toto -x -y -v $(kwote "$a")
    "
    eval "$commande"
    # ou meme, création d'un script
    echo "#! /bin/sh
    $commande" > monscript
    
    chmod 755 monscript
    ./monscript
    

    La technique suivante est utilisée.

    Ainsi, la chaine toto est transformée en 'toto'
    La chaine toto l'est pa bo est transformée en 'toto l'\''est pas bo'

    Il est possible dans certains cas que les apostrophes des bords soient génantes (pour construire une chaine quotée par morceaux par exemple), c'est pourquoi la fonction kwotenokwote existe.

    NB


    Les versions de shell supportant le format %q pour printf, utilisent printf %q pour la fonction kwote. Dans ce cas, la valeur produite par kwote n'est pas entourée d'apostrophe. Mais c'est toujours une chaine complètement délimitée et destinée à être employée seule.
    La seul exception à l'utilisation de %q est pour le cas d'un argument nul (essayez de faire l'équivallent de '' avec des \). Dans ce cas, '' est affiché.

    exemple:

    for i in ${1+"$@"}
    do
    	args="$args -e $(kwote "$i")"
    done
    eval "grep $args /un/fichier"
    

    kwotenokwote val

    rend la valeur val sure pour une évaluation.
    C'est une version de kwote qui est faite pour être utilisée à l'intérieur d'une chaine protégée par des apostrophes (').
    On l'utilise par conséquent souvent pour préparer des commandes qui sont évaluées ultérieurement.

    La chaine toto est transformée en toto
    La chaine toto l'est pas bo est transformée en toto l'\''est pas bo

    exemple :

    b='Test me `ls` ; : " '\'
    a="echo 'abcd efgh $(kwotenokwote "$b") ahahahaha'"
    eval "$a"
    

    varkwote var

    rend la valeur de la variable var sure pour une évaluation.

    Comme kwote mais l'argument est un nom de variable. Le contenu de la variable est modifié par cette fonction.

    varkwote a
    

    est plus efficace que :

    a="$(kwote "$a")"
    

    car cela ne nécessite aucun fork/clone de la part du shell.

    exemple :

    read a
    # Voulant tester un peu, j'ai répondu : toto ; `ls` ;
    varkwote a
    commande="
    	echo $a
    	b=$a
    	toto -x -y -v $a
    "
    eval "$commande"
    # ou meme, création d'un script
    echo "#! /bin/sh
    $commande" > monscript
    
    chmod 755 monscript
    ./monscript
    

    varkwotenokwote var

    rend la valeur de la variable var sure pour une évaluation.

    Comme kwotenokwote mais l'argument est un nom de variable. Le contenu de la variable est modifié par cette fonction.

    varkwotenokwote a
    

    est plus efficace que :

    a="$(kwotenokwote "$a")"
    

    car cela ne nécessite aucun fork/clone de la part du shell.

    exemple :

    b='Test me `ls` ; : " '\'
    varkwotenokwote b
    a="echo 'abcd efgh $b ahahahaha'"
    eval "$a"
    

    Retour table des matières

    libkwote.scl

    Cette bibliothèque et son contenu existent uniquement à des fins de compatibilité. Elle est obsolète. Il faut utiliser libkwubst à la place.


    Retour table des matières

    libgsubst.scl

    Cette bibliothèque et son contenu existent uniquement à des fins de compatibilité. Elle est obsolète. Il faut utiliser libkwubst à la place.


    Retour table des matières

    libm.scl

    m est l'abréviation de more, misc, machin.

    On trouve donc dans cette bibliothèque des tas de trucs qui n'ont pas leur place ailleurs.

    utilisation et initialisation :

    . $LIBSHDIR/libm.scl
    

    utilise :

    globale:

    définit :

  • globale:
  • MIprog : nom du programme
  • MIscriptname : nom complet du script, avec le chemin.
  • MIfatal_code : valeur du exit code pour les fonction fatal et fatalf.
    valeur par defaut : 1
  • fonctions:
  • __DATA__
  • data
  • warn texte [texte...]
  • warnf format texte [texte...]
  • fatal texte [texte...]
  • fatalf format texte [texte...]
  • description

    On trouve deux familles de fonctions dans cette bibliothèque.

  • la gestion des données inscrites dans le script
  • la gestion des messages d'erreurs et de l'arret du script.
  • L'idée est de pouvoir écrire des trucs à la perl dans le genre try-abort :

    mkdir "$rep" || fatal "Impossible de créer le répertoire '$rep'"
    
    ou de mettre des données dans le script et d'avoir un moyen de le récupérer lors de l'exécution, comme en perl encore une fois...
    #! /bin/sh
    
    data | sed -e s/couicouic/BLABLA/
    
    __DATA__
    a
    b
    c
    couicouic
    tralala
    
    Voila, si tout ou presque est dit dans les exemples, regarder la doc complète ne peut pas nuire.

    __DATA__ et data

    La fonction __DATA__ a un double but. lorqu'elle est éxécutée, elle termine le programme courant avec la commande exit. Par conséquent, rien de ce qui se trouve après elle ne sera éxécuté, et cela peut donc être n'importe quel type de données, (même des données binaires ???? à vérifier...)
    D'autre part, elle sert de marqueur pour la fonction data, qui, elle utilise sed pour éliminer du script toutes les lignes jusqu'à la ligne __DATA__, ce qui fait que les données suivant la ligne __DATA__ sont disponibles.

    Attention, rien de ce qui se trouve sous une ligne __DATA__ ne peut etre exécuté car __DATA__ est une fonction qui effectue un exit.

    exemples :

    #! /bin/sh
    
    for i in $(data)
    do
    	mkdir $i
    done
    __DATA__
    rep_1
    dir_b
    blabla
    

    Code de retour

    NA

    Effets secondaires

    Les données situées sous la ligne __DATA__ sont affichées.

    warn[f] texte [texte...] et fatal[f] texte [texte...]

    Affiche sur l'erreur standard le nom du script, puis ':' puis les textes, chacun sur une ligne.

    Le nom du script est en fait la valeur de la variable MIprog. la valeur par défaut est automatiquement calculée par la bibliothèque et est le nom du script.

    Si cette variable a une valeur nulle ou est oubliée (unset) alors, les ':' ne sont pas affichés ; seuls les textes le sont.

    La différence entre fatal et warn est que fatal, en plus effectue un exit $MIfatal_code(initialisé à 1 lors du chargement de la bibliothèque).

    Les versions warnf et fatalf, attendent un format pour printf en premier argument. N'oubliez pas le \n final sinon il n'y aura pas de passage à la ligne

    exemples :

    #! /bin/sh
    # programme a faire bip !!!
    	test -r ~/.biprc || {
    		warn "Aucun fichier d'initialisation" \
    			"Création d'un fichier standard"
    		touch ~/.biprc
    	}
    	echo 
    
    
    	mkdir /tmp/un-rep || fatal 'Impossible de créer un répertoire'
    #
    

    Code de retour

    NA

    Effets secondaires

    les textes sont affichés sur l'erreur standard.

    avec fatal et fatalf, le script se termine.


    o Retour table des matières

    libdialog.scl

    Trouve une commande dialog, et fourni des boites standard. (voir les remarques sur dialog).

    utilisation et initialisation

    set +e
    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libdialog.scl
    whichdialog [opt]
    

    La commande

    exec 3>&1
    
    est exécutéé quand le fichier libdialog.scl est chargé.

    voir aussi Utilisation des boites de dialogue pour une explication sur la nécessité de dupliquer la sortie standard dans le descripteur de fichier 3.

    utilise

  • globale :
    typeset
    LIBSHDIR (optionnel, pour whichdialog seulement)
  • descripteur de fichier :
    3
  • définit

  • globale :
    whiptail
  • fonctions :
  • whichdialog
  • DIerrbox
  • DImsgbox
  • DIouinon
  • DItagmenu
  • DIcheckbox3
  • description

    Il existe au moins deux commandes qui sont identiques au niveau syntaxique et qui ont le meme but. Construire des boites de dialogue dans des terminaux texte. Ces deux programmes sont dialog et whiptail. En fait, il existe une troisième commande nommée Xdialog, qui est une version X11 (gtk) des deux précédentes.
    Il existe même une commande de type kde, mais à ma connaissance, sa syntaxe est très différente des autres, ce qui la rend incompatible. :-(

    La première chose à faire est donc de rechercher une commande disponible (whichdialog fait ça très bien), ensuite on peut utiliser des fonctions de plus haut niveau qui se débrouilleront très bien quelque soit la commande trouvée.

    whichdialog

  • whichdialog
  • whichdialog [options obsoletes]
  • whichdialog recherche un programme compatible avec dialog. et donne une préférence a Xdialog (à condition qu'on puise exécuter Xdialog --version (variable DISPLAY non nulle et Xdialog fonctionne)), à dialog sinon. Le PATH est fouillé à la recherche d'une commande satisfaisante.

    Le résultat est enregistré dans l& variable globale whiptail.

    Depuis la version 1.4.5.0, le chemin complet de la commande trouvée est enregistré dans la variable.

    Les commandes essayées à tour de rôle sont :

    • Xdialog
    • dialog
    • whiptail
    • dialok
    • DImdialog

    Il est possible d'influencer la recherche en fixant des variables dont le contenu doit être une commande «dialog». Les 5 variables sont testées. La dernière testée qui est valide sera celle utilisée.
    Les variables testées sont, dans cet ordre :

    WHIPTAIL	(variable d'environnement)
    DIALOG		(variable d'environnement)
    XDIALOG		(variable d'environnement)
    whiptail
    dialog
    

    Si la consultation de ces variables n'a rien donné de satisfaisant (si, par exemple aucune de ces variables n'est définie), alors whichdialog effectue une recherche de programme: Si Xdialog est trouvé et fonctionne, il est utilisé ; sinon si dialog est trouvé, il est utilisé ; sinon si whiptail est trouvé, il est utilisé. Sinon, si la variable LIBSHDIR est définie, alors la commande dialok (fournie avec la bibliothèque libsh), écrite en Tcl/Tk est essayée et si elle fonctionne, est utilisée; sinon, la fonction interne DImdialog est utilisée.

    Comme il y a toujours une solution, les arguments autrefois utilisés pour savoir quoi faire en cas d'impossibilité de trouver une commande compatible dialog sont purement et simplement ignorés.

    dialok et DImdialog sont deux commandes écrites dans le but de satisfaire les besoins de la bibliothèque libsh. Leur imitation de "dialog" est juste suffisante pour libsh. Le but n'étant pas de réécrire complètement "Xdialog", "dialog" ou "whiptail" en Tcl/Tk ou bourn shell.

    NB 1
    Les variables testées peuvent contenir des options, mais ne peuvent pas etre un pipe (|) ou autre commande composée ( && ||... ).
    Elles ne peuvent pas non plus contenir d'argument avec un espace (comme par exemple mon_dialogue --SuperTitre 'Salut Monde'). exemples valides :

    DIALOG="/home/moi/bin/mondialog"
    DIALOG="/home/moi/bin/mondialog --compat --debug"
    

    NB 2
    On peut parfaitement «compléter» la variable whiptail après appel a whichdialog. L'exemple suivant montre un cas ou c'est même interessant :

    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libdialog.scl
    whichdialog || {
    	printf 'Pas trouvé de commande "dialog"\n' >&2
    	exit 1
    }
    case "$whiptail" in
    *Xdialog*)
    	export XDIALOG_HIGH_DIALOG_COMPAT=1 XDIALOG_INFOBOX_TIMEOUT=2000
    	whiptail="$whiptail --cr-wrap"
    ;;
    esac
    

    NB 3 (pour utilisateurs avancés)

    Si vous utilisez une commande dialog personalisée comme par exemple « DIALOG="/home/moi/bin/mondialog --compat --debug" » ET si vous changez l'IFS, alors peut-être bien que la commande $whiptail --yesno coucou 0 0 ne pourra pas s'exécuter normalement.
    Si l'IFS ne contient pas l'espace, $whiptail ne sera pas découpé par le shell.
    La solution sûre est

    eval "$whiptail"' reste de la commande'

    Remarquez bien les guillemets (") et les apostrophes (').
    Toutes les fonctions de la bibliothèque sont construites sur ce modèle et supportent donc toute sorte d'IFS.
    exemple

    DIALOG="/home/moi/bin/mondialog --compat --debug"
    whichdialog
    IFS=:
    eval "$whiptail"' --yesno coucou 0 0'
    

    Code de retour

  • toujours 0
  • Effets secondaires

    La valeur du programme à utiliser est affecté à la variable globale whiptail.

    DIerrbox

    DIerrbox "message" ["titre de fond"]
    		
    Affiche une boite de dialogue d'erreur contenant le message et un bouton OK. Le titre de fond est affiché en dehors de la boite, en haut à gauche de l'écran.
    Exemple
    DIerrbox "This program cannot be run under windows
    
    but will hapilly run under any UNIX" 'Erreur Fatale ;-)'
    
     Erreur Fatale ;-)
     -----------------------------------------------------
    
         +---------------- Erreur -----------------+
         | This program cannot be run under        |
         | Windows                                 |
         |                                         |
         | but will hapilly run under any UNIX     |
         +-----------------------------------------+
         |               <Accepter>                |
         +-----------------------------------------+
    

    DImsgbox

    DImsgbox "message" ["titre de fond"]
    		

    Affiche une boite de dialogue d'information contenant le message et un bouton OK. Le titre de fond est affiché en dehors de la boite, en haut à gauche de l'écran.

    DIouinon

    DIouinon [def=oui|non|yes|no] "message" ["titre" ["titre de fond"]]
    DIouinon [--defaultyes|--defaultno] "message" ["titre" ["titre de fond"]]
    

    affiche une boite de dialogue de type oui non.
    Le titre par defaut est 'Question'
    Il n'y a pas de titre de fond par défaut

    Normalement, le bouton selectionné par défaut est le bouton 'oui'.
    Si le premier argument est de l'un des trois mots def=oui, def=yes, --defaultyes, alors, le bouton selectionné est le bouton 'oui'
    Si le premier argument est de l'un des trois mots def=non, def=no, --defaultno, alors, le bouton selectionné est le bouton 'non'

    Code de retour

    0 : oui
    1 : non
    >1 :annulation ou autre erreur

    Exemple

    if DIouinon 'Continuer à blouitzoir les pitounes ?'  \
                'Étape 3' \
                'Jeu des 10000000 bloutoks'
    then
    	DImsgbox "D'accord. Une pitoune bien blouitzue en vaut deux"
    else
    	DImsgbox " OK :-( On arrête là avec les pitounes."
    fi
    
    
     Jeu des 10000000 bloutoks
     ------------------------------------------------
    
    
             +---------Étape 3-----------+
             | Continuer à blouitzoir    |
             | les pitounes ?            |
             +---------------------------+
             |     < Oui >   < Non >     |
             +---------------------------+
    
    

    DItagmenu

    DItagmenu "texte" "titre de fond" [deftag] tag article tag article...
    		

    Code de retour

    toujours 0

    Effets secondaires

    La variable globale DIchoix est mise à jour.

    description

    Affiche un menu
    Le résultat de la sélection utilisateur est contenu dans la variable DIchoix. Si l'utilisateur a annulé d'une manière ou une autre, ou si une erreur est survenue, alors DIchoix contient une valeur vide, sinon elle contient le tag sélectionné.

    Si le titre du fond est remplacé par la chaine -- ou par une chaine vide, alors il n'y a pas de titre de fond.

    Si il y a un nombre impaire d'argument, alors le premier d'entre eux est considéré comme le tag de la ligne à sélectionner par défaut.
    Sinon, la ligne par défaut est la première.

    exemple

    DItagmenu 'Choix de stratégie' 'Jeux de tête à claque' \
    	3 \
    	1 'Même pas mal' \
    	2 'Demarrer doucement' \
    	3 'Franc ! Ça claque' \
    	4 'Pan dans la gueule' \
    	5 'Pan danloeil' \
    	6 'Force brute' 
    
    	case "$DIchoix" in
    	'')
    		# annulation
    		echo froussard
    	;;
    	[123])
    		echo Petit joueur
    	;;
    	[456])
    		echo Bravo, Vous êtes un grand joueur.
    	;;
    	esac
    
    

    Voila à quoi ressemble le menu :

     Jeux de tête à claque
     ---------------------------------------------------------
               +-------------------------------+
               | Choix de stratégie            |
               | +---------------------------+ |
               | |   1  Même pas mal         | |
               | |   2  Demarrer doucement   | |
               | |   3  Franc ! Ça claque    | |
               | |   4  Pan dans la gueule   | |
               | |   5  Pan danloeil         | |
               | |   6  Force brute          | |
               | +---------------------------+ |
               +-------------------------------+
               |   <Accepter>  <Annuler >      |
               +-------------------------------+
    

    DIcheckbox3

    DIcheckbox3 "texte" "titre de fond" tag article etat tag article etat...
    		

    Code de retour

    toujours 0

    Effets secondaires

    La variable globale DIchoix est mise à jour. et contient la liste des tags selectionnés.

    description

    Affiche une checklist (une liste à choix multiple)
    Le résultat de la sélection utilisateur est contenu dans la variable DIchoix. Si l'utilisateur a annulé d'une manière ou une autre, ou si une erreur est survenue, alors DIchoix contient une valeur vide, sinon elle contient la liste des tags sélectionnés.

    Si le titre du fond est remplacé par la chaine -- ou par une chaine vide, alors il n'y a pas de titre de fond.

    etat peut valoir on ou off

    exemple

    DIcheckbox3 'Que voulez vous faire' -- \
    	1 'Pêcher' on \
    	2 'Du patin à roulette' off \
    	3 'de la tarte au concombre' on \
    	4 'dormir' on
    
    	for i in "$DIchoix"
    	do
    	case $i in
    	1)
    		echo "J adore la peche a la truite"
    	;;
    	2)
    		echo "Il faut prendre un casque"
    	;;
    	3)
    		echo "C'est pas bon, hein!!!!"
    	;;
    	4)
    		echo "Ok, relaxe aujourd'hui"
    	;;
    	esac
    
    

    Voila à quoi ressemble la liste :

    	   +----------------------------------------+
    	   | Que voulez vous faire                  |
    	   | +------------------------------------+ |
    	   | |  [*] 1  Pêcher                     | |
    	   | |  [ ] 2  Du patin à roulette        | |
    	   | |  [*] 3  de la tarte au concombre   | |
    	   | |  [*] 4  dormir                     | |
    	   | +------v(+)--------------------------+ |
    	   +----------------------------------------+
    	   |       <Accepter>    <Annuler >         |
    	   +----------------------------------------+
    
    Retour table des matières

    libstddial.scl

    Boîtes de dialogue standard. Les fonctions définies ici ont besoin de libmaniptab.scl, contrairement à celles définies dans libdialog.scl.
    (voir les remarques sur dialog).

    utilisation et initialisation

    set +e
    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libkwubst.scl
    . $LIBSHDIR/libdialog.scl
    whichdialog
    . $LIBSHDIR/libstddial.scl
    

    utilise

  • globale :
    typeset
  • descripteur de fichier :
    3
  • définit

  • globale :
  • fonctions :
  • STonefromfile
  • STonefromtagfile
  • SToneof
  • DIcheckbox2
  • DIcheckbox1
  • description

    Cette bibliothèque fournit des boîtes de dialogue pour les choix multiples. Que ce soit à partir du contenu d'un fichier ou d'une liste construite par le programme.


    STonefromfile

    STonefromfile "text" "backtitle" /a/file [loop/noloop]

    Permet de choisir une ligne du fichier texte dont le nom est passé en paramètre. Le fichier doit être relativement court pour que cette fonction soit utilisable. La limite varie selon chaque shell et système. elle dépend en effet du nombre de paramètres que l'on peut passer à une fonction et à un programme externe.

    Le fichier ne DOIT PAS conenir de caractère ^C (control-C), car celui ci est utilisé en interne par cette fonction. Comme cette fonction s'utilise sur des fichiers textes, cette restriction ne devrait pas poser de problèmes.

    La ligne choisie est affichée sur la sortie standard.

    Le quatrième paramètre est facultatif et s'il vaut loop oblige l'utilisateur à faire un choix. Si l'utilisateur annule d'une manière ou une autre, la boite de dialogue réapparait.

    code de retour

    Le code de retour de la commande de dialogue.
    0 : ok et valeur validée par opérateur
    1 : Non ou bouton « Annuler » appuyé.
    -1 (255) : Erreur interne de dialogue ou touche « échap » pressée.

    exemple

    line=$(STonefromfile 'You MUST choose a user' '' /etc/passwd loop)
    
    +------------------------------------------------------------------+
    | You MUST choose a user                                           |
    | +--------------------------------------------------------------+ |
    | |0   root:x:0:0:root:/root:/bin/bash                           | |
    | |1   daemon:x:1:1:daemon:/usr/sbin:/bin/sh                     | |
    | |2   bin:x:2:2:bin:/bin:/bin/sh                                | |
    | |3   sys:x:3:3:sys:/dev:/bin/sh                                | |
    | |4   sync:x:4:65534:sync:/bin:/bin/sync                        | |
    | |5   games:x:5:60:games:/usr/games:/bin/sh                     | |
    | |6   man:x:6:12:man:/var/cache/man:/bin/sh                     | |
    | |7   lp:x:7:7:lp:/var/spool/lpd:/bin/sh                        | |
    | |8   mail:x:8:8:mail:/var/mail:/bin/sh                         | |
    | |9   news:x:9:9:news:/var/spool/news:/bin/sh                   | |
    | |10  uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh                 | |
    | |11  proxy:x:13:13:proxy:/bin:/bin/sh                          | |
    | |12  postgres:x:31:32:postgres:/var/lib/postgres:/bin/sh       | |
    | |13  www-data:x:33:33:www-data:/var/www:/bin/sh                | |
    | |14  backup:x:34:34:backup:/var/backups:/bin/sh                | |
    | +.(+)----------------------------------------------------------+ |
    |                                                                  |
    +------------------------------------------------------------------+
    |                             <Accepter>                           |
    +------------------------------------------------------------------+
    
    

    STonefromtagfile

    STonefromtagfile "text" "backtitle" /a/file [loop/noloop] [sep]

    Comme STonefromfile Mais le fichier doit être structuré.

    Les paramètre 4 et 5 sont facultatifs, le cinquième s'il n'est pas précisé vaut ':'

    Chaque ligne doit être composée d'un marqueur pas nécessairement unique suivi d'un séprarateur, suivi du reste de la ligne, ou le séparateur ne doit pas apparaitre. par exemple un fichier comme cela:

    A;bla bli blo
    coucou;Gnarf zplouioque Zschblank!
    Grr;gloup gloup gloup
    Tarte à la fraise;3 tartes et deux fraises
    	

    Le caractère de séparation n'a pas besoin d'être un caractère imprimable. il est parfaitement possible d'utiliser les caractères d'échappement (ASCII 27), control C (ASCII 3) etc...

    La ligne choisie est affichée sur la sortie standard (ycompris le tag et le séparateur).

    Le quatrième paramètre est facultatif et s'il vaut loop oblige l'utilisateur à faire un choix. Si l'utilisateur annule d'une manière ou une autre, la boite de dialogue réapparait.

    code de retour

    Le code de retour de la commande de dialogue.
    0 : ok et valeur validée par opérateur
    1 : Non ou bouton « Annuler » appuyé.
    -1 (255) : Erreur interne de dialogue ou touche « échap » pressée.

    exemple

    
    # Pour cet exemple, on suppose que
    # le fichier /tmp/toto contient ceci
    sep=';'
    ligne="$(STonefromtagfile 'choisir un truc' '' /tmp/toto n "$sep")"
    aifs=$IFS
    IFS=$sep
    set zouip $line
    IFS=$aifs
    shift
    echo "la ligne est --|$ligne|--"
    echo "le tag est --|$1|--"
    echo "le reste de la ligne est --|$2|--"
    
    
      +--------------------------------------------------------+
      | choisir un truc                                        |
      | +----------------------------------------------------+ |
      | |   A                  bla bli blo                   | |
      | |   coucou             Gnarf zplouioque Zschblank!   | |
      | |   Grr                gloup gloup gloup             | |
      | |   Tarte à la fraise  3 tartes et deux fraises      | |
      | +----------------------------------------------------+ |
      +--------------------------------------------------------+
      |             <Accepter>       <Annuler >                |
      +--------------------------------------------------------+
    
    

    SToneof

    SToneof "text" "backtitle" loop/noloop [def=choix] choix [choix...]

    Comme STonefromfile Mais les données sont passées en paramètre.
    Les trois premiers paramètres sont obligatoires
    On peut choisir le choix preselectionné grâce à l'utilisation de def=choix.
    Les données passées ne doivent pas contenir de caractère Control-C (ASCII 3).

    il faut passer au moins un choix à cette fonction

    La ligne choisie est affichée sur la sortie standard.

    code de retour

    Le code de retour de la commande de dialogue.
    0 : ok et valeur validée par opérateur
    1 : Non ou bouton « Annuler » appuyé.
    -1 (255) : Erreur interne de dialogue ou touche « échap » pressée.

    exemple

    
    rep="$(SToneof 'Choisissez votre adversaire' 'Tournoi de gourme' loop \
    	'Schplurtz le déboulonné' \
    	'Zorg l'\''inoxidable' \
    	'Zurst le titanesque' \
    	'Schpluntz l'\''inflexible' \
    	'Maman les p'\''tits bateaux' \
    )"
    
    echo "votre réponse est --|$rep|--"
    votre réponse est --|Schpluntz l'inflexible|--
    
     Tournoi de gourme
     ----------------------------------------------
       +-------------------------------------+
       | Choisissez votre adversaire         |
       | +---------------------------------+ |
       | |   0  Schplurtz le déboulonné    | |
       | |   1  Zorg l'inoxidable          | |
       | |   2  Zurst le titanesque        | |
       | |   3  Schpluntz l'inflexible     | |
       | |   4  Maman les p'tits bateaux   | |
       | +---------------------------------+ |
       +-------------------------------------+
       |             <Accepter>              |
       +-------------------------------------+
    
    

    DIcheckbox2

    DIcheckbox2 "texte" "titre de fond" [etat] tag article tag article...
    		

    Code de retour

    toujours 0

    Effets secondaires

    La variable globale DIchoix est mise à jour. et contient la liste des tags selectionnés.

    description

    Affiche une checklist (une liste à choix multiple)
    Le résultat de la sélection utilisateur est contenu dans la variable DIchoix. Si l'utilisateur a annulé d'une manière ou une autre, ou si une erreur est survenue, alors DIchoix contient une valeur vide, sinon elle contient la liste des tags sélectionnés.

    Si le titre du fond est remplacé par la chaine -- ou par une chaine vide, alors il n'y a pas de titre de fond.

    etat peut valoir on ou off et s'applique à tous les éléments

    exemple

    DIcheckbox2 'Que voulez vous faire' -- on \
    	1 'Pêcher' \
    	2 'Du patin à roulette' \
    	3 'de la tarte au concombre' \
    	4 'dormir'
    
    	for i in "$DIchoix"
    	do
    	case $i in
    	1)
    		echo "J adore la peche a la truite"
    	;;
    	2)
    		echo "Il faut prendre un casque"
    	;;
    	3)
    		echo "C'est pas bon, hein!!!!"
    	;;
    	4)
    		echo "Ok, relaxe aujourd'hui"
    	;;
    	esac
    
    

    Voila à quoi ressemble la liste :

    	   +----------------------------------------+
    	   | Que voulez vous faire                  |
    	   | +------------------------------------+ |
    	   | |  [*] 1  Pêcher                     | |
    	   | |  [*] 2  Du patin à roulette        | |
    	   | |  [*] 3  de la tarte au concombre   | |
    	   | |  [*] 4  dormir                     | |
    	   | +------v(+)--------------------------+ |
    	   +----------------------------------------+
    	   |       <Accepter>    <Annuler >         |
    	   +----------------------------------------+
    

    DIcheckbox1

    DIcheckbox1 "texte" "titre de fond" article article...
    		

    Code de retour

    toujours 0

    Effets secondaires

    La variable globale DIchoix est mise à jour. elle est un tableau dont chaque membre est un des articles selectionnés par l'utilisateur.

    description

    Affiche une checklist (une liste à choix multiple)
    Le résultat de la sélection utilisateur est contenu dans la variable DIchoix. Si l'utilisateur a annulé d'une manière ou une autre, ou si une erreur est survenue, alors DIchoix contient une valeur vide, sinon elle est un talbleau dont chaque membre est un des articles sélectionnés.

    Si le titre du fond est remplacé par la chaine -- ou par une chaine vide, alors il n'y a pas de titre de fond.

    etat peut valoir on ou off et s'applique à tous les éléments

    exemple

    DIcheckbox1 'Que voulez vous faire' -- \
    	'Pêcher' \
    	'Du patin à roulette' \
    	'de la tarte au concombre' \
    	'dormir'
    
    	if '' = "$DIchoix"
    	then
    		echo "vous ne voulez rien faire...
    	else
    		for i in "${DIchoix[@]}"
    		do
    		case $i in
    		"Pêcher")
    			echo "J adore la peche a la truite"
    		;;
    		'Du patin'*)
    			echo "Il faut prendre un casque"
    		;;
    		'de la tarte'*)
    			echo "C'est pas bon, hein!!!!"
    		;;
    		dormir)
    			echo "Ok, relaxe aujourd'hui"
    		;;
    		esac
    	fi
    
    

    Voila à quoi ressemble la liste :

    	   +----------------------------------------+
    	   | Que voulez vous faire                  |
    	   | +------------------------------------+ |
    	   | |  [ ] 1  Pêcher                     | |
    	   | |  [ ] 2  Du patin à roulette        | |
    	   | |  [ ] 3  de la tarte au concombre   | |
    	   | |  [ ] 4  dormir                     | |
    	   | +------v(+)--------------------------+ |
    	   +----------------------------------------+
    	   |       <Accepter>    <Annuler >         |
    	   +----------------------------------------+
    
    Retour table des matières

    libeset.scl

    Édition facile de variables.

    utilisation et initialisation

    set +e
    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libkwubst.scl
    . $LIBSHDIR/libdialog.scl
    . $LIBSHDIR/maniptab.scl
    
    whichdialog
    . $LIBSHDIR/libeset.scl
    

    utilise

  • globale :
    typeset
  • descripteur de fichier :
    3
  • définit

  • globale :
  • fonctions :
  • eset
  • esetlen
  • esetlist
  • eset_valid
  • description

    Le but de cette bibliothèque est de permettre facilement l'édition de variables ou de suite de variables. Le nom eset vient de la commande hyperpratique du même nom de 4dos.
    Cet ensemble de fonctions utilise beaucoup la fonction eval. Pour éviter des clash dans les noms de variables "eval"ués et les noms de variables interne aux fonctions, les noms de toutes les variables internes sont de la forme ESabcdetc ou ES_abcdetc
    N'appelez pas ces fonctions sur des variables dont le nom est constitué de ES_quelquechose ou ESet_de_lettres_en_minuscule !

    eset

    eset nom_de_variable [description] [titre de fond]
    Présente une boîte de dialogue qui permet d'éditer la valeur de la variable. Description est un texte court qui est affiché dans la boîte de dialogue, du genre "Entrer la valeur du Zlorg". Si description n'est pas précisé ou est vide, le nom de la variable est utilisé dans la boite de dialogue.

    code de retour

    Le code de retour de la commande de dialogue.
    0 : ok et valeur validée par opérateur
    1 : Non ou bouton « Annuler » appuyé.
    -1 (255) : Erreur interne de dialogue ou touche « échap » pressée.

    exemple

    eset PATH
    
    +----------------------------------------------------+
    | PATH                                               |
    | +------------------------------------------------+ |
    | |/usr/sbin:/sbin:/home/infor/cmartin/bin:/home/lo| |
    | +------------------------------------------------+ |
    |                                                    |
    +----------------------------------------------------+
    |           <Accepter>      < Annuler >              |
    +----------------------------------------------------+
    

    autre exemple

    function ma_fontion {
    	$typeset val="$1" msg
    
    	eset val "Nouvelle valeur SVP"
    	case $? in
    	0)
    		msg='Vous avez validé'
    	;;
    	1)
    		msg='Vous avez utilisé le bouton « Annuler »'
    	;;
    	-1|255)
    		msg='Vous avez appuyé la touche « échap »'
    	;;
    	*)
    		msg='Erreur inconnue'
    	;;
    	esac
    	DImsgbox "$msg
    quoi qu'il en soit, la valeur de val est :
    $val"
    }
    

    esetlen

    esetlen nom_de_variable description [longueur_max ['titre de fond']]
    Idem eset mais en plus la variable sera tronquée si nécessaire pour ne pas faire plus de longueur_max caractères.
    Si longueur_max n'est pas précisé, sa valeur est 0.

    esetlist

    esetlist nom_de_variable description
    	[- texte]
    	[nom_de_variable description]... ['titre de fond']
    Permet de changer plusieurs variables d'un seul coup. L'annulation ou la validation concerne toutes les variables d'un seul coup.
    Si un nom de variable est le caractère moins (-) alors ce n'est pas un nom de variable, et ce qui suit est le texte qui apparaitra dans la boite de menu. Le texte par defaut est "option setting"

    code de retour

    Le code de retour de la commande de dialogue. Normalement les codes suivants :

    0 : ok et valeur validée par opérateur
    1 : Non ou bouton « Annuler » appuyé.
    -1 (255) : Erreur interne de dialogue ou touche « échap » pressée.
    exemple

    bla='haha `ls -lar`'
    esetlist PATH "chemin d'exécution" HOME maison bla 'bla bla'
    
    +----------------------------------------------------+
    | option setting                                     |
    | +------------------------------------------------+ |
    | |done                                            | |
    | |chemin d'exé /usr/sbin:/sbin:/home/infor/cmartin| |
    | |maison       /home/infor/cmartin                | |
    | |bla bla      haha `ls -lar`                     | |
    | +------------------------------------------------+ |
    |                                                    |
    +----------------------------------------------------+
    |           <Accepter>      < Annuler >              |
    +----------------------------------------------------+
    
    
    esetlist PATH "chemin d'exécution" HOME maison bla 'bla bla' \
    - "Bonjour,
    Validez ou annulez tous ces réglages d'un seul coup" 
    
    +-----------------------------------------------------+
    | Bonjour,                                            |
    | Validez ou annulez tous ces réglages d'un seul coup |
    | +-------------------------------------------------+ |
    | |done                                             | |
    | |chemin d'exécut /usr/sbin:/sbin:/home/infor/cmart| |
    | |maison          /home/infor/cmartin              | |
    | |bla bla         haha `ls -lar`                   | |
    | +-------------------------------------------------+ |
    |                                                     |
    |                                                     |
    +-----------------------------------------------------+
    |             <Accepter>       <Annuler >             |
    +-----------------------------------------------------+
    
    

    eset_valid

    eset_valid nom_de_variable description code_de_validation
    	[titre_de_fond]
    Edite la variable nom_de_variable jusqu'à ce qu'un critère d'acceptabilité soit satisfait ou que l'utilisateur annule. à chaque changement de valeur, le pseudo code suivant est exécuté :
    	variable=valeur_saisie
    	if code_de_validation nom_de_variable valeur_saisie
    	then
    		OK et fin
    	else
    		reset variable et ré-édite
    	fi	
    	

    code de retour 0 : OK, variable a été changée.
    code de retour 1 : Opération annulée ou autre erreur. variable non modifiée.

    normalement, le code de validation est juste le nom d'une fonction ou le nom d'une fonction plus quelques paramètres déja connus (voir exemples ci dessous).
    Si le code de validation est une fonction, et non un programme externe, la variable éditée est disponible dans la fonction de validation, avec la valeur que l'utilisateur voudrait lui donner. Si cette valeur n'est pas acceptable, la fonction doit se terminer avec un code d'erreur non nul, sinon le code d'erreur doit être 0
    Si la valeur est acceptée, la fonction de validation peut même modifier le contenu de la variable, sinon eset_valid remet la variable à sa valeur d'origine et repropose à l'utilisateur d'entrer une valeur.


    exemple 1

    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libkwubst.scl
    . $LIBSHDIR/libdialog.scl
    whichdialog warn
    . $LIBSHDIR/libeset.scl
    function valid_longueur {
    	if test 0 -le "$longueur" -a "$longueur" -le "$1" 2>/dev/null
    	then
    		longueur="$longueur.707"
    		return 0
    	else
    		DIerrbox "La longueur doit être comprise entre 0 et $1"
    		return 1
    	fi
    }
    
    function test_func {
    	$typeset max=100
    	$typeset longueur=4
    
    	eset_valid longueur "Saisissez la longueur entre 0 et $max" "valid_longueur $max" "saisie des longueur"
    
    	printf "la longueur est -->%s<--\n" "$longueur"
    }
    test_func
    
    
    Le même exemple récrit différement
    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libkwubst.scl
    . $LIBSHDIR/libdialog.scl
    whichdialog warn
    . $LIBSHDIR/libeset.scl
    # valid_longueur max nom_var val_var
    function valid_longueur {
    	if test 0 -le "$3" -a "$3" -le "$1" 2>/dev/null
    	then
    		setv "$2" "$3.707"
    		return 0
    	else
    		DIerrbox "La longueur de la variable $2 doit être comprise entre 0
    et $1
    Vous avez saisi : $3
    C'est vraiment n'importe quoi, veuillez recommencer"
    		return 1
    	fi
    }
    
    function test_func {
    	$typeset max=100
    	$typeset longueur=4
    
    	eset_valid longueur "Saisissez la longueur entre 0 et $max" "valid_longueur $max" "saisie des longueur"
    
    	printf "la longueur est -->%s<--\n" "$longueur"
    }
    test_func
    
    

    exemple pour les adresses IP v4. encore qu'on pourait utiliser libnetchoice.scl pour ce genre de chose

    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libkwubst.scl
    . $LIBSHDIR/libdialog.scl
    . $LIBSHDIR/libipv4.scl
    whichdialog warn
    . $LIBSHDIR/libeset.scl
    function valid_ipv4 {
    	$typeset nomvar="$1" valeur="$2"
    	$typeset err oifs="$IFS" msg nl
    	nl='
    '
    	IPsplitip "$valeur" 2>/dev/null || {
    		err=$?
    		case $err in
    		[1234])
    			oifs=$IFS
    			IFS=.
    			set -- $valeur
    			IFS=$oifs
    			eval "msg=\"\${nl}la partie \$err de l'adresse est incorrecte (\$$err)\""
    		;;
    		esac
    		DIerrbox "'$valeur' est une adresse ip invalide$msg"
    		return 1
    	}
    }
    
    eset_valid adresse_ip 'Saisissez une adresse ipv4 normale' valid_ipv4 'un test'
    echo $adresse_ip
    

    Retour table des matières

    libbrowse.scl

    Boîtes de dialogue de parcours d'arborescence.

    utilisation et initialisation

    set +e
    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libdialog.scl
    whichdialog
    . $LIBSHDIR/libbrowse.scl
    

    utilise

  • globale :
    typeset
  • descripteur de fichier :
    3
  • définit

  • globale :
  • fonctions :
  • BRbrowsedir
  • BRbrowsefile
  • description

    Le but de cette bibliothèque est d'offrir des boîtes de dialogue permettant de parcourir facilement des arborescences pour trouver un fichier ou un répertoire.
    Elle fut écrite avant que dialog n'ait l'option --fselect. De toutes façons, Les deux fonctions de cette bibliothèque permettent la navigation dans l'arborescence, ce que ne permet pas dialog même avec cette option. Le fait de ne pas utiliser cette option rend les scripts portables puisqu'ils fonctionneront soit avec whiptail, soit avec dialog, soit avec Xdialog (Si on utilise Xdialog, cette bibliothèque utilise Xdialog --fselect quand elle le peut).

    BRbrowsedir

    BRbrowsedir 'Ttitre relativement court' /start/dir
    Présente une boîte de dialogue qui permet de parcourir une arborescence à la recherche d'un répertoire.

    code de retour

    Normalement, toujours 0

    valeur affichée

    Le répertoire choisi est affiché sur la sortie standard,
    Si rien n'est affiché, l'opérateur a annulé.

    exemple

    dir="$(BRbrowsedir 'Répertoire pour schplourdre les sgrouics' /usr/share/doc)"
    
    +--------------- Répertoire pour schplourdre les sgrouics -----------+
    | Choisissez un répertoire.                                          |
    | Lorsque le répertoire courant est le répertoire que                |
    | vous voulez choisir, sélectionnez «.».                             |
    | Le répertoire courant est :                                        |
    | «/usr/share/doc»                                                   |
    | +-^(+)-----------------------------------------------------------+ |
    | | cm-openoffice               En lecture seule                   | |
    | | cm-openoffice-debian-files  En lecture seule                   | |
    | | console-common              En lecture seule                   | |
    | | console-data                En lecture seule                   | |
    | | console-tools               LS ; ln symb -> console-tools-libs | |
    | | console-tools-libs          En lecture seule                   | |
    | | cpio                        En lecture seule                   | |
    | | cpp                         En lecture seule                   | |
    | | cpp-2.95                    En lecture seule                   | |
    | | cpp-3.0                     LS ; ln symb -> gcc-3.0-base       | |
    | | cramfsprogs                 En lecture seule                   | |
    | +-v(+)-----------------------------------------------------------+ |
    |                                                                    |
    +--------------------------------------------------------------------+
    |                 <Accepter>           < Annuler >                   |
    +--------------------------------------------------------------------+
    
    

    BRbrowsefile

    BRbrowsefile 'Ttitre relativement court' /start/dir [drapeau_création]
    Idem BRbrowsedir mais pour les fichiers.

    Si drapeau_création est indiqué et différent de 0 (zéro) alors l'utilisateur peut choisir de créer des répertoire et choisir un fichier n'existant pas (un nouveau fichier, quoi...)

    Si la comande $whiptail est du type */Xdialog* alors, Xdialog --fselect est utilisé. Cette commande permet TOUJOURS de créer des fichiers, répertoires et même d'en détruire... mais elle est tellement plus pratique et performante que l'ensemble des trucs et bidules nécessaires pour faire fonctionner ces boîtes de dialogue en mode texte...
    exemple

    fichier="$( BRbrowsefile "fichier des sgrouics" /tmp)"
    if test '' = "$fichier"
    then
    	echo Operation annulée
    else
    	....
    fi
    
            +-------------- fichier des sgrouics ----------------+
            | Choisissez un fichier dans le répertoire courant   |
            | ou changer de répertoire. Le répertoire courant    |
            | est :                                              |
            | «/tmp»                                             |
            | +------------------------------------------------+ |
            | |   .                        Répertoire normal   | |
            | |   ..                       En lecture seule    | |
            | |   .home.852                En lecture seule    | |
            | |   ssh-XXi25Vit             Répertoire normal   | |
            | |   .X11-unix                Répertoire normal   | |
            | |   session_mm_apache0.sem                       | |
            | |   titi                                         | |
            | |   toutenv                                      | |
            | |   .vmware.started.cmartin                      | |
            | |   .X0-lock                                     | |
            | |   zmanXZwwwm                                   | |
            | +------------------------------------------------+ |
            +----------------------------------------------------+
            |           <Accepter>      < Annuler >              |
            +----------------------------------------------------+
    
    
    

    Retour table des matières

    libipv4.scl

    Calcul d'adresse IPV4 en shell

    utilisation et initialisation

    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libipv4.scl
    

    utilise

  • globale :
    typeset
  • définit

  • globale :
  • fonctions :
  • IPsplitip
  • IPiptonum
  • IPnumtoip
  • IPmaxaddr
  • IPminaddr
  • IPnetwork
  • IPguessnetmask
  • IPnextip
  • description

    Le but de cette bibliothèque est de permettre facilement le traitement des adresses, masques, réseau IPV4. Aucune commande externe n'est appelée. Toute la logique est implémentée avec des commandes internes des shell. Les masques de réseau peuvent être suivant deux notation : Le nombre de bits à un ou le plus classique quadruplet.

    IPsplitip

    Découpe et vérifie les quatres composants d'une adresse IPV4. Les quatres composants sont affichés sur la sortie standard si l'adresse en paramètre est valide.

    IPsplitip W.X.Y.Z
    	

    Code de retour

  • 0 : Tout est OK
  • 5 : Mauvais format d'adresse
  • 1, 2, 3, 4 : Le nombre 1 (resp 2, 3, 4) n'est pas dans les bornes IPV4 (1..255) ou n'est pas un nombre.

  • On peut donc utiliser du code dans ce genre juste pour tester la validité d'une adresse IP :
    	IPsplitip $addr >&-
    	if test $? = 0 ; then
    		echo $addr is a valid IP adress
    	else
    		echo $addr is an invalid IP adress.
    	fi
    	

    IPiptonum

    Converti une adresse IPv4 en un nombre de 32 bits, plus pratique pour effectuer l'arithmétique. Ce nombre peut sur certaines architectures être négatif (si W >= 128). Ce nombre n'est pas portable d'une architecture à une autre et ne doit être utilisé que pour faciliter l'arithmétique.
    Cette fonction est utilisee par toutes les autres fonctions de cette bibliothèque qui font du calcul sur les adresses et les masques de réseau.
    On peut l'appeler avec un seul nombre (compris entre 8 et 32 inclus) au lieu d'une adresse IPv4. Elle considere alors qu'il s'agit d'un nombre de bits contigus en partant du bit de poids fort ; ce qui permet de faire des calculs sur les masques en notation CIDR.
    Le résultat est affiché sur la sortie standard.

    	IPiptonum W.X.Y.Z
    
    	a=$( IPiptonum $addr )
    
    	mask=$( IPiptonum 21 )
    	# ou alors
    	mask=$( IPiptonum 255.255.248.0 )
    	

    Code de retour

    Attention, depuis la version 1.4.2.0, IPiptonum X avec 8 <= X <= 32 retourne 0 et affiche un nombre sur la sortie standard correspondant à une valeur de masque ayant le nombre X de bits consécutifs à un.
    depuis la version 1.4.0.0, IPiptonum X avec 0 <= X <= 32 retourne 0 et affiche un nombre sur la sortie standard correspondant à une valeur de masque ayant le nombre X de bits consécutifs à un.
    Les verions antérieures n'afichaient rien et retournaient 5.

  • 0 : Tout est OK
  • 5 : Mauvais format d'adresse
  • 1, 2, 3, 4 : Le nombre 1 (resp 2, 3, 4) n'est pas dans les bornes IPV4 (1..255) ou n'est pas un nombre.
  • exemple d'utilisation :

    	# est_dans_reseau IP masque reseau
    	function est_dans_reseau {
    		$typeset nip=$(IPiptonum "$1")
    		$typeset nmasque=$(IPiptonum "$2")
    		$typeset nreseau=$(IPiptonum "$3")
    
    		if test $(( nip & nmasque )) = $nreseau
    		then
    			echo "$1 est dans le reseau $3"
    		else
    			echo "$1 n'est pas dans le reseau $3"
    			return 1
    		fi
    	}
    	est_dans_reseau 199.232.41.9 255.255.255.0 199.232.41.0
    		199.232.41.9 est dans le reseau 199.232.41.0
    	est_dans_reseau 199.232.41.9 24 199.232.41.0
    		199.232.41.9 est dans le reseau 199.232.41.0
    	est_dans_reseau 199.232.42.9 255.255.255.0 199.232.41.0
    		199.232.42.9 n'est pas dans le reseau 199.232.41.0
    	

    IPnumtoip

    Fonction inverse de IPiptonum.

    	IPnumtoip num
    	

    code de retour

  • 0 si num est un entier de 32 bits
  • indéfini sinon
  • IPpfxtonum

    Converti un nombre de bit de masque d'un format CIDR en un nombre entier de 32 bits. L'utilisation de ce nombre est décrite dans l'aide de IPiptonum.
    Le nombre de bit doit être compris entre 8 et 32 inclus.
    Le résultat est affiché sur la sortie standard.

    	mask=$( IPpfxtonum 21 )
    	

    Code de retour

  • 0 : Tout est OK
  • 5 : Le nombre n'est pas un nombre ou il est hors borne.
  • IPpfxtoip

    Converti un nombre de bit de masque d'un format CIDR en un masque ip v4 classique
    Le nombre de bit doit être compris entre 8 et 32 inclus.
    Le résultat est affiché sur la sortie standard.
    Si le parametre en entree est invalide, IPpfxtoip affiche 0.0.0.0 .

    	mask=$( IPpfxtoip 21 )
    
    	test 0.0.0.0 = $mask && echo erreur 2>&1
    	

    Code de retour

    toujours 0

    IPmaxaddr

    
    	a=$( IPmaxaddr 199.232.41.9 255.255.255.0 )
    	# a = 199.232.41.255
    	
    retourne l'adresse la plus haute dans un réseau. (Souvent) l'adresse de broadcast.

    Code de retour

  • 0 : Tout est OK
  • 1 : l'un des deux parametres est invalide.
  • IPminaddr

    	IPminaddr W.X.Y.Z netmask
    
    	a=$( IPminaddr 199.232.41.9 255.255.255.0 )
    	# a = 199.232.41.1
    	
    retourne l'adresse d'hôte valide la plus petite dans le reseau dont fait parti l'adresse IP.

    Code de retour

  • 0 : Tout est OK
  • 1 : l'un des deux parametres est invalide.
  • IPnetwork

    	IPnetwork W.X.Y.Z netmask
    
    	a=$( IPnetwork 172.16.189.25 255.255.248.0 )
    	# a = 172.16.184.0
    	
    retourne l'adresse de reseau dont fait parti l'adresse IP.

    Code de retour

  • 0 : Tout est OK
  • 1 : l'un des deux parametres est invalide.
  • IPnumbit

    	IPnumbit W.X.Y.Z variable
    	IPnumbit CIDR variable
    
    	IPnumbit 255.255.248.0 nbit
    	IPnumbit 21 nbit
    	echo $nbit
    	# affiche 21
    	# nbit = 21
    	
    Met dans la variable passée en 2ème paramètre le nombre de bits à 1 dans le masque.

    Code de retour

    Le même que IPsplitip

    IPguessnetmask

    	IPguessnetmask W.X.Y.Z
    
    	a=$( IPguessnetmask 199.232.41.9 )
    	# a = 255.255.255.0
    	
    retourne le masque de réseau probable pour l'adresse IP passée. Pour un classe A, huit bits de masque, pour un classe B seize bits pour un classe C 24 bits.

    Code de retour

  • 0 : Tout est OK
  • 1 : parametre invalide.
  • IPnextip

    	IPnextip W.X.Y.Z
    
    	a=$( IPnextip 199.232.255.254 )
    	# a = 199.232.255.255
    	a=$( IPnextip $a )
    	# a = 199.233.0.0
    	IPnextip 255.255.255.255
    		0.0.0.0
    	# ATTENTION :
    	IPnextip 134.158.1432.65432
    		134.159.0.0
    	
    retourne l'adresse IP immédiatement supérieure à l'adresse passée en paramètre. le numéro IP est simplement incrémenté, sans autre forme de procès. tout numéro dépassant 255 est mis à zéro et provoque l'incrémentation du nombre suivant.
    Utile pour boucler sur une série d'adresse ip.

    Code de retour

    À l'inverse des autres fonctions de cette bibliothèque, IPnextip ne vérifie pas l'adresse IP passée en paramètre. Tant qu'elle recoit 4 nombres séparés par un point, elle arrive a afficher quelque chose joyeusement. Il est même possible que certains shells affichent un résultat faux si l'entrée est fausse
    Le code de retoure d'IPnextip est donc :

  • probablement non significatif
  • Exemple d'utilisation :

    	# parcours de toutes les adresse d'hôte du sous réseau
    	# 10.1.0.0/22
    	ip=$(IPminaddr 10.1.0.0 255.255.252.0)
    	max=$(IPmaxaddr 10.1.2.3 255.255.252.0)
    	while test $ip != $max
    	do
    		echo $ip
    		ip=$(IPnextip $ip)
    	done
    	


    Retour table des matières

    libnetchoice.scl

    Boîte de dialogue pour saisie des info IPV4 relatives à un ordinateur

    utilisation et initialisation

    set +e
    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libipv4.scl
    . $LIBSHDIR/libkwubst.scl
    . $LIBSHDIR/libdialog.scl
    . $LIBSHDIR/libeset.scl
    whichdialog
    . $LIBSHDIR/libnetchoice.scl
    

    utilise

  • globale :
    typeset
    CMLANG . (en ou fr etc...)
  • descripteur de fichier :
    3
  • eset n'est utilisé QUE si les fonctionalités extra-data sont utilisées. On peut donc normalement ne pas utiliser la libeset avec netchoice.
  • définit

  • globale :
  • GRVERSION Une chaine décrivant la version de la routine. de la forme
    majeur.mineur - texte de la date non parsable
    Par exemple :
    "2.1 - lun mai 27 23:13:18 MEST 2002"
  • fonctions :
  • GRgetip
  • description

    Le but de cette bibliothèque est de permettre facilement l'édition des informations relatives à la configuration IP (v4) d'un ordinateur.

    GRgetip

    resultat="`GRgetip`"
    if test "$resultat" = none
    then
    	echo utilisateur a pas choisi
    elif test dhcp = "$resultat"
    then
    	echo "l'utilisateur" veut configurer par dhcp.
    elif test "$resultat" != :
    then
    	echo configuration manuelle
    	eval "$resultat"
    	echo "pour voir ce qui vient d'être évalué :"
    	echo "$resultat"
    else
    	echo configuration manuelle anullée ou \
    	aucun champ saisi.
    fi
    
    Présente une boîte de dialogue qui permet d'éditer les valeurs IP d'un ordinateur. Au fur et à mesure que l'utilisateur rempli les champs, toutes les valeurs pouvant être calculées (ou devinées avec de bonnes chances) sont remplies automatiquement.

    La première question posée par cette routine est : dhcp ou manuel ? Si l'utilisateur choisis dhcp, alors GRgetip affiche le mot « dhcp » sur sa sortie standard et se termine.

    Si l'utilisateur annule, le texte retourné sur la sortie standard est « none »

    Sinon, l'utilisateur entre dans une boite de dialogue complexe qui permet de saisir les variables suivantes (dont le sens est donné par leur nom):

    	name      ipaddr netmask   network broadcast gateway
            domain    dns_1  dns_2     dns_3
    
    Le texte affiché sera evaluable et sera soit ':'
    si l'oprération est annulée par l'utilisateur, ou si aucun champ n'est rempli soit une suite de 'variable="valeur"' correctement quotée. Les variables sont celles listées juste ci-dessus (name, ipaddr ... dns_3). Dans tous les cas, quelles que soient les options employées, toutes les variables seront affichées dans la valeur à évaluer.

    Les options possibles de GRgetip sont

  • --nodhcp
    Passe directement à l'écran de configuration manuelle.
  • -n ou --noname
    Le dialogue manuel ne demandera pas le nom d'hôte.
  • -d ou --nodomain
    Le dialogue manuel ne demandera pas le domaine
  • -r ou --noresolver
    Ne pas demander les adresse des serveurs de noms
  • -i ou --noip
    Ne pas demander d'information IP (IP, netmask, network number broadcast, default gateway)
  • --var=valeur
    On peut ainsi fixer les variables
    	name   ipaddr netmask   network broadcast gateway
            domain dns_1  dns_2     dns_3
    Et commencer avec une boite de dialogue qui n'est pas vide.
  • --dns='valeur valeur...'
    méthode alternative pour fixer les variables dns_1, dns_2 et dns3. --dns prend une liste de valeur séparée par des espaces ou des virgules.
  • -x nom_variable Description valeur_initiale
    ou --extra-data nom_variable Description valeur_initiale

    Permet de totalement personaliser la boîte de dialogue, en ajoutant des variables au nom et au contenu arbitraire.
  • Aspect visuel de GRgetip

    +------------------------------------------------------------------+
    | Sélectionnez la méthode pourt obtenir une adresse IP.            |
    | La sélection s'effectue avec la barre d'espace                   |
    | utilisez les fleches pour naviguer.                              |
    |                                                                  |
    | Appuyez <Entrée> ou sélectionnez le bouton <ok> pour valider     |
    | votre choix.                                                     |
    |                                                                  |
    | Appuyez <Échap> ou sélectionnez le bouton <cancel> pour sortir   |
    | sans sauvegarder                                                 |
    | +--------------------------------------------------------------+ |
    | |             (X) 1  Utilisation du protocole dhcp             | |
    | |             ( ) 2  spécifier une adresse IP manuellement     | |
    | |                                                              | |
    | |                                                              | |
    | +-----------------.(+)-----------------------------------------+ |
    |                                                                  |
    |                                                                  |
    |                                                                  |
    +------------------------------------------------------------------+
    |                <Accepter>            <Annuler >                  |
    +------------------------------------------------------------------+
    
    +------------------------------------------------------------------+
    | information IP                                                   |
    | Veuillez remplir chacune des rubriques ci dessous. Des réponses  |
    | par défaut vous seront proposées lorsque ce sera possible.       |
    |                                                                  |
    | Choisissez "fini" lorsque vous avez terminé                      |
    | Appuyez <Échap> ou choissisez le bouton <cancel> pour arreter.   |
    | +--------------------------------------------------------------+ |
    | |             Nom                    imladris                  | |
    | |             adresse IP             172.16.197.32             | |
    | |             Masque de sous reseau  255.255.248.0             | |
    | |             Numéro de réseau       172.16.192.0              | |
    | |             Adresse de broadcast   172.16.7.255              | |
    | |             Passerelle par défaut  172.16.0.1                | |
    | |             Nom de domaine                                   | |
    | |             Serveur de nom 1                                 | |
    | |             Serveur de nom 2                                 | |
    | |             Serveur de nom 3                                 | |
    | |             fini                                             | |
    | +--------------------------------------------------------------+ |
    +------------------------------------------------------------------+
    |                 <Accepter>         <Annuler >                    |
    +------------------------------------------------------------------+
    
    	


    Retour table des matières

    libethernet.scl

    Verification et remise en forme textuelle des adresses ethernet

    utilisation et initialisation

    LIBSHDIR=/la/ou/est/installe/la/bibliotheque
    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libkwubst.scl
    . $LIBSHDIR/libethernet.scl
    
    

    utilise

  • globale :
    typeset
    LIBSHDIR (Obligatoire)
    NAWK (Pour
    ETvendeur_nawk seulement)
  • définit

  • globale :
  • fonctions :
  • ETvalidemacp
  • ETcanonmac
  • ETvendeur
  • ETvendeur_nawk
  • ETget_new_iaboui
  • description

    Le but de cette bibliothèque est de manipuler les adresses MAC ou ethernet 48 bits.

    ETvalidemacp

    ETvalidemacp "adresse mac supposée"
    

    Vérifie que la chaine passée en paramètre ressemble à une adresse MAC. pour être valide, la chaine doit être formée de 5 paires de nombres hexadécimaux séparés par des tirets (-), des deux points (:) des espaces ( ) ou rien.

    La fonction n'affiche rien.

    Son code de retour est :
    0 : la chaine est une adresse ethernet unicast
    1 : la chaine est une adresse ethernet multicast
    2 : la chaine n'est pas une adresse ethernet

    Exemple de chaine valide :

    40 00 C0 AF 21 B7
    40 00 C0 af 21 B7
    40-00-C0-af-21-B7
    40:00:C0:af:21:B7
    4000C0af21B7
    40 00C0af21B7
       40 00	C0 af 21 B7
    

    Exemple d'utilisation

    while : ; do
    	printf 'Entrez une adresse ethernet de MACHINE sous une forme quelconque '
    	read ether
    	er=0
    	ETvalidemacp "$ether" || $er=$?
    	test $er = 2 && {
    		printf '%s n'\''est pas une adresse ethernet\n' "$ether" >&2
    		continue;
    	}
    	test $er = 1 && {
    		printf '%s est une adresse ethernet de multidiffusion\n' "$ether" >&2
    		continue;
    	}
    	printf 'OK ! %s est une adresse ethernet valide\n' "$ether"
    	break
    done
    

    ETcanonmac

    ETcanonmac "adresse mac supposée" [sep]
    

    Affiche l'adresse mac sous forme canonique. C'est à dire en majuscule, les octets séparés par des signes deux points (:).
    On peut passer un autre séparateur en second paramètre (y compris une chaine vide).

    Cette fonction fait appel à sed et reformate joyeusement toute sorte de chaine, pas seulement des adresses MAC.

    exemple :

    ether='40 00C0af21B7'
    e1=$(ETcanonmac "$ether") ; echo "$e1"
    ETcanonmac "$ether" ''
    ieee_et=$(ETcanonmac "$ether" -) ; echo $ieee_et
    

    L'exemple précédent peut être réécrit comme ça :

    while : ; do
    	printf 'Entrez une adresse ethernet de MACHINE sous une forme quelconque '
    	read ether
    	er=0
    	ETvalidemacp "$ether" || $er=$?
    	test $er = 2 && {
    		printf '%s n'\''est pas une adresse ethernet\n' "$ether" >&2
    		continue;
    	}
    	test $er = 1 && {
    		printf '%s est une adresse ethernet de multidiffusion\n' "$ether" >&2
    		continue;
    	}
    	ether="$(ETcanonmac "$ether")"
    	printf 'OK ! %s est une adresse ethernet valide\n' "$ether"
    	break
    done
    

    ETvendeur et ETvendeur_nawk

    ETvendeur "adresse mac supposée" [iab.txt] [oui.txt]
    # ou bien
    NAWK=/usr/bin/nawk
    ETvendeur_nawk "adresse mac supposée" [iab.txt] [oui.txt]
    

    Comme les adresses ethernet sont attribuées par l'IEEE, et que l'IEEE distribue ses tables d'attribution librement, il est possible de connaitre le vendeur d'une carte en fonction de son adresse. Ces fonctions recherchent et affichent les informations sur le vendeur de la carte ethernet dont l'adresse est passée en paramêtre.
    La recherche se fait dans les deux fichiers $LIBSHDIR/libsh/iab.txt et $LIBSHDIR/libsh/oui.txt.

    code d'erreur : normalement 0, du moment que les deux fichiers sont accessibles.
    Si l'adresse n'est pas trouvée, le code est tout de même 0. il n'y a pas d'affichage.

    Les deux fichiers iab.txt et oui.txt sont des fichiers texte public publiés par l'IEEE aux URL suivantes :
    http://standards.ieee.org/regauth/oui/iab.txt
    et
    http://standards.ieee.org/regauth/oui/oui.txt

    Vous pouvez, de temps en temps télécharger ces fichiers pour mettre à jour ceux qui sont installés avec la bibliothèque, ou vous pouvez fournir vos propres fichiers lors de l'appel de ces fonctions.
    Le premier fichier DOIT comporter au moins une ligne.

  • ETvendeur
    Cette fonction est portable. Malheureusement elle est assez lente et coûteuse. Elle appelle ETcanonmac et utilise ensuite sed pour traiter les fichiers iab.txt et oui.txt.
  • ETvendeur_nawk
    Cette foncion n'est malheureusement pas portable car elle utilise nawk (un awk POSIX pour faire simple) et localiser une telle commande de manière certaine n'est pas aisé.
    Par contre, elle n'a pas besoin d'appeler ETcanonmac et elle est incontestablement plus rapide.
    AVANT d'appeler cette fonction, il faut renseigner la variable NAWK pour qu'elle pointe vers un nawk voir les exemples ci dessous.
  • exemple portable :

    ETvendeur 00:01:FA:3A:17:7E
    HOROSCAS
    26, LOUIS BLANC
    69006 LYON
    FRANCE
    FRANCE
    
    ETvendeur ACDE48124365
    PRIVATE
    

    exemple moins portable
    Sous SOLARIS ou bien Debian GNU/Linux

    	NAWK=/usr/bin/nawk
    	ETvendeur_nawk 0050C230D345
    	SETARAM
    	7 Rue de l'oratoire
    	CALUIRE rhone 69300
    	FRANCE
    

    Sous Darwin

    	NAWK=/usr/bin/awk
    	ETvendeur_nawk 0050C230D345
    	SETARAM
    	7 Rue de l'oratoire
    	CALUIRE rhone 69300
    	FRANCE
    

    Sous une vieille ChapeauRouge

    	NAWK=/bin/awk
    	ETvendeur_nawk 0050C230D345
    	SETARAM
    	7 Rue de l'oratoire
    	CALUIRE rhone 69300
    	FRANCE
    

    ETget_new_iaboui

    ETget_new_iaboui [show=true] "repertoire"
    

    tente de télécharger depuis le site web de l'ieee la version actualisée des fichiers iab.txt et oui.txt.

    Les fichiers sont téléchargés dans le repertoire indiqué ou dans /tmp si le répertoire est omis.

    Le telechargement se fait avec l'utilitaire wget.

    Si l'option show=true est utilisé alors le bavardage habituel de wget (principalement la barre de progression) est affiché sur l'erreur standard. Sinon, cette fonction ne produit aucun affichage.

    code de retour est :
    0 : wget n'a pas indiqué d'erreur et les fichiers ont pu être mis dans le répertoire indiqué sous les noms iab.txt et oui.txt
    1 : wget s'est mal terminé.
    autre : wget s'est bien terminé mais les fichiers n'ont pas pu être placés dans le répertoire indiqué sous les noms iab.txt et oui.txt. Les fichiers téléchargés sont effacés.


    Retour table des matières

    libdiethernet.scl

    Boîtes de dialogue pour saisir des adresses mac

    utilisation et initialisation

    LIBSHDIR=/la/ou/est/installe/la/bibliotheque
    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libkwubst.scl
    . $LIBSHDIR/libethernet.scl
    . $LIBSHDIR/libdialog.scl
    . $LIBSHDIR/libdiethernet.scl
    whichdialog
    
    

    utilise

  • globale :
    typeset
    whiptail
    CMLANG (pour les messages)
    LIBSHDIR (Obligatoire à cause de
    libethernet.scl)
  • descripteur de fichier :
    3 : une copie de 1 (exec 3>&1)
  • définit

  • globale :
  • fonctions :
  • ETdi_validemac_ou_vide
  • ETdi_validemac
  • ETeset_mac_valide
  • description

    Le but de cette bibliothèque est de présenter une boite de dialogue permettant la saisie d'adresse mac/ethernet 48 bits.

    ETdi_validemac_ou_vide

    ETdi_validemac_ou_vide [-ok-multicast] nom_variable valeur_candidate
    

    Cette fonction est une fonction de vérification pour eset_valid.

    Elle accepte quelque chose qui ressemble à une adresse ethernet (voir ETvalidemacp) ou qui est vide.
    Par défaut, les adresses ethernet de multidiffusion ne sont pas acceptées ; pour qu'elles le soient, il faut utiliser l'option -ok-multicast.

    En cas d'erreur de saisie, une boîte d'erreur est affichée. et la fonction retourne 1

    sinon la fonction retourne 0 et l'adresse mac sous forme canonique (voir ETcanonmac) est affectée à la variable.

    Exemple de chaine valide

    eset_valid adr_ether "Entrez une adresse ethernet" ETdi_validemac_ou_vide
    printf 'vous avez saise la chose suivante --|%s|--\n' "$adr_ether"
    

    ETdi_validemac

    ETdi_validemac [-ok-multicast] nom_variable valeur_candidate
    

    Cette fonction est une fonction de vérification pour eset_valid.

    Elle se comporte comme ETdi_validemac_ou_vide mais les chaines vides sont refusées.

    ETeset_mac_valide

    ETeset_mac_valide [-ok-multicast] [-ok-vide] nom_variable [texte_d_invite]
    

    Cette fonction affiche une boîte de dialogue invitant l'utilisateur à saisir une adresse mac. Si aucun texte_d_invite n'est donné, elle utilise une explication générique invitant l'utilisateur à saisir une adresse mac.

    La valeur saisie est vérifiée par l'une des deux fontions de vérification définies plus haut et par conséquent, la variable dont le nom est passé en paramètre reçoit une adresse sous forma canonique.

    Code de retour :

  • 0 : une adresse valide est saisie et l'utilisateur n'a pas annulé l'opération.
  • non 0 : opération annulée par l'utilisateur ou autre erreur de $whiptail.
  • Cette fonction admet deux options ; si on emploie les deux options, -ok-multicast DOIT être la première.

  • -ok-multicast
    accepter aussi les adresses ethernet de multidiffusion.
  • -ok-vide
    accepter aussi une chaine vide
  • exemple

    while :
    do
    	ETeset_mac_valide ether || break
    	DImsgbox "Description de l'adresse saisie :
    $(ETvendeur "$ether")"
    done
    
    #
    # Exemple d'ecrans produits par ce code :
    #
    +----------------------------------------------------------+
    | Veuillez saisir l'adresse physique (MAC) de la machine   |
    |                                                          |
    | Vous pouvez utiliser des majuscules, minuscules          |
    | des deux point (00:50:C2:FF:A9:B8),                      |
    | des tirets (00-50-C2-FF-F4-B8),                          |
    | des espaces (00 50 C2 FF F4 B8),                         |
    | ou rien du tout (0050C2FFF4B8)                           |
    | +------------------------------------------------------+ |
    | |00:50:C2:FF:F4:B8                                     | |
    | +------------------------------------------------------+ |
    +----------------------------------------------------------+
    |               <Accepter>        <Annuler >               |
    +----------------------------------------------------------+
    
    
    
    +------------Information--------------+
    | Description de l'adresse saisie :   |
    | IEEE REGISTRATION AUTHORITY         |
    | 445 HOES LANE                       |
    | PISCATAWAY NJ 08854                 |
    | UNITED STATES                       |
    +-------------------------------------+
    |             <Accepter>              |
    +-------------------------------------+
    
    

    Retour table des matières

    libmaniptab.scl

    manipulation de tableau. Création, destruction, copie, concaténation de tableau. Insertion, destruction, ajout, recherche et remplacement d'éléments. ATTENTION

    utilisation et initialisation

    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libkwubst.scl
    . $LIBSHDIR/libmaniptab.scl
    
    # auto initialisation done
    

    utilise

  • globale :
    typeset
  • définit

  • globale :
  • TAindice
    ATTENTION
    renseignée par fonctions tabindicede et tabtousindicede
  • fonctions :
  • tableau
  • tablong
  • tabaffiche
  • tabcopie
  • tabajoute
  • tabdepile
  • tabsommet
  • tabdefile
  • tabinsere
  • tabintercale
  • tabplace
  • tabconcatene
  • tabdetruit
  • tabindicede
  • tabcontient
  • tabtousindicede
  • tabforeach
  • tabboucle
  • tabpourn
  • tabmix
  • tabsep
  • tabsauve
  • ATTENTION

    Les version précédentes utilisaient TABindice. Comme ce nom ne peut être utilisé dans une boucle tabforeach (la chaine TAB serait transformée), j'utilise désormais TAindice (le B a disparu.)

    description

    Toutes les fonctions tab* manipulent des tableaux. Il existe quelques contraintes.

    • La taille des tableaux est limitée en ksh (512 max?)
    • Les noms des tableaux passés en paramètre à ces fonctions ne peuvent être l'un des suivants :
      TAcma TAcmb TAcmn TAcmi TAcml TAcmt TAcmN TAcmf TAcmI TAcmj
       
      En effet, les noms étant passé en paramètre, ces fonctions font appel à « eval ». Il peut dont y avoir un conflit de nom entre le nom passé en paramètre et les noms de variable locale utilisées par les fonctions tab*.
    • Les indices doivent commencer à zéro.
      En zsh(1), il faudra donc utiliser l'option KSH_ARRAYS pour que les tableaux comencent à un. mais cela a d'autres effets. D'autre part, zsh propose des tableaux associatifs, qui ont sans aucun doute possible de biens meilleures performance que la fonction tabindicede.
    • Les indices doivent tous être contigüs. (pas de trous dans la numérotation).

    tableau

    tableau nom [element] [element...]

    tableau crée ou recrée un tableau nommé nom, et contenant les éléments éventuel passés en paramètre. Il est a noter que BASH a un comportement étrange. Si l'un, ou plus, des élément est de la forme [nombre]=chaine, alors chaine est la valeur de l'indice nombre. Les autres shell n'utilisent pas cette particularité et donc la commande

    tableau table valA 'Val B' [12]=Val_C Val_DEF
    Ne produit pas le même résultat avec tous les shells.
    Encore une fois, je déteste les Basheries.

    exemple :

    tableau table /tmp/*

    tablong

    tablong tableau
    Affiche le nombre d'éléments d'un tableau. plus pratique que ${#tableau[@]}, mais aussi beaucoup plus couteux. À éviter si possible.

    exemple :

    n=$(tablong table)
    n=${#table[@]}
    

    La première ligne est moins performante que la seconde.

    tabaffiche

    tabaffiche tableau

    Afiche le contenu du tableau, avec les indices. Si le tableau ne respecte pas les contraintes indiquées dans la section description l'affichage ne refletera pas le contenu du tableau. C'est une des limitations due au fait qu'il est impossible de savoir quels indices sont réellement utilisés dans un tableau.

    tabcopie

    tabcopie dest source

    tabcopie copie le contenu du tableau source dans le tableau dest.
    en fait tabcopie effectue l'équivallent de

    eval "tableau $dest \"\${${source}[@]}\""

    On peut copier un tableau sur lui même. cela consomme du temps mais ne change aucune valeur.

    tabajoute

    tabajoute tableau [elem] [elem...]

    Ajoute à la fin de tableau des éléments. Il est parfaitement possible d'ajouter à un tableau inexistant. Cela crée le tableau et commence à le remplire à partir de l'indice 0.
    Attention toutefois à la basherie suivante : si le tableau est local a une fonction et simplement déclaré avec $typeset, alors le premier indice est déja occupé, voir exemple 2.
    exemple:

    tabajoute table fin finfin finFINfin
    tabaffiche table

    exemple 2

    function f {
    	$typeset x
    	tabajoute x 1
    	tabajoute x 2 3 4
    	tabaffiche x
    }
    f
    x[0] = ''
    x[1] = '1'
    x[2] = '2'
    x[3] = '3'
    x[4] = '4'
    

    On peut contourner le problème de la manière suivante, mais cette fois c'est pdksh (au moins) qui n'est pas content et réagit plutot mal (il affecte à une variable globale)

    function f {
    	$typeset x
    	tableau x
    	tabajoute x 1 2 3 4
    	tabaffiche x
    }
    

    M O R A L I T É
    Mettez au moins un element dans vos tableaux locaux avant d'utiliser tabajoute. La fonction tableau appelée avec un élément à mettre dans le tableau, produit un tableau local comme on s'y attend. L'exemple suivant est donc parfaitement portable :

    function f {
    	$typeset x
    	tableau x dummy
    	tabajoute x a b cd
    	tabajoute x 1 2 3 4
    	tabdetruit x 0 1
    	tabaffiche x
    }
    
    en plus ça marche aussi avec ksh :

    tabdepile

    tabdepile dest var

    tabdepile enlève l'élément de plus grand indice du tableau dest et le place dans la variable var

    Le code de retour est 0 (zéro) si le tableau contenait au moins un élément lors de l'appel.
    Le code est non nul dans tous les autres cas.

    function f {
    	$typeset pile sommet
    	tableau pile 1 2 3 4
    	while tabdepile pile sommet
    	do
    		echo "so = --|$sommet|--"
    	done
    	tabajoute pile toto titi tutu
    	tabaffiche pile
    }
    f
    echo de retour de f
    tabaffiche pile
    	affichage produit :
    so = --|4|--
    so = --|3|--
    so = --|2|--
    so = --|1|--
    pile[0] = 'toto'
    pile[1] = 'titi'
    pile[2] = 'tutu'
    de retour de f
    		

    Autre exemple rigolo

    # hanoi nb_disc
    function hanoi {
    	$typeset i
    	tabdetruit ha_un tout || :
    	tabdetruit ha_deux tout || :
    	tabdetruit ha_trois tout || :
    	i=$1
    	while test $i -gt 0
    	do
    		tabajoute ha_un $i
    		i=$(( i - 1 ))
    	done
    	# Correspondance numpile, tableau de ce qui est empilé dessus.
    	tableau ha_nb_nm '' ha_un ha_deux ha_trois
    	rhanoi "$1" 1 3
    }
    
    # rhanoi n de ver libre
    function rhanoi {
    	$typeset n nde nvers nlibre de vers libre sommet
    	n=$1
    	nde=$2
    	nvers=$3
    
    
    	if test $n = 0
    	then
    		return
    	fi
    	nlibre=$(( 6 - nde - nvers ))
    	rhanoi $((n - 1)) $nde $nlibre
    
    	de=${ha_nb_nm[nde]}
    	vers=${ha_nb_nm[nvers]}
    	libre=${ha_nb_nm[nlibre]}
    
    	tabdepile $de sommet
    	tabajoute $vers "$sommet"
    	printf 'Déplacer le disque num %d du piquet %d vers piquet %d\n' \
    		$sommet $nde $nvers
    
    	rhanoi $((n - 1)) $nlibre $nvers
    }
    hanoi 5
    

    tabsommet

    tabsommet tableau [var]

    tabsommet affiche ou place dans la variable var la valeur de l'élément de plus grand indice du tableau.

    Si le tableau n'a pas d'éléments (ie si aucune variable portant ce nom n'est définie),

      • rien n'est affiché (si aucune variable passée en paramètre)
      • La variable passée en paramètre reçoit une valeur nulle
    1. et le code de retour vaut 1

    tableau Zorh a b c d
    tabsommet Zorh
    # Ça affiche : d
    tabsommet Zorh x
    echo "$x"
    # Ça affiche : d
    		

    tabdefile

    tabdefile dest var

    tabdefile enlève l'élément d'indice 0 du tableau dest et le place dans la variable var.

    Tous les autres éléments du tableau sont ensuites déplacés d'une place vers le bas.

    Le code de retour est 0 (zéro) si le tableau contenait au moins un élément lors de l'appel.
    Le code est non nul dans tous les autres cas.

    tableau file  1 2 3 4
    while tabdefile file devant
    do
    	echo "de = --|$devant|--"
    done
    	produit cela :
    de = --|1|--
    de = --|2|--
    de = --|3|--
    de = --|4|--
    
    		

    tabinsere

    tabinsere tableau [elem] [elem...]

    Insère les éléments au début du tableau.
    exemple :

    $ tableau t a b
    $ tabaffiche t
    t[0] = 'a'
    t[1] = 'b'
    $ tabinsere t debut 'Juste apres' 'plus loin'
    tabaffiche t
    t[0] = 'debut'
    t[1] = 'Juste apres'
    t[2] = 'plus loin'
    t[3] = 'a'
    t[4] = 'b'
    

    tabintercale

    tabintercale tableau indice [elem] [elem...]

    Insère les éléments à l'indice indiqué. l'indice doit être dans l'intervalle [0 nombre-d-element]. Si indice est égal au nombre d'élément du tableau, cette fonction se comporte comme tabajoute, si indice est plus grand, son code de retour est 1, sinon les éléments sont insérés à l'indice indiqué.
    exemple

    $ tabaffiche t
    t[0] = 'a'
    t[1] = 'b'
    t[2] = 'c'
    t[3] = 'd'
    $ tabintercale t 4 comme tabajoute
    $ tabaffiche t
    t[0] = 'a'
    t[1] = 'b'
    t[2] = 'c'
    t[3] = 'd'
    t[4] = 'comme'
    t[5] = 'tabajoute'
    $ tabintercale t 4 pas tout à fait
    $ tabaffiche t
    t[0] = 'a'
    t[1] = 'b'
    t[2] = 'c'
    t[3] = 'd'
    t[4] = 'pas'
    t[5] = 'tout'
    t[6] = 'à'
    t[7] = 'fait'
    t[8] = 'comme'
    t[9] = 'tabajoute'
    

    tabplace

    tabplace tableau indice [elem] [elem...]
    Remplace les éléments du tableau à partir de indice. Cette fonction peut parfaitement agrandir le tableau. Comme pour tabintercale, l'indice peut être le premier indice non utilisé du tableau, mais pas supérieur. Si l'indice est trop grand, tabplace a un code de retour égal à 1.
    $ tableau t a b c
    $ tabaffiche t
    t[0] = 'a'
    t[1] = 'b'
    t[2] = 'c'
    $ tabplace t 1 X Y Z
    $ tabaffiche t
    t[0] = 'a'
    t[1] = 'X'
    t[2] = 'Y'
    t[3] = 'Z'
    
    		

    tabconcatene dest [tab...]

    augmente ou crée le tableau dest en y plaçant les éléments de tous les tableaux dont les noms suivent.
    exemple :
    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libmaniptab.scl
    
    tableau tab a b c
    tableau zorg 1 2 3
    tabconcatene blu tab zorg
    tabaffiche blu
    blu[0] = 'a'
    blu[1] = 'b'
    blu[2] = 'c'
    blu[3] = '1'
    blu[4] = '2'
    blu[5] = '3'
    		

    tabdetruit tab indice longueur

    si indice vaut "tout" le tableau est dé-défini (unset) dans sa globalité, le troisième paramètre est inutile dans ce cas.
    sinon,

    détruit longueur éléments dans le tableau tab à partir de l'indice indice.
    Les éléments d'indice suppérieur au dernier indice détruit sont décalé vers le bas de manière à conserver le tableau "sans trous".
    Si longueur est plus grand que le nombre d'élément du tableau (en comptant à partir de indice), cela n'affecte pas cette fonction, ni ses performances.
    Si indice est plus grand que le plus grand indice du tableau cette fonction se comporte bien et ne fait rien.
    Le code de retour de la fonction n'est pas significatif et vaut normalement toujours 0.
    exemple :

    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libmaniptab.scl
    
    tableau tab a b c E F G H i j k l
    #           0 1 2 3 4 5 6 7 8 9 10
    tabdetruit tab 3 4
    tabaffiche tab
    tab[0] = 'a'
    tab[1] = 'b'
    tab[2] = 'c'
    tab[3] = 'i'
    tab[4] = 'j'
    tab[5] = 'k'
    tab[6] = 'l'
    
    		

    tabindicede

    tabindicede tableau "Valeur"

    Parcours séquentiellement les éléments du tableau tableau et s'arrete dès qu'un élément identique à valeur est trouvé. La variable TAindice contient alors l'indice du tableau contenant l'élément identique à valeur. Si valeur n'est pas trouvée dans le tableau, TAindice est fixée à ''
    Le code de retour de la fonction n'est pas significatif et vaut normalement toujours 0.
    On préferera souvent la fonction tabcontient car le code de retoure de tabcontient est significatif.
    exemple :

    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libmaniptab.scl
    
    tableau tab a b c d e F g h i j F F m n o F q r s t u v
    tabindicede tab F
    if ! test "$TAindice"
    then
    	echo pas d"'élément F dans tab"
    else
    	echo "l'indice du 1er l'élément F dans tab est $TAindice"
    	echo "tab[$TAindice]=${tab[$TAindice]}"
    
    fi
    		

    tabcontient

    tabcontient tableau "Valeur"

    Parcours séquentiellement les éléments du tableau tableau et s'arrete dès qu'un élément identique à valeur est trouvé. La variable TAindice contient alors l'indice du tableau contenant l'élément identique à valeur. Si valeur n'est pas trouvée dans le tableau, TAindice est fixée à ''
    Le code de retour de la fonction est significatif et vaut 0 si l'élément est trouvé et 1 sinon.
    exemple :

    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libmaniptab.scl
    
    tableau tab a b c d e F g h i j F F m n o F q r s t u v
    if tabcontient tab F
    then
    	echo "l'indice du 1er élément F dans tab est $TAindice"
    	echo "tab[$TAindice]=${tab[$TAindice]}"
    else
    	echo pas d"'élément F dans tab"
    
    fi
    		

    tabtousindicede

    idem tabindicede mais TAindice contient une liste d'indice si plus d'un élément du tableau est idenique à la valeur recherchée. Si aucune valeur n'est trouvée dans le tableau, TAindice est fixée à ''
    Le code de retour de la fonction est

    0
    Au moins un élément a été trouvé
    1
    Aucun élément n'a été trouvé

    exemple :
    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libmaniptab.scl
    
    tableau tab a b c d e F g h i j F F m n o F q r s t u v
    if tabtousindicede tab F
    then
    	for i in $TAindice
    	do
    		echo "tab[$i]=${tab[i]}"
    
    	done
    else
    	echo pas d"'élément F dans tab"
    fi
    		

    tabforeach

    tabforeach tableau commande
    tabforeach tableau indice_debut commande
    tabforeach tableau indice_debut incr commande

    Cette fonction est trop compliquée et fait trop de choses, utiliser tabboucle est souvent suffisant

    Pour chaque élément du tableau, tabforeach excute la commande. Les éléments sont passés en revue séquentiellement de l'indice indice_debut ou 0 si celui ci n'est pas indiqué, jusqu'à l'indice maximum du tableau, par pas de incr (1 par défaut).
    Si le tableau ne contient aucun élément, la commande n'est pas exécutée du tout.
    Si indice_debut est plus grand que le plus grand indice du tableau, la commande n'est pas exécutée du tout.

    Il est possible d'utiliser un "break" pour sortir prématurément de la boucle.

    Il est possible d'utiliser un "continue" pour passer directement à l'itération suivante de la boucle.

    On peut parfaitement imbriquer les commandes tabforeach, bien que l'écriture de la commande devienne difficile à cause des nombreux \ qu'on est en général obligé d'utiliser.

    Avant d'exécuter la commande, tabforeach remplace toutes les occurences de la chaine "TAB" par le nom du tableau.

    Dans la comande, "$1" correspond à l'indice de l'élément examiné et "$2" correspond à sa valeur.

    exemple :

    tableau toto a bcd 1 '2 3 4' ijkl moi douze
    tabforeach toto 'printf "TAB[$1] = %s\n" "$2"'
    toto[0] = a
    toto[1] = bcd
    toto[2] = 1
    toto[3] = 2 3 4
    toto[4] = ijkl
    toto[5] = moi
    toto[6] = douze
    
    tabforeach toto 'printf "TAB[$1] = %s\n" "$2"
    if test $1 -ge 4
    then
    	printf "\$1 = 4, on quitte\n"
    	break
    fi'
    toto[0] = a
    toto[1] = bcd
    toto[2] = 1
    toto[3] = 2 3 4
    toto[4] = ijkl
    $1 = 4, on quitte
    
    Exemple, utilisant des tabforeah imbriqué : Le tableau "premier" contient des noms de tableau dont on affiche les éléments.
    tableau premier deuxieme troisieme autre_tableau 
    tableau deuxieme 2 22 222 22212
    tableau troisieme ttt 333 33 3333
    tableau autre_tableau hjkhk 9090 'ls -l' 'Gnarf gnarf'
    tabforeach premier 'printf "TAB[$1]=%s\n" "$2"
    tabforeach "$2" "printf \"	$2[\$1]=%s\n\" \"\$2\""'
    premier[0]=deuxieme
            deuxieme[0]=2
            deuxieme[1]=22
            deuxieme[2]=222
            deuxieme[3]=22212
    premier[1]=troisieme
            troisieme[0]=ttt
            troisieme[1]=333
            troisieme[2]=33
            troisieme[3]=3333
    premier[2]=autre_tableau
            autre_tableau[0]=hjkhk
            autre_tableau[1]=9090
            autre_tableau[2]=ls -l
            autre_tableau[3]=Gnarf gnarf
    
    L'emploi d'une fonction supplémentaire pour exécuter la seconde commande peut grandement simplifier la commande ci dessus.
    function f {
    	tabforeach $1 'printf "\tTAB[$1]=%s\n" "$2"'
    }
    tabforeach premier 'printf "TAB[$1]=%s\n" "$2" ; f $2'
    premier[0]=deuxieme
            deuxieme[0]=2
            deuxieme[1]=22
            deuxieme[2]=222
            deuxieme[3]=22212
    premier[1]=troisieme
            troisieme[0]=ttt
            troisieme[1]=333
            troisieme[2]=33
            troisieme[3]=3333
    premier[2]=autre_tableau
            autre_tableau[0]=hjkhk
            autre_tableau[1]=9090
            autre_tableau[2]=ls -l
            autre_tableau[3]=Gnarf gnarf
    

    tabboucle

    tabboucle tableau variable_de_boucle commande
    tabboucle tableau variable_de_boucle indice_debut commande
    tabboucle tableau variable_de_boucle indice_debut incre commande
    

    Pour chaque élément du tableau, tabboucle excute la commande. Les éléments sont passés en revue séquentiellement de l'indice indice_debut ou 0 si celui ci n'est pas indiqué jusqu'à l'indice maximum du tableau, par pas de incr (1 par defaut)
    Si le tableau ne contient aucun élément, la commande n'est pas exécutée du tout.
    Si indice_debut est plus grand que le plus grand indice du tableau, la commande n'est pas exécutée du tout.

    La variable variable_de_boucle est utiliséee pour les indices du tableau et est disponible dans la commande.

    Il est possible d'utiliser un "break" pour sortir prématurément de la boucle.

    Il est possible d'utiliser un "continue" pour passer directement à l'itération suivante de la boucle.

    On peut parfaitement imbriquer les commandes tabboucle, bien que l'écriture de la commande devienne difficile à cause des nombreux \ qu'on est en général obligé d'utiliser.

    tableau toto a bcd 1 '2 3 4' ijkl moi douze
    tabboucle toto i 'printf "toto[$i] = %s\n" "${toto[i]}"'
    toto[0] = a
    toto[1] = bcd
    toto[2] = 1
    toto[3] = 2 3 4
    toto[4] = ijkl
    toto[5] = moi
    toto[6] = douze
    
    tabboucle toto i 2 'printf "toto[$i] = %s\n" "${toto[i]}"
    if test $1 -ge 4
    then
    	printf "\$1 = 4, on quitte\n"
    	break
    fi'
    toto[2] = 1
    toto[3] = 2 3 4
    toto[4] = ijkl
    $1 = 4, on quitte
    

    tabpourn

    tabpourn tableau min max commande
    tabpourn tableau min max incr commande
    

    C'est une variante de tabforeach

    Pour chaque élément du tableau, allant de min a max, tabpourn exécute commande. Les éléments sont passés en revue séquentiellement de l'indice min jusqu'à l'indice max par pas de incr

    si incr n'est pas specifié, il vaut 1.

    si max vaut - (le signe moins), alors le plus grand indice du tableau sera utilisé.
    Si min vaut - (le signe moins), alors le plus petit indice du tableau (toujours 0) sera utilisé.

    si max est (ou même min) est supérieur au nombre d'élément du tableau, la boucle est tout de même exécutée pour ces éléments.

    Il est possible d'utiliser un "break" pour sortir prématurément de la boucle.

    Il est possible d'utiliser un "continue" pour passer directement à l'itération suivante de la boucle.

    On peut parfaitement imbriquer les commandes tabpourn, bien que l'écriture de la commande devienne difficile à cause des nombreux \ qu'on est en général obligé d'utiliser.

    Avant d'exécuter la commande, tabpourn remplace toutes les occurences de la chaine "TAB" sont remplacées par le nom du tableau.

    Dans la comande, "$1" correspond à l'indice de l'élément examiné et "$2" correspond à sa valeur.

    exemple

    $ zbouib=1
    $ tabpourn zbouib 1 12 'zbouib[$1]=$(( zbouib[$1 - 1] + 3 ))'
    $ tabaffiche zbouib
    zbouib[ 0] = '1'
    zbouib[ 1] = '4'
    zbouib[ 2] = '7'
    zbouib[ 3] = '10'
    zbouib[ 4] = '13'
    zbouib[ 5] = '16'
    zbouib[ 6] = '19'
    zbouib[ 7] = '22'
    zbouib[ 8] = '25'
    zbouib[ 9] = '28'
    zbouib[10] = '31'
    zbouib[11] = '34'
    zbouib[12] = '37'
    $ tabpourn 7 - 'zbouib[$1]=$2.$RANDOM'
    $ tabaffiche zbouib
    zbouib[ 0] = '1'
    zbouib[ 1] = '4'
    zbouib[ 2] = '7'
    zbouib[ 3] = '10'
    zbouib[ 4] = '13'
    zbouib[ 5] = '16'
    zbouib[ 6] = '19'
    zbouib[ 7] = '22.398'
    zbouib[ 8] = '25.17437'
    zbouib[ 9] = '28.8985'
    zbouib[10] = '31.6438'
    zbouib[11] = '34.18406'
    zbouib[12] = '37.17526'
    
    plat=---
    tabpourn plat 1 12 'plat[$1]="${plat[$1 - 1]}--"'
    tabaffiche plat
    plat[ 0] = '---'
    plat[ 1] = '-----'
    plat[ 2] = '-------'
    plat[ 3] = '---------'
    plat[ 4] = '-----------'
    plat[ 5] = '-------------'
    plat[ 6] = '---------------'
    plat[ 7] = '-----------------'
    plat[ 8] = '-------------------'
    plat[ 9] = '---------------------'
    plat[10] = '-----------------------'
    plat[11] = '-------------------------'
    plat[12] = '---------------------------'
    
    

    tabmix

    tabmix dest t1 [t2 ... tn]

    tabmix mélange n tableaux ayant le même nombre d'éléments en un seul tableau en intercalant les éléments de t1, t2 ... tn. Cela peut être très pratique pour préparer des commandes, mais on peut envisager d'autres utilisations.

    tableau t1 'a b' 'c d' e f
    tabforeach t1 'tabajoute t2 -e'
    tabmix c t2 t1
    tabaffiche c
    c[0] = '-e'
    c[1] = 'a b'
    c[2] = '-e'
    c[3] = 'c d'
    c[4] = '-e'
    c[5] = 'e'
    c[6] = '-e'
    c[7] = 'f'
    grep "${c[@]}"
    # produit la commande grep -e 'a b' -e 'c d' -e d -e f
    

    tabsep

    tabsep src t1 [t2 ... tn]

    tabsep est la réciproque de tabmix. Elle sépare src en n, en plaçant alternativement les éléments de src dans t1, t2, ... tn

    tabsauve

    tabsauve tab [nom] >fichier

    tabsauve affiche des lignes permettant de recharger le tableau tab grace à la commande tableau.

    On peut enregistrer le tableau sous un autre nom si un second paramètre est donné.

    C'est de la responsabilité du programmeur de rediriger la sortie de cette fonction vers un fichier.

    tableau a "a bcd ' ef" ijkl 'coucou les amis'
    tabsauve a
    produit cela
    tableau a \
            'a bcd '\'' ef'\
            'ijkl'\
            'coucou les amis'\
    
    
    tabsauve a abis      
    produit cela
    tableau abis \
            'a bcd '\'' ef'\
            'ijkl'\
            'coucou les amis'\
    
    


    Retour table des matières

    liboption.scl

    Analyse des options de la ligne de commande. Supporte les options longues (abrégées ou non), courtes "à la tar". Chaque option accepte 0, 1, 2 ... n paramètres, ou de n à m paramètres, ou bien encore un nombre variable de paramètres (à la find -exec).

    utilisation et initialisation

    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libkwubst.scl
    . $LIBSHDIR/libmaniptab.scl
    . $LIBSHDIR/liboption.scl
    

    utilise

  • globale :
    typeset
  • définit

  • globale :
  • OCarg
    renseigné par fonction
    OCgetopt, contient le(s) paramètre(s) de l'option reconnue,
  • OCargsused
    renseigné par fonction OCgetopt, quand l'analyse est terminée, contient le nombre de mots utilisés, (ie à la fin de l'analyse des paramètres de la ligne de commande, on peut utiliser shift $OCargsused ; les paramètres restant alors ne sont pas des options),
  • OCmsg_err
    renseigné par fonction OCgetopt, en cas d'erreur, contient le message d'erreur.
  • fonctions :
  • OCaccepte_option
  • OCaccepte_option_t
  • OCraz
  • OCgetopt
  • OCchange_option
  • description

    Les fonctions OC* ont pour but de gérer facilement les options longues et courtes dans un script.

    Le lecteur pressé habitué a getopt et consort pourra passer directement à un exemple complet. Sinon, cet exemple est détaillé dans les paragraphes qui suivent.

    Cette bibliothèque a les propriétés suivantes

  • Toute option courte a une option longue correspondante
  • les options courtes peuvent être concaténées "à la tar"
    tar -cbvf 40 /dev/rmt/0hn /un/repertoire
    Le 40 va avec le b et /dev/rmt/0hn avec f
  • les options longues peuvent être abrégées jusqu'à 2 lettres, pourvue que l'abréviation reste non ambiguë
  • les paramètres des options longues s'écrivent indifférement
    --option-longue=param1 param2....
    ou
    --option-longue param1 param2....
  • le mot « -- » s'il est utilisé en tant qu'option (pas en tant que paramètre d'option) termine les options, les mots suivants ne sont plus analysés même s'il commencent par un signe '-'. Comme on y est habitué sous unix, ce mot sera complètement ignoré. (Il sera compté dans la variable OCargsused)
  • le mot « - » s'il est utilisé en tant qu'option (pas en tant que paramètre d'option) termine les options, les mots suivants ne sont plus analysés même s'il commencent par un signe '-'. Comme on y est habitué sous unix, ce mot sera pris en compte par le script. (Il ne sera pas compté dans la variable OCargsused)
  • possibilité d'utiliser des options numériques génériques :
    prenons un exemple pour comprendre.
    Un script traite des livres et a donc une option --page=Numero ou -p Numéro. Plutot que d'utiliser l'option courte -p, on peut directement utiliser -Numéro comme option courte correspondant à --page. On peut ainsi exécuter le programme avec les «options» -1, -123 -2535647 etc...

    Si ce comportement est désiré, il n'est plus possible d'utiliser des chiffres seuls comme option courte. Que signifierait -12 alors ?
  • Les options peuvent accepter un nombre quelconque mais fixé de paramètres, par exemple
    un_script --troisD x y z
  • Les options peuvent accepter un nombre variable de paramètres, délimités par un symbole donné (à la find -exec)
    par exemple :
    un_script --type carre x y longueur_coté . --coul=bleu
    un_script --type rectangle x y largeur hauteur . --coul=bleu
    La bibliothèque se charge de trouver et d'éliminer le caractère de délimitation.
  • Les options peuvent accepter un nombre variable de paramètres, sans délimiteur mais les nombres minimum et maximum de paramètres est fixé.
    par exemple, l'option --type attend exactement 4 ou 5 paramètres (remarquez l'absence du délimiteur (.) dans ce cas :
    un_script --type carre x y longueur_coté --coul=bleu
    un_script --type rectangle x y largeur hauteur --coul=bleu
    Si le minimum est 0 et le maximum est 1, on a alors un paramètre optionnel.
  • Ce qu'on ne peut pas faire avec cette bibliothèque, ou pas faire facilement.

  • Avoir des options longues sans options courtes
  • la programmation pour sa part est très simple. On commence par déclarer les options que le programme accepte avec la fonction OCaccepte_option (ou OCaccepte_option_t si on a la liste des options valables dans un tableau). On utilise alors OCgetopt dans une boucle pour analyser les options. En cas d'erreur un message est prévu dans la variable OCmsg_err ; vous pouvez l'afficher. Si la ligne de commande ne comporte pas d'erreur, le nombre d'éléments analysés est alors contenu dans la variable OCargsused

    Si l'on veut tester un nouveau jeu d'option, sans changer les options que le programme accepte, il faut appeler OCraz qui remet l'automate de reconnaissance des options dans son état initial.

    Il n'est pas nécessaire d'appeler OCraz si les options acceptées par le programe sont changées grace à un appel à OCaccepte_option.

    Chaque option, longue ou courte, peut avoir plusieurs forme. Cela peut servir à maintenir la compatibilité entre différentes versions d'un script, ou à d'autre chose.

    OCaccepte_option

    Cette fonction déclare les options qu'il faut reconnaitre et initialise l'automate de reconnaissance d'option. Elle doit recevoir un nombre de paramètres multiple de trois.

    • Le premier paramètre de chaque triplet est l'option courte à reconnaitre.
      L'option courte est en fait un modèle pour l'ordre interne case. Ainsi il est possible d'avoir plusieurs lettres correspondant à la même option (compatibilité avec les différentes versions de vore script).
      Pour utiliser des caractères spéciaux comme options comme ?, *, ou # il faut utiliser une barre oblique inverse ET des apostrophes (voir l'exemple ci-dessous).
      Pour utiliser les options numériques génériques, il faut préciser « num » comme option courte. Le nombre de paramètre est alors ignoré (puisque le nombre est en fait un paramètre de l'option). On ne peut plus alors utiliser les chiffres comme option. OCgetopt renverra toujours 'num'.
    • Le second est la forme longue de l'option.
      L'option longue est une série de mot séparés par une barre verticale (|). Chacun des mots est une des formes possibles de l'option longue.
    • Le troisième est le nombre de paramètres dont l'option a besoin.
      Dans le cas d'option numérique générique (option courte = num) ce nombre est ignoré puisque l'option numérique générique est son propre, seul et unique paramètre.

      Si ce paramètre a la forme nombre_1-nombre_2, cela indique que l'option a nombre_1 paramètres obligatoires et accepte éventuèlement jusqu'à nombre_2 paramètres. Dans ces paramètres optionnels, le signe moins (-) est considéré comme l'un des paramètres. Toute autre chaîne commençant par le symbole moins (-) termine la liste des paramètres optionnels.

      Si ce paramètre à la forme +chaine où chaine ne commence pas par un chiffre, alors l'option acceptera un nombre variable de paramètres. Le premier mot de la ligne de commande égal à chaine indiquera la fin des paramètres.

      OCaccepte_option bla bla bla ....
      est equivallent à :
      OCchange_option bla bla bla ....
      OCraz

    exemple
    OCaccepte_option o      output            1 \
    		 p      position-3d       3 \
    		 'k|f'  'key|field|champ' 1 \
    		 '\#'   number            1 \
    		 '\?|h' 'help|aide|hilf'  0 \
    		 num    sgrouic           0 \
    		 a	alea              2-5 \
    		 e      execute           +:
    		

    OCaccepte_option_t

    Comme accepte_option, mais cette fonction prend en parametre un nom de variable de type tableau qui contient les options.

    OCgetopt

    C'est la fonction qui controle la boucle sur les options. elle analyse les options, fixe le message d'erreur éventuel, l'option trouvée, ses paramètres et le nombre de mots utilisé lors de l'analyse.

    Elle doit être appelée avec la même séquence de paramètre jusqu'à ce que l'analyse soit terminée ou jusqu'à ce que OCraz soit appelée.

    Elle prend en paramètre le nom d'une variable qui contiendra l'option découverte et la série de mots que l'on veut analyser.
    Si l'analyse réussi, cette variable contiendra un des symbols correspondant à l'une des options courtes, même si on a rencontré une option longue.

    Si l'analyse échoue, cette variable est vide au retour de la fonction.

    Si cette variable contient 'num', alors on a rencontré une option numérique générique et la variable OCarg est garantie ne contenir que des chiffres.

    Les paramètres de l'option sont contenus dans la variable OCarg. Cette variable est un tableau si elle doit contenir plusieurs arguments. une variable scalaire sinon.

    Si on traite une option avec nombre de paramètres variable, le délimiteur n'est pas présent dans le tableau OCarg.

    Si une option courte a plusieurs formes (comme 'k|f' dans l'exemple ci dessus), OCgetopt est suceptible de retourner n'importe laquelle des formes possibles.
    En ayant utilisé OCaccepte_option comme dans l'exemple ci dessus, alors « OCgetopt option -h », « OCgetopt option '-?' » et « OCgetopt option --aide » fixeront tous les trois la variable option soit à 'h', soit à '?'.

    Le code de retour de la fonction est 0 si une option a pu être reconnue, ou s'il y a eu une erreur. Le code est 1 lorsqu'il n'y a plus d'options à reconnaitre.

    Elle s'utilise normalement de la manière suivante

    while OCgetopt option "$@"
    do
    	case "$option" in
    	o)
    		outputfile=$OCarg
    	;;
    	p)
    		x=${OCarg[0]} y=${OCarg[1]} z=${OCarg[2]}
    	;;
    	f|k)
    		field=$OCarg
    	;;
    	\#)
    		number=$OCarg
    		if test $(( ( number / 2 ) * 2 + number % 2 )) != $number 2>/dev/null
    		then
    			echo "$number n'est pas un nombre" >&2
    			exit
    		fi
    	;;
    	\?|h)
    		usage
    		exit
    	;;
    	num)
    		sgrouic=$OCarg
    	;;
    	e)
    		# tabaffiche OCarg
    		faire_qqchose "${OCarg[@]}"
    	;;
    	a)
    		arg_variable "${OCarg[@]}"
    	;;
    	*)
    		echo "$OCmsg_err" >&2
    		exit 1
    	;;
    	esac
    done
    shift $OCargsused
    # Les arguments restant ne sont pas des options.
    printf 'voila les arguments restants qui ne sont pas des options :\n'
    printf '\t--|%s|--\n' "$@"
    

    OCraz

    Permet de redémarrer une analyse d'option.
    Lorsqu'on veut analyser plusieurs fois les options, doit être appelée avant de refaire une boucle «while OCgetopt option "$@"»
    exemple

    ok=0
    while test 0 = "$ok"
    do
    	ok=1
    	echo "Ceci est une simulation "
    	printf 'Entrez les options pour le programme « bloundje » '
    	read ligne
    	OCraz
    	while OCgetopt option $ligne
    	do
    		if test '' = "$option"
    		then
    			ok=0
    			echo "vous avez fait une erreur.... voila le message"
    			echo "$OCmsg_err"
    			break
    
    		fi
    	done
    done
    echo "B R A V O !"
    echo "Vous avez réussi la simulation avec succès"
    

    OCchange_option

    Cette fonction, déclarée dans ce fichier est utilisée de manière interne par OCaccepte_option. Normalement, il n'est pas nécessaire de savoir ce qu'elle fait ni à quoi elle sert, mais si vous voulez vraiment entrer dans la quatrième dimension, lisez la documentation de libexoption.scl, qui documente des fonctionalités du coté obscur des options.


    Un exemple complet de OCgetopt

    #! /votre/shell
    
    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libkwubst.scl
    . $LIBSHDIR/libmaniptab.scl
    . $LIBSHDIR/liboption.scl
    
    function faire_qqchose {
    	echo faire_qqchose a recu $# parametres
    	test "$*" && {
    		echo les voila :
    		printf '\t--|%s|--\n' "$@"
    	}
    }
    
    function troisd {
    	echo "Captaine Kirk :
    	Coefficient Espace temps $1.$2 -$3"
    }
    arg_variable() {
    	echo "arg_variable a recu $# parametres que voila"
    	printf '\t--|%s|--\n' "$@"
    }
    
    OCaccepte_option o      output            1 \
    		 p      position-3d       3 \
    		 'k|f'  'key|field|champ' 1 \
    		 '\#'   number            1 \
    		 '\?|h' 'help|aide|hilf'  0 \
    		 num    sgrouic           0 \
    		 a	alea              2-5 \
    		 e      execute           +:
    
    while OCgetopt option "$@"
    do
    	case "$option" in
    	o)
    		outputfile=$OCarg
    		echo "outputfile=$OCarg"
    
    	;;
    	p)
    		x=${OCarg[0]} y=${OCarg[1]} z=${OCarg[2]}
    		troisd "${OCarg[@]}"
    	;;
    	f|k)
    		field=$OCarg
    		echo "field=$OCarg"
    	;;
    	\#)
    		number=$OCarg
    		if test $(( ( number / 2 ) * 2 + number % 2 )) != $number 2>/dev/null
    		then
    			echo "$number n'est pas un nombre" >&2
    			exit
    		fi
    		echo "number=$OCarg"
    	;;
    	\?|h)
    		usage
    		exit
    	;;
    	num)
    		sgrouic=$OCarg
    		echo "sgrouic=$OCarg"
    	;;
    	e)
    		# tabaffiche OCarg
    		faire_qqchose "${OCarg[@]}"
    	;;
    	a)
    		arg_variable "${OCarg[@]}"
    	;;
    	*)
    		echo "$OCmsg_err" >&2
    		exit 1
    	;;
    	esac
    done
    shift $OCargsused
    # Les arguments restants ne sont pas des options.
    printf 'voila les arguments restants qui ne sont pas des options :\n'
    printf '\t--|%s|--\n' "$@"
    

    essayez ce script de la manière suivante :

    le_script -10 --alea 2 zouip click brrr --posit=1 2 3 -o10e18#epe fichier a b c '   d    e' f : 890 : 4 5 6 ABC D : --fie Zblounge I J K L
    

    Retour table des matières

    libexoption.scl

    Fonctionallités rarement utilisées du système de gestion d'options. Comment changer les options acceptées par le script pendant l'analyse des options de la ligne de commande et autres bizarreries.

    utilisation et initialisation

    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libkwubst.scl
    . $LIBSHDIR/libmaniptab.scl
    . $LIBSHDIR/liboption.scl
    . $LIBSHDIR/libexoption.scl
    

    utilise

  • globale :
    typeset
  • définit ou change

  • globale :
  • OCargsused
    mémorisé par fonction OCobtient_co, Changé par fonction OCplace_co.
  • fonctions :
  • OClongue_vers_courte
  • OCchange_option
  • OCobtient_co
  • OCplace_co
  • OCdetruit_co
  • description

    Les fonctions OC* ont pour but de gérer facilement les options longues et courtes dans un script.

    Ces fonctions présentent des fonctionnalités rarement utilisées car très contre-nature (he oui, même l'informatique a un aspect naturel), comme par exemple la possibilité de changer la liste d'options acceptées par le script pendant l'analyse des options de la ligne de commande, ou dont on a rarement besoin, comme de savoir quelle option courte correspond à un mot supposé représenter une forme d'option longue.

    OClongue_vers_courte mot nom_variable

    Cette fonction fait presque le même travail que OCgetopt mais uniquement pour les options longues et ne s'occupe pas des paramètres.
    Son but exact est d'essayer de trouver quelle option courte pourrait bien correspondre à une supposée option longue. Le résultat est mis dans la variable passé en second paramètre.

    mot peut commencer par deux signes moins «--», mais ce n'est pas nécessaire.

    La variable OCmsg_err est positionnée si le mot ne correspond pas à une option longue, et la variable nom_variable aura une valeur nulle après l'appel a cette fonction.
    exemple

    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libkwubst.scl
    . $LIBSHDIR/libmaniptab.scl
    . $LIBSHDIR/liboption.scl
    
    OCaccepte_option o      output           1 \
    		 p      position-3d      3 \
    		 'k|f'  'key|field'      1 \
    		 '\#'   number           1 \
    		 '\?|h' 'help|aide|hilf' 0 \
    		 num    sgrouic          0
    
    x=--po=34
    OClongue_vers_courte "$x" opt
    if test '' != "$opt"
    then
    	echo "l'option courte correspondant à --|$x|-- est
    --|$opt|--"
    else
    	echo "le mot --|$x|-- n'est pas une option longue, il n'y
    a pas d'option courte associée (bien sur) et l'erreur est
    --|$OCmsg_err|--"
    fi
    		

    OCchange_option court long nombre [court long nombre...]

    Cette fonction permet de changer la liste des options valides sans affecter l'analyse en cours.

    Ses paramètres sont identiques à OCaccepte_option

    je ne donne aucun exemple ici, car on ne comprendrait pas trop le sens.

    OCobtient_co OCplace_co OCdetruit_co

    OCobtient_co nom_contexte
    OCplace_co nom_contexte
    OCdetruit_co nom_contexte
    

    Ces trois fonctions gerent des contextes d'options. Un contexte rassemble tout ce qui est nécessaire à la gestion des options : La liste des options valides et l'état de l'automate de reconnaissance des options.
    Cela permet de d'analyser des options, et alors que l'analyse des options n'est pas terminée d'analyser une autre série d'option avec des paramètres différents, et de reprendre la première analyse là où on l'a abandonnée.

    Le parametre nom_contexte est un nom arbitraire, qui doit respecter les regles du shell concernant les noms de variable.

    OCobtient_co nom
    crée un contexte à partir de l'état de l'automate de reconnaissance des options.

    OCdetruit_co nom
    Détruit un contexte précédement créé

    OCplace_co nom
    Replace l'automate de reconaissance d'option dans l'état ou il était lors de la création du contexte.

    Exemple:
    Un script qui fait bip, accepte comme option une chaine de caractère se trouvant justement être une série d'options pour une seconde commande (que le premier script est sensé utiliser):

    #! /mettez/votre/shell/ici
    #
    #
    LIBSHDIR=/usr/local/lib
    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libkwubst.scl
    . $LIBSHDIR/libmaniptab.scl
    . $LIBSHDIR/liboption.scl
    . $LIBSHDIR/libexoption.scl
    
    # Analyse des options imbriquées :
    function analyse_autre_opt {
    	$typeset o
    	OCaccepte_option j bzip2 0 z 'gzip|ungzip' 0 c create 0 \
    		t list 0 \
    		x 'extract|get' 0 \
    		f file 1 \
    		b blocking-factor 1 \
    		v verbose 0
    	while OCgetopt o "$@"
    	do
    		# case "$o" in
    		# [txfbvjzc])
    		#	: ok
    		# ;;
    		# *)
    		#	echo "erreur dans autre options : $OCmsg_err >&2
    		#	exit 1
    		# ;;
    		# esac
    		if test '' != "$OCmsg_err"
    		then
    			echo "Erreur dans les autres options :$OCmsg_err" >&2
    			exit 1
    		fi
    	done
    }
    
    OCaccepte_option \
    	t tar +. \
    	o fichier-de-sortie 1 \
    	i fichier-d-entree 1
    while OCgetopt option "$@"
    do
    	case "$option" in
    	o)
    		sortie=$OCarg
    	;;
    	i)
    		entree=$OCarg
    	;;
    	t)
    		OCobtient_co avant
    		analyse_autre_opt "${OCarg[@]}"
    		OCplace_co avant
    	;;
    	*)
    		echo "Erreur : $OCmsg_err" >&2
    		exit 1
    	;;
    	esac
    done
    shift $OCargsused
    
    Maintenant, en supposant que ce script s'appelle «le_script» testez le avec la commande suivante :
    le_script --fichier-d-en=/tmp/blibli -t -jcvfb /dev/rmt/0hn 40 . -o /tmp/tutu
    
    ou avec une erreur dans une des options pour la commande tar.
    le_script --fichier-d-en=/tmp/blibli -t -jcvkfb /dev/rmt/0hn 40 . -o /tmp/tutu
    

    Retour table des matières

    libsystem.scl

    Diverses fonctions système. mode de fichier, propriétaire, périphérique correspondant à un dossier etc...

    utilisation et initialisation

    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libsystem.scl
    

    utilise

  • globale :
    typeset
  • définit

  • globale :
  • fonctions :
  • filemode
  • fileowner
  • get_directory_dev
  • get_directory_mountpoint
  • description

    Ces fonctions ne sont pas particulièrement difficiles à écrire, mais leur fréquence d'utilisation justifie pleinement leur présence dans cette bibliothèque. D'autre part, elles fonctionnent sous différents OS. On pourra donc se concentrer sur le problème à résoudre et non sur les spécificités de tel ou tel OS.

    filemode fichier_ou_rep

    Retourne une valeur octale correspondant au mode du fichier. Les Acl ne sont pas prises en compte, seul le mode de base.

    Si fichier_ou_rep est un lien symbolique, la valeur du lien, et non de la cible du lien est retournée.

    exemple :

    $ filemode /tmp
    1777
    $ mode=$(filemode /tmp)
    $ chmod $mode /copie/tmp
    

    fileowner fichier_ou_rep

    Affiche propriétaire:groupe de fichier_ou_rep.

    Si fichier_ou_rep est un lien symbolique, la valeur du lien, et non de la cible du lien est retournée.
    exemple :

    # prop=$(fileowner src)
    # cp src dest
    # chown $prop dest
    # chmod $(filemode src) dest
    

    get_directory_dev rep

    Affiche le périphérique où se trouve un répertoire.
    Cette fonction comence par utiliser "cd" pour se placer dans le répertoire -- cela uniquement afin de déclencher si besoin un quelconque automonteur -- puis l'ordre df sert à savoir sur quel périphérique on se trouve.

    Code de retour :
    0 si pas d'erreur
    non zéro si erreur quelconque.

    exemple:

    # dev=$(get_directory_dev /home)
    # dump -f /dev/bande_magnetique $dev
    

    get_directory_mountpoint fichier_ou_rep

    Affiche le point de montage du périphérique où se trouve un répertoire ou un fichier.
    À l'inverse de get_directory_dev cette fonction n'utilise pas "cd" pour se placer dans un répertoire et ne déclenche donc pas éventuellement l'automonteur.

    Code de retour :
    ?

    exemple:

    $ mp=$(get_directory_mountpoint $HOME)
    $ echo point de montage de $HOME : $mp
    $ mp=$(get_directory_mountpoint /usr/local)
    $ echo point de montage de /usr/local : $mp
    $ mp=$(get_directory_mountpoint /opt)
    $ echo point de montage de /opt : $mp
    

    Retour table des matières

    libquota.scl

    Obtenir et fixer les quotas de bloc pour les utilisateurs.

    utilisation et initialisation

    LIBSHDIR=/la/ou/est/la/bibliothèque
    . $LIBSHDIR/liblocal.scl
    . $LIBSHDIR/libkwubst.scl
    . $LIBSHDIR/libsystem.scl
    . $LIBSHDIR/libquota.scl
    

    utilise

  • globale :
    typeset
    LIBSHDIR
  • définit

  • globale :
  • CMlibshdir
  • CMedquota
  • fonctions :
  • get_user_block_quota
  • get_user_used_block_quota
  • set_user_block_quota
  • set_dev_user_block_quota
  • description

    Fonctions de manipulation des quotas de disque. Seuls les quotas en tailles et pas les quotas en nb d'inodes sont gérés. Ces derniers étant trop peu utilisés à ma conaissance.
    Pas de gestion de quota de groupe non plus, seulement les utilisateurs.

    Pour fixer les quotas, la technique est de créer un script qui sera utilisé pour editer les quota lors de l'exécution de "edquota".
    Cela nécessite de connaitre parfaitement le format du ficher texte. N'ayant accès qu'à deux systèmes, je n'ai pu développer que pour eux. Si vous avez la possibilité de m'envoyer un fichier à éditer lors de edquota, j'ajouterai avec plaisir d'autres scripts pour ces autres OS.

    Charger cette bibliothèque sur un système ne faisant pas partie de la liste des systèmes supportés provoque l'arret du script par exécution de exit 1

    Les scripts d'édition de fichier quota reçoivent leur paramètres par variables d'environnement. La bibliothèque sait où sont installés les scripts grâce à la variable LIBSHDIR. Cette variable est utilisée au moment où la bibliothèque est sourcée. On peut par la suite unseter cette variable ou en changer la valeur, cela n'a plus aucune importance.
    Nota :
    Les personnes utilisant le compilateur de script sc et/ou le relieur de script ld.sh n'ont pas à se soucier de fixer cette variable, le relieur s'en charge. Ces outils sont documentés à l'heure actuelle ( ven mai 6 08:03:22 CEST 2005 ) au moyen d'une page de manuel en anglais.

    Actuelement, on peut utiliser cette bibliothèque sur les systèmes suivants.

  • Solaris
  • Linux
  • MacOS X (testé sous 10.3)
  • get_user_block_quota user mountpoint

    Affiche le quota mou et dur pour l'utilisateur et le point de montage spécifié.
    exemple :

    dir=$HOME
    mp="$(get_directory_mountpoint "$dir")"
    set zapezmoi $(get_user_block_quota ${USER:-$LOGNAME} "$mp")
    shift
    if test $# = 0
    then
    	echo pas de quota pour ${USER:-$LOGNAME} sur l\'arborescence $dir
    else
    	echo limite basse : $1
    	echo limite absolue : $2
    fi
    

    get_user_used_block_quota user mountpoint

    Affiche le quota utilisé par l'utilisateur sur le point de montage spécifié. L'affichage affiche :

  • rien du tout :
    Pas de quota sur ce filesystem pour cet utilisateur.
  • Un seul nombre :
    Le nombre correspond au quota de l'utilisateur.
  • Un nombre et une étoile
    Le nombre correspond au quota de l'utilisateur.
    L'étoile indique que la limite est passée (quota -v colle l'étoile au nombre dans ce cas)
  • exemple :

    dir=$HOME
    mp="$(get_directory_mountpoint $dir)"
    set zapezmoi $(get_user_used_block_quota ${USER:-$LOGNAME} "$mp")
    shift
    if test $# = 0
    then
    	echo pas de quota pour ${USER:-$LOGNAME} sur l\'arborescence $dir
    else
    	if test $# -gt 1
    	then
    		echo utilisateur ${USER:-$LOGNAME} dépasse son quota
    	fi
    	echo quota utilisé : "$1"
    fi
    

    set_user_block_quota user mountpoint basse haute

    fixe les quotas pour l'utilisateur.

    Il faut être root pour pouvoir appeler cette fonction.

    Code de retour :
    0 : quota fixé
    non 0 : erreur lors de l'établissementdes quotas. quotas inchangé.

    ATTENTION
    Il est possible que cette fonction retourne un code d'erreur nul (indiquant une exécution correcte) dans le cas suivant :
    Un filesystem est monté avec quota, un autre est monté sans quota, on veut fixer les quota sur le filesystème sans quota.

    exemple d'utilisation :

    dir=/home
    user=un_user
    mp="$(get_directory_mountpoint $dir)"
    if set_user_block_quota $user $mp 100000 110000
    then
    	echo quota pour $user changé :
    	quota -v $user
    else
    	echo impossible de changer les quotas pour $user
    fi
    

    set_dev_user_block_quota user device basse haute

    Ne fonctionne que sous linux
    fixe les quotas pour l'utilisateur. La seule différence avec set_user_block_quota, est que cette fonction (sous linux) évite un appel à get_directory_dev. (Sous les autres OS, les quotas fonctionnent avec les points de montages, pas avec les périphériques, et cette fonction n'est donc pas utile)

    Il faut être root pour pouvoir appeler cette fonction.

    Code de retour :
    0 : quota fixé
    non 0 : erreur lors de l'établissementdes quotas. quotas inchangé.

    ATTENTION
    Même problème que fonction set_user_block_quota

    exemple :

    dir=/home
    user=un_user
    dev=$(get_directory_dev "$dir")
    if set_dev_user_block_quota $user $dev 100000 110000
    then
    	echo quota pour $user changé :
    	quota -v $user
    else
    	echo impossible de changer les quotas pour $user
    fi
    

    Annexes


    Retour table des matières

    Remarques sur dialog

    S'il existe bien trois commandes de type dialog au moins, compatible syntaxiquement, elles ont, en revanche, des comportement fort différent dès que l'on sort des classiques oui-non, input-box, ok-box et menu.

    Incompatibilité de version

    La commande dialog (ComeOn Dialog!) est incompatible avec elle même ! ainsi la version 0.9b-20040606 et la version 1.0-20050306 se comportent différement pour, au moins l'option --radiolist.
    La version 0.9b-20040606 retourne à tort le tag entouré de guillemets (") alors que la version 1.0-20050306 ne l'entoure pas. ainsi :

    dialog --radiolist 'choisissez 1 ou 2' 22 76 3 \
    	1 numero_un off  \
    	2 numero_deux off \
    	2>&1 >&3
    

    retourne dans un cas --|"1"|-- et dans l'autre --|1|-- (pas de guillemets), suivant la version. Au regard de vieux script, il apparait que de plus anciennes versions de dialog se comportaient comme les versions récentes.

    Fort heureusement, il est souvent possible d'utiliser --menu au lieu de --radiolist (car radiolist n'autorise la séléction que d'un seul élément)

    Problème de dessin et incompatibilité de programme

    J'ai cru un moment que Xdialog pouvait être un remplaçant immédiat de dialog. Il n'en est rien. Leur comportement dans le cas de --checklist est totalement différent. L'option --checklist permet de cocher plusieurs choix dans une liste. Les commandes retournent donc une série de tag.

    Dialog renvoie les tags entourés par des guillemets et semble-t-il correctement échappés de manière à ce que cette série de valeur puisse être évaluées et correctement séparée par l'évaluation.

    a="$(
    dialog --checklist 'choisissez un ou plusieurs tag etranges' 0 0 0 \
    	0       zero off \
    	'$$'    "c'est le pid d'habitude" off \
    	'1 + 1' "Avec des espaces" off \
    	'"'     "un guillemet" off \
    	/      "C'est pour rire plus tard" off
    	'`ls`'  "une commande qui pourrait être mortelle (rm -rf??)" off \
    	'$(ls)'  "une autre commande qui pourrait etc..." off \
    	2>&1 >&3
    )"
    

    Si on sélectionne tout, la chaine obtenu en retour est :

    "0" "\$\$" "1\ +\ 1" "\"" "/" "\`ls\`" "\$\(ls\)"

    On peut à peut pret s'en sortir avec une horreur telle que :

    eval "set -- $a"
    echo "$@"
    

    mais ça ne marche pas vraiment car certains caractères sont échappés qui ne devraient pas l'être (les espace et les parenthèses)...

    bref, il faut sortir l'artillerie lourde avec sed au moins pour remettre de l'ordre dans le merdier. ou alors il faut être certain que tous les tags employés seront exclusivement alphanumérique et sans espace. Ça correspond à 99% des emplois mais si les tags sont issus du traitement d'un fichier journal ou autre.... Aïe ! ça peut exploser à tout moment.

    Xdialog de son coté ne fourni rien de comparable, ce qui rend le machin totalement incompatible avec dialog. La valeur retournée est composée de tag non échappés séparés par des slashs (/). cela à le mérite de pouvoir se traiter facilement, sauf dans le cas ou un slash est un des tags retournés, comme dans l'exemple précédent.

    On peut toutefois traiter le résultat facilement si on sait qu'on aura jamais de slash (ou nom de fichier :-/ ) comme tag :

    a="$(
    Xdialog --checklist 'choisissez un ou plusieurs tag etranges' 0 0 0 \
    0       zero off \
    '$$'    "c'est le pid d'habitude" off \
    '1 + 1' "Avec des espaces" off \
    '"'     "un guillemet" off \
    /      "C'est pour rire plus tard" off \
    '`ls`'  "une commande qui pourrait être mortelle (rm -rf??)" off \
    '$(ls)'  "une autre commande qui pourrait etc..." off \
    2>&1 >&3
    )"
    aifs=$IFS
    IFS=/
    set -- $a
    IFS=$aifs