Programmation système : Présentation du Mini-Shell amélioré

Mecredi 30 novembre 2022

Par Sylvain Chiron, Université de Bordeaux, Licence 3 Informatique groupe A42

Les scripts hébergés sur ce site sont sous licence AGPL v3.

Téléchargez l’archive du projet

Cliquez sur le nom du fichier source en haut des extraits de code pour voir le fichier complet.

Utilisez les flèches ← et → pour changer de diapositive.

En l’absence de clavier, cliquez sur le titre pour faire apparaitre des boutons fléchés.

Le fichier de construction (Makefile) : cinq nouveaux modules

Comme vous le verrez dans cette présentation, j’ai modifié tous les fichiers du projet. Je n’en ai épargné aucun.


   

Le fichier d’analyse syntaxique CmdParsing.l

Objectif principal des modifications : permettre à l’analyseur d’accepter davantage de caractères sans altérer sa visée initiale de fournir des paramètres prêts à être utilisés.

L’analyseur d’origine n’acceptait que deux formes de paramètres (même si on les collait, c’était considéré comme plusieurs paramètres) :

Remarques (défauts par rapport à Bash) :


      

Faites vos tests ! Mettez en forme vos paramètres et regardez ce qui apparait entre crochets. Puis comparez avec le comportement de Bash.

echo # abc
echo#
echo \# "#"
echo "#"
echo \
echo \\
echo 1 2 1\ 2 "1 2" 1" "2
echo `
echo "
echo "`" "\""
echo `"` `\` `\"`
echo \\\"\& '\\"&'
...
      

Le fichier d’analyse syntaxique CmdParsing.y

Défauts par rapport à Bash : les redirections de descripteurs de fichiers sont évaluées de droite à gauche (comme s’il y avait des parenthèses) et doivent forcément être après tous les paramètres (alors que Bash les accepte n’importe où dans la liste des paramètres).


      

Expérience : essayez echo; echo && echo & sans puis avec la modification de priorité de ;.

Le module principal : Shell

Dans l’entête :


      

Dans le fichier source :

Le module Expression : types pour les expressions et leurs paramètres

J’ai déplacé dans ce module ce qui concerne le type Expression.


      

   

Le module Proc : gestion des processus et des signaux

Dans l’entête :


      

Dans le fichier source :

Défaut par rapport à Bash : envoyer SIGTERM sur un processus enfant stoppé n’arrête pas ce dernier immédiatement.

Essayez de lancer des commandes de toutes sortes et de les interrompre ou les stopper avec Ctrl+C ou Ctrl+Z.

Le module Evaluation : évaluation des expressions

Dans l’entête :


      

Dans le fichier source :

Défauts par rapport à Bash :

Amusez-vous ! Regardez ce qui se passe quand vous exécutez les commandes suivantes, et quand vous les interrompez ou les stoppez, ou les exécutez en arrière-plan.

ls | (sleep 3 && cat) | cat -n
echo >& 3 3> file.txt
...
      

Le module Jobs : gestion des tâches de fond

J’ai déplacé les fonctions de gestion des tâches de fond dans ce module.

Dans l’entête :


      
      

Différences par rapport à Bash :

Le module Display : affichage des expressions

Il y a bien entendu des défauts par rapport à Bash dans la linéarisation des expressions : les parenthèses ne sont plus telles quelles (elles sont rajoutées artificiellement pour le respect de l’ordre des opérations reçu) et les caractères d’échappement (barres obliques inversées et guillemets : \"') ne sont pas remis.

Le module InternalCommands : commandes spéciales

Dans l’entête :


      

Dans le fichier source :

Quelques différences par rapport à Bash :

Maintenant, il est temps de s’amuser avec ces commandes ! Mini-Shell n’affiche pas automatiquement le répertoire de travail ; vous devez utiliser la commande pwd pour obtenir le chemin.

Le module ArgsParsing : traitement avancé des commandes

On peut voir dans l’entête que le module propose quatre fonctions : l’une (setEnvValues) lit dans les paramètres des instructions pour modifier l’environnement, les trois autres transforment les paramètres.


      

La fonction putEnvValues remplace les désignations de variables (commençant par $) par les valeurs de ces variables. Les variables spéciales ?, #, $, * et @ sont prises en charge ; leur contenu est calculé la première fois qu’elles sont vues dans le texte du paramètre. À part ça, les paramètres fournis au shell, à indices numériques, sont pris en charge. Et les variables d’environnement classiques sont prises en charge, grâce à la fonction getenv. La fonction accepte que le nom de la variable soit entouré d’accolades. La présence d’espaces dans la valeur d’une variable ne conduit pas à découper le paramètre (c’est équivalent au comportement de Bash lorsqu’on met la désignation de la variable entre guillemets doubles).


      

La fonction putCmdsOutput remplace les commandes entre accents graves par la sortie de ces commandes. Une seule commande est exécutée à la fois, elle peut être interrompue mais pas stoppée (comportement identique à celui de Bash). Seulement 1023 caractères au maximum sont récupérés. La présence d’espaces dans la sortie ne conduit pas à découper le paramètre (c’est équivalent au comportement de Bash lorsqu’on met les accents graves et la commande entre guillemets doubles).


      

La fonction setEnvValues est la plus courte du module : elle parcourt les paramètres tant que chaque paramètre vu commence par un nom de variable correct suivi du signe =. Elle renvoie le nombre de paramètres ainsi lus.


      

Enfin, la fonction expandWildCards utilise la fonction récursive addCorrespondingPaths pour remplacer les métacaractères * et ? par les noms de fichiers/dossiers qui correspondent au motif, s’il y en a. Cette fois, le nombre de paramètres augmente potentiellement, c’est pourquoi la fonction prend en paramètre la liste de tous les paramètres, et renvoie une toute nouvelle ArgsList. La fonction fnmatch vue au TD 2 est utilisée. Si un paramètre génère plusieurs paramètres, ces derniers sont triés lexicographiquement (sinon, ils sont ordonnés n’importe comment).


      

Quelques défauts par rapport à Bash :

À l’attaque !

var=truc
echo $var
var=`echo A`
echo $var*
echo $$ $# $*
cat > truc.sh
echo $$ $# $*
echo $var2
[Ctrl+D]
var2=machin . truc.sh a b c
var2=machin sh truc.sh -s d e f
var2=machin ./Shell g h i < truc.sh
cat | var2=machin sh -s j k l
echo $var2 $# $*
[Ctrl+D]
...
      

C’est la fin ! Merci ! N’hésitez pas à poser des questions et à rapporter des anomalies !