A la découverte d'UNIX (FreeBSD)

A la découverte d'UNIX (FreeBSD)

Mis à jour le mardi 8 janvier 2013

En principe, un seul type de bureau suffit pour faire tout ce qu'on veut sur un ordinateur. Mais puisqu'UNIX vous offre de nombreuses possibilités dans ce domaine (fluxbox, KDE, GNOME, etc.) vous aurez peut-être envie de changer de temps en temps. Peut-être qu'un certain bureau vous semblera plus adapté pour travailler et un autre pour vous détendre. Ou peut-être prendrez-vous simplement plaisir à changer de décor.

Si vous avez installé gdm ou kdm, vous pouvez choisir votre type d'interface graphique dans un menu à chaque ouverture de session. Dans le cas contraire, je vous propose d'écrire vous-même un script qui vous accordera le même choix.

A - Créer le menu

Le script doit d'abord déterminer quelles sont les interfaces disponibles sur votre système, afin de ne vous proposer que celles-ci. Nous allons rechercher les interfaces suivantes : Twm, Fluxbox, KDE, LXDE, Xfce, GNOME, Enlightenment.

Vous savez que, pour lancer l'une de ces interfaces, il faut éditer votre fichier .xinitrc et y demander l'exécution d'un programme de démarrage. Ce programme dépend bien sûr de l'interface voulue :

  • Pour Twm : /usr/local/bin/twm

  • Pour Fluxbox : /usr/local/bin/startfluxbox

  • Pour KDE : /usr/local/kde4/bin/startkde

  • Pour LXDE : /usr/local/bin/startlxde

  • Pour Xfce : /usr/local/bin/startxfce4

  • Pour GNOME : /usr/local/bin/gnome-session

  • Pour Enlightenment : /usr/local/bin/enlightenment_start

La première tâche de votre script est, par conséquent, de déterminer si certains de ces fichiers sont présents sur votre système et de créer un fichier texte menuBureaux qui proposera le choix d'une des interfaces disponibles.

Pour déterminer si un fichier existe, la commande est :

if (-e nomDuFichier) instruction à exécuter si le fichier existe

Voici donc le début du script, que nous allons appeler change :

#!/bin/csh

if (-e /usr/local/bin/twm) echo 'T : Twm' >> menuBureaux
if (-e /usr/local/bin/startfluxbox) echo 'F : Fluxbox' >> menuBureaux
if (-e /usr/local/kde4/bin/startkde) echo 'K : KDE' >> menuBureaux
if (-e /usr/local/bin/startlxde) echo 'L : LXDE' >> menuBureaux
if (-e /usr/local/bin/startxfce4) echo 'X : Xfce' >> menuBureaux
if (-e /usr/local/bin/gnome-session) echo 'G : GNOME' >> menuBureaux
if (-e /usr/local/bin/enlightenment_start) echo 'E : Enlightenment' >> menuBureaux
echo "Choisissez votre interface graphique :"
cat menuBureaux

Deux petites subtilités : sur un système à plusieurs utilisateurs, vous n'aurez peut-être pas le droit d'exécuter certains de ces programmes. L'important n'est pas qu'ils existent mais que vous ayez le droit de les exécuter. Il faut donc modifier légèrement notre condition et remplacer le -e par un -x.

Voici la liste des conditions de ce genre :

  • -e : vrai si le fichier existe

  • -x : vrai si le fichier est exécutable

  • -d : vrai si le fichier est un dossier

  • -f : vrai si le fichier est un fichier normal (pas un dossier, donc)

  • -o : vrai si le fichier vous apprtient

  • -r : vrai si le fichier est lisible

  • -w : vrai si le fichier est modifiable

  • -z : vrai si le fichier est vide

Par ailleurs, si vous exécutez ce script plusieurs fois, vous allez réécrire plusieurs fois les mêmes choix dans le menu. C'est absurde. Il faut donc préciser au début du script que, si le fichier menuBureaux existe déjà, on l'efface et on recommence :

#!/bin/csh

if (-e menuBureaux) rm menuBureaux
if (-x /usr/local/bin/twm) echo 'T : Twm' >> menuBureaux
if (-x /usr/local/bin/startfluxbox) echo 'F : Fluxbox' >> menuBureaux
if (-x /usr/local/kde4/bin/startkde) echo 'K : KDE' >> menuBureaux
if (-x /usr/local/bin/startlxde) echo 'L : LXDE' >> menuBureaux
if (-x /usr/local/bin/startxfce4) echo 'X : Xfce' >> menuBureaux
if (-x /usr/local/bin/gnome-session) echo 'G : GNOME' >> menuBureaux
if (-x /usr/local/bin/enlightenment_start) echo 'E : Enlightenment' >> menuBureaux
echo "Choisissez votre interface graphique :"
cat menuBureaux

Avant d'exécuter le script pour la première fois, pensez bien à vous en accorder l'autorisation à vous-même avec la commande chmod.

Voici le résultat si seuls Twm, Fluxbox et GNOME sont installés sur votre machine :

% change
Choisissez votre interface graphique :
T : Twm
F : Fluxbox
G : GNOME

Si vous avez installé une autre interface que celles que je vous ai proposées plus haut, pensez à ajouter une ligne dans le script pour la tester également.

B - Choix par l'utilisateur

L'utilisateur doit maintenant faire son choix dans le menu qui s'affiche. Il va taper T pour Twm, G pour GNOME, etc.

On récupère sa saisie avec le symbole $< :

set choix = $<

Puis, selon ce qu'il a tapé, on édite le fichier .xinitrc. Nous allons avoir besoin de l'instruction switch, dont voici la structure :

switch($variable)
   case première valeur possible
      instruction à exécuter si la variable a la première valeur possible
      autres instructions éventuelles
   breaksw
   case deuxième valeur possible
      instruction à exécuter si la variable a la deuxième valeur possible
      autres instructions éventuelles
   breaksw
   case troisième valeur possible
      instruction à exécuter si la variable a la troisième valeur possible
      autres instructions éventuelles
   breaksw
   
   ... 

endsw

Ici, nous voulons tester la valeur de la variable choix, et prévoir un case différent pour chacun des cas prévus par le menu.

Quelles instructions mettre dans chaque case ? Il faut indiquer dans .xinitrc le programme de démarrage de l'interface voulue, puis afficher un message disant à l'utilisateur qu'on a bien enregistré son choix. Par exemple, pour le bureau LXDE, on écrira :

case L
   echo 'exec startlxde' > .xinitrc
   echo "Votre prochaine session graphique emploiera le bureau LXDE."
breaksw

Le script complet devient alors :

#!/bin/csh

if (-e menuBureaux) rm menuBureaux
if (-x /usr/local/bin/twm) echo 'T : Twm' >> menuBureaux
if (-x /usr/local/bin/startfluxbox) echo 'F : Fluxbox' >> menuBureaux
if (-x /usr/local/kde4/bin/startkde) echo 'K : KDE' >> menuBureaux
if (-x /usr/local/bin/startlxde) echo 'L : LXDE' >> menuBureaux
if (-x /usr/local/bin/gnome-session) echo 'G : GNOME' >> menuBureaux

echo 'Choisissez votre interface graphique :'
cat menuBureaux
set choix=$<

switch ($choix)
    case T
       echo 'exec twm' > .xinitrc
       echo 'Votre prochaine session graphique emploiera le gestionnaire de fenetres Twm.'
    breaksw
    case F
       echo 'exec startfluxbox' > .xinitrc
       echo "Votre prochaine session graphique emploiera le gestionnaire de fenetres Fluxbox."
    breaksw
    case K
       echo "exec /usr/local/kde4/bin/startkde" > .xinitrc
       echo 'Votre prochaine session graphique emploiera le bureau KDE.'
    breaksw
    case L
       echo 'exec startlxde' > .xinitrc
       echo "Votre prochaine session graphique emploiera le bureau LXDE."
    breaksw
    case X
       echo 'exec startxfce4' > .xinitrc
       echo "Votre prochaine session graphique emploiera le bureau Xfce."
    breaksw
    case G
       echo 'exec gnome-session' > .xinitrc
       echo 'Votre prochaine session graphique emploiera le bureau GNOME.'
    breaksw
    case E
       echo 'exec enlightenment_start' > .xinitrc
       echo 'Votre prochaine session graphique emploiera le bureau Enlightenment.'
    breaksw
endsw

C - Et si l'utilisateur se trompe ?

Qu'arrivera-t-il si l'utilisateur se trompe :( et entre n'importe quoi : un nombre, un mot, une lettre minuscule, etc. ?

Dans l'état actuel du script, il ne va rien se passer du tout. Il serait bon de prévoir cette éventualité et d'afficher alors un message d'erreur avant de reproposer le menu à l'utilisateur, tant qu'il n'a pas fait un choix correct.

Tant que... Tant que... On ne va pas utiliser un while, des fois ?

Je vois que vous avez compris le principe. :) Nous allons faire une grande boucle while pour reposer la question tant que l'utilisateur n'a pas donné une réponse satisfaisante.

Nous allons avoir besoin d'une variable choisi qui vaudra 0 au début et passera à 1 quand l'utilisateur aura fait son choix.

Par ailleurs, il faut prévoir dans le switch un cas par défaut, dont les instructions seront exécutées si aucun des case n'est valable. La structure du switch devient donc :

switch($variable)
   case première valeur possible
      instruction à exécuter si la variable a la première valeur possible
      autres instructions éventuelles
   breaksw
   case deuxième valeur possible
      instruction à exécuter si la variable a la deuxième valeur possible
      autres instructions éventuelles
   breaksw
   case troisième valeur possible
      instruction à exécuter si la variable a la troisième valeur possible
      autres instructions éventuelles
   breaksw
   
   ... 
   
   default
      instruction à exécuter si la variable n'a aucune des valeurs prévues
      autres instructions éventuelles
   breaksw
endsw

Et le script, lui, devient :

#!/bin/csh

#Création du menu

if (-e menuBureaux) rm menuBureaux
if (-x /usr/local/bin/twm) echo 'T : Twm' >> menuBureaux
if (-x /usr/local/bin/startfluxbox) echo 'F : Fluxbox' >> menuBureaux
if (-x /usr/local/kde4/bin/startkde) echo 'K : KDE' >> menuBureaux
if (-x /usr/local/bin/startlxde) echo 'L : LXDE' >> menuBureaux
if (-x /usr/local/bin/gnome-session) echo 'G : GNOME' >> menuBureaux

#Initialisation de "choisi" et début de la boucle principale.
set choisi = 0

while ($choisi == 0)

   #Échange avec l'utilisateur
   echo 'Choisissez votre interface graphique :'
   cat menuBureaux
   set choix=$<
   set choisi = 1
   
   #En fonction du choix de l'utilisateur
   switch ($choix)
       case T
          echo 'exec twm' > .xinitrc
          echo 'Votre prochaine session graphique emploiera le gestionnaire de fenetres Twm.'
       breaksw
       case F
          echo 'exec startfluxbox' > .xinitrc
          echo "Votre prochaine session graphique emploiera le gestionnaire de fenetres Fluxbox."
       breaksw
       case K
          echo "exec /usr/local/kde4/bin/startkde" > .xinitrc
          echo 'Votre prochaine session graphique emploiera le bureau KDE.'
       breaksw
       case L
          echo 'exec startlxde' > .xinitrc
          echo "Votre prochaine session graphique emploiera le bureau LXDE."
       breaksw
       case X
          echo 'exec startxfce4' > .xinitrc
          echo "Votre prochaine session graphique emploiera le bureau Xfce."
       breaksw
       case G
          echo 'exec gnome-session' > .xinitrc
          echo 'Votre prochaine session graphique emploiera le bureau GNOME.'
       breaksw
       case E
          echo 'exec enlightenment_start' > .xinitrc
          echo 'Votre prochaine session graphique emploiera le bureau Enlightenment.'
       breaksw

       #Cas par défaut
       default
          echo "Choisissez l'une des interfaces proposees en tapant la majuscule correspondante."
          set choisi = 0
          #On remet "choisi" à 0 pour relancer la boucle while
       breaksw
   endsw
end

#Quand tout est fini, on affiche le nouveau contenu de .xinitrc
echo "Voici votre nouveau fichier .xinitrc :"
cat .xinitrc

Tous les cas du switch doivent faire passer choisi à 1 sauf le dernier. Je le mets donc à 1 avant le switch et ne le repasse à 0 que dans le cas default.

À la fin, on présente à l'utilisateur le nouveau contenu de .xinitrc. La prochaine fois qu'il lancera l'environnement X.org (avec startx, avec SLiM ou avec xdm), il aura l'interface choisie. S'il utilise gdm ou kdm, le choix fait ici deviendra le choix par défaut.

Dans son état actuel, ce script présente encore un défaut. Si l'utilisateur demande une interface qui n'est pas présente sur son système, .xinitrc sera modifié de façon à tenter de lancer cette interface. Et ça ne fonctionnera pas. Il faut arranger ça en mettant des if(-x ) dans les case. Cela modifie aussi la manière de gérer la variable choisi.

Je vous laisse chercher la solution comme des grands. ;)

D - Les tableaux

Il y a plusieurs instructions répétitives dans ce script et on peut simplifier tout cela en utilisant des tableaux.

Un tableau est un peu comme une variable, à la différence près qu'il comporte plusieurs cases. Par exemple, on peut définir un tableau nom regroupant les noms de toutes ces interfaces graphiques :

set nom = (Twm Fluxbox KDE LXDE Xfce GNOME Enlightenment)

Vous le voyez, un tableau se remplit avec set, comme pour une variable simple, mais on utilise des parenthèses pour regrouper ses différentes cases. Ici, nous avons un tableau de 7 cases. Pour afficher le contenu de l'une d'elles :

echo $nom[4]

Cette instruction affiche le contenu de la 4ème case du tableau, c'est-à-dire LXDE.

Et pour afficher la totalité du tableau (sans les parenthèses) :

echo $nom

De la même manière, on peut définir un tableau pour la lettre représentant chaque interface et un autre pour la commande qui la lance. Comme toutes ces commandes commencent par /usr/local/, il n'est pas utile de répéter cette partie :

set lettre = (T F K L X G E)
set commande = (bin/twm bin/startfluxbox kde4/bin/startkde bin/startlxde bin/startxfce4\
bin/gnome-session bin/enlightenment_start)

Comme le tableau commande est assez long, on ne peut pas tout faire tenir sur une seule ligne. On utilise donc le caractère \, qui signifie qu'on continue une instruction à la ligne suivante.

Du coup, au début du script, on peut remplacer les lignes :

if (-x /usr/local/bin/twm) echo 'T : Twm' >> menuBureaux
if (-x /usr/local/bin/startfluxbox) echo 'F : Fluxbox' >> menuBureaux

par

if (-x /usr/local/$commande[1]) echo "$lettre[1] : $nom[1]" >> menuBureaux
if (-x /usr/local/$commande[2]) echo "$lettre[2] : $nom[2]" >> menuBureaux

Cette fois-ci, il faut obligatoirement utiliser des guillemets " " après echo, et pas des apostrophes ' '. Regardez la différence :

echo "$lettre[1] : $nom[1]"
echo '$lettre[1] : $nom[1]'

Ce code affiche :

T : Twm
$lettre[1] : $nom[1]

Nous pouvons maintenant réécrire le début du script : la création du fichier menuBureaux.

#!/bin/csh

#Definition des tableaux
set nom = (Twm Fluxbox KDE LXDE Xfce GNOME Enlightenment)
set lettre = (T F K L X G E)
set commande = (bin/twm bin/startfluxbox kde4/bin/startkde bin/startlxde bin/startxfce4\
bin/gnome-session bin/enlightenment_start)
                                      
#Creation du menu
if (-e menuBureaux) rm menuBureaux

foreach i (1 2 3 4 5 6 7)
   if (-x /usr/local/$commande[$i]) echo "$lettre[$i] : $nom[$i]" >> menuBureaux
end

Par la même occasion, on peut en profiter pour créer un tableau disponible, dans lequel on enregistrera si chaque interface est disponible ou pas sur votre système. Essayez de modifier le code vous-mêmes.

#!/bin/csh

#Definition des tableaux
set nom = (Twm Fluxbox KDE LXDE Xfce GNOME Enlightenment)
set lettre = (T F K L X G E)
set commande = (bin/twm bin/startfluxbox kde4/bin/startkde bin/startlxde bin/startxfce4\
bin/gnome-session bin/enlightenment_start)
set disponible = (0 0 0 0 0 0 0)

#Creation du menu
if (-e menuBureaux) rm menuBureaux

foreach i (1 2 3 4 5 6 7)
   if (-x /usr/local/$commande[$i]) then
      echo "$lettre[$i] : $nom[$i]" >> menuBureaux
      set disponible[$i] = 1
   endif
end

Si vous avez Twm, Fluxbox et GNOME, le tableau disponible contiendra alors : 1 1 0 0 0 1 0. Vous pouvez vérifier avec echo $disponible, si vous voulez. Ce tableau va nous être très utile dans la suite du script.

Ensuite, l'utilisateur fait son choix :

#Echange avec l'utilisateur
set choisi = 0

while ($choisi == 0)
   echo "Choisissez votre interface graphique :"
   cat menuBureaux
   set choix=$<

   ...

end

L'utilisateur tape alors une lettre. Il faut vérifier si celle-ci correspond à l'une des cases du tableau lettre et récupérer le numéro de cette case. Pour ça, on se sert d'une boucle foreach :

foreach i (1 2 3 4 5 6 7)
   if (lettre[$i] == $choix && disponible[$i] == 1) then
      set choisi = 1
      echo "exec /usr/local/$commande[$i]" > .xinitrc
      echo "Votre prochaine session emploiera l'interface graphique $nom[$i]."
  endif
end

Là, il y a deux conditions dans le if, séparées par le symbole &&, qui signifie ET.

  • Première condition : le contenu de la case i du tableau lettre correspond à ce que l'utilisateur a tapé.

  • Seconde condition : l'interface i est disponible, d'après le tableau disponible.

Les instructions suivant le then sont exécutées uniquement si les deux conditions sont vraies. Si on veut exécuter une série d'instruction dès que l'une des deux conditions est vraie, il faut les séparer par le symbole ||, qui signifie OU.

Si on veut continuer à distinguer "gestionnaire de fenêtres" et "bureau" dans le message de la ligne 5, il faut introduire une nouvelle variable et un test supplémentaire :

foreach i (1 2 3 4 5 6 7)
  if ($lettre[$i] == $choix && $disponible[$i] == 1) then
      set choisi = 1
      if ($i < 3) then
         set interface = "gestionnaire de fenetres"
      else
         set interface = "bureau"
      endif
      echo "exec /usr/local/$commande[$i]" > .xinitrc
      echo "Votre prochaine session emploiera le $interface $nom[$i]."
  endif
end

Si $i < 3, c'est que l'utilisateur a choisi Twm ou Fluxbox, qui sont des gestionnaires de fenetres. Sinon, c'est qu'il a choisi un bureau.

Maintenant que ces problèmes sont réglés, on peut remettre la boucle while, au cas où l'utilisateur taperait n'importe quoi ou demanderait une interface non disponible.

Le script complet est alors :

#!/bin/csh

#Definition des tableaux
set nom = (Twm Fluxbox KDE LXDE Xfce GNOME Enlightenment)
set lettre = (T F K L X G E)
set commande = (bin/twm bin/startfluxbox kde4/bin/startkde bin/startlxde bin/startxfce4\
bin/gnome-session bin/enlightenment_start)
set disponible = (0 0 0 0 0 0 0)

#Creation du menu
if (-e menuBureaux) rm menuBureaux

foreach i (1 2 3 4 5 6 7)
   if (-x /usr/local/$commande[$i]) then
      echo "$lettre[$i] : $nom[$i]" >> menuBureaux
      set disponible[$i] = 1
   endif
end

#Echange avec l'utilisateur
set choisi = 0   

echo "Choisissez votre interface graphique :"
cat menuBureaux
set choix=$<

#Modification de .xinitrc
while ($choisi == 0)
   foreach i (1 2 3 4 5 6 7)
      if ($lettre[$i] == $choix && $disponible[$i] == 1) then
         set choisi = 1
         if ($i < 3) then
            set interface = "gestionnaire de fenetres"
         else
            set interface = "bureau"
         endif
         echo "exec /usr/local/$commande[$i]" > .xinitrc
         echo "Votre prochaine session emploiera le $interface $nom[$i]."
      endif
   end
end
echo "Voici votre nouveau fichier .xinitrc :"
cat .xinitrc

Comme il y a plusieurs boucles et conditions imbriquées, les indentations sont maintenant indispensables pour s'y retrouver.

Découvrez aussi ce cours en...

Exemple de certificat de réussite
Exemple de certificat de réussite